1

大きなテーブル(800万行以上)でグループクエリを生成しようとしています。ただし、すべてのデータを日付でグループ化する必要性を減らすことができます。私は必要な日付をキャプチャするビューを持っていますが、これはクエリを制限しますが、それほど良くはありません。最後に、フィールドを取得するために別のテーブルに参加する必要があります。

クエリ、メインテーブルでの作成、およびクエリの説明を以下に示します。

メインクエリ:

SELECT  pgi_raw_data.wsp_channel,
        'IOM' AS wsp,
        pgi_raw_data.dated,
        pgi_accounts.`master`,
        pgi_raw_data.event_id,
        pgi_raw_data.breed,
        Sum(pgi_raw_data.handle),
        Sum(pgi_raw_data.payout),
        Sum(pgi_raw_data.rebate),
        Sum(pgi_raw_data.profit)
FROM    pgi_raw_data
        INNER JOIN summary_max
                ON pgi_raw_data.wsp_channel = summary_max.wsp_channel
                        AND pgi_raw_data.dated > summary_max.race_date
        INNER JOIN pgi_accounts
                ON pgi_raw_data.account = pgi_accounts.account
GROUP   BY pgi_raw_data.event_id
ORDER   BY NULL

テーブルの作成:

 CREATE TABLE `pgi_raw_data` (
  `event_id` char(25) NOT NULL DEFAULT '',
  `wsp_channel` varchar(5) NOT NULL,
  `dated` date NOT NULL,
  `time` time DEFAULT NULL,
  `program` varchar(5) NOT NULL,
  `track` varchar(25) NOT NULL,
  `raceno` tinyint(2) NOT NULL,
  `detail` varchar(30) DEFAULT NULL,
  `ticket` varchar(20) NOT NULL DEFAULT '',
  `breed` varchar(12) NOT NULL,
  `pool` varchar(10) NOT NULL,
  `gross` decimal(11,2) NOT NULL,
  `refunds` decimal(11,2) NOT NULL,
  `handle` decimal(11,2) NOT NULL,
  `payout` decimal(11,4) NOT NULL,
  `rebate` decimal(11,4) NOT NULL,
  `profit` decimal(11,4) NOT NULL,
  `account` mediumint(10) NOT NULL,
  PRIMARY KEY (`event_id`,`ticket`),
  KEY `idx_account` (`account`),
  KEY `idx_wspchannel` (`wsp_channel`,`dated`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=latin1

これはsummary_maxに対する私の見解です:

CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW 
 `summary_max` AS select `pgi_summary_tbl`.`wsp_channel` AS 
 `wsp_channel`,max(`pgi_summary_tbl`.`race_date`) AS `race_date` 
from `pgi_summary_tbl` group by `pgi_summary_tbl`.`wsp

また、評価されたクエリ:

1   PRIMARY <derived2>  ALL                 6   Using temporary

1   PRIMARY pgi_raw_data    ref idx_account,idx_wspchannel  idx_wspchannel  
7   summary_max.wsp_channel 470690  Using where

1   PRIMARY pgi_accounts    ref PRIMARY PRIMARY 3   gf3data_momutech.pgi_raw_data.account   29  Using index

2   DERIVED pgi_summary_tbl ALL                 42282   Using temporary; Using filesort

インデックス作成に関するヘルプがあれば役立ちます。

4

2 に答える 2

0

少なくとも、次のフィールドにインデックスが必要です。

pgi_raw_data.wsp_channel,
pgi_raw_data.dated,  
pgi_raw_data.account
pgi_raw_data.event_id,
summary_max.wsp_channel, 
summary_max.race_date, 
pgi_accounts.account

一般的な (常にではありません) ルールは、並べ替え、グループ化、フィルター処理、または結合するものはすべてインデックスを持つ必要があるということです。

また:pgi_summary_tbl.wsp

また、なぜorder by nullですか?

于 2013-02-05T14:40:19.987 に答える
0

最初のことは、インデックスがあることを確認することですpgi_summary_table(wsp_channel, race_date)pgi_accounts(account). このクエリでは、生データのこれらの列にインデックスは必要ありません。

MySQL は、インデックスが最も効率的なパスではない場合でも、インデックスを使用する傾向があります。結合なしで、「完全な」クエリのパフォーマンスを調べることから始めます。

SELECT  pgi_raw_data.wsp_channel,
        'IOM' AS wsp,
        pgi_raw_data.dated,
        -- pgi_accounts.`master`,
        pgi_raw_data.event_id,
        pgi_raw_data.breed,
        Sum(pgi_raw_data.handle),
        Sum(pgi_raw_data.payout),
        Sum(pgi_raw_data.rebate),
        Sum(pgi_raw_data.profit)
FROM    pgi_raw_data
GROUP   BY pgi_raw_data.event_id

これによりパフォーマンスが向上する場合は、インデックスが不利に働いている状況にある可能性があります。特定の問題は「スラッシング」と呼ばれます。テーブルが小さすぎてメモリに収まらない場合に発生します。多くの場合、このようなテーブルを処理する最速の方法は、すべてを読み取ることです。インデックスを介してテーブルにアクセスすると、ほとんどの行で余分な I/O 操作が発生する可能性があります。

これが機能する場合は、集計の後に結合を行います。また、テーブル全体がメモリに収まるように、より多くのメモリを取得することを検討してください。

第 2 に、このタイプのデータを処理する必要がある場合、テーブルを日付で分割すると非常に便利なオプションになることがあります。これにより、大きなテーブルを読み取るオーバーヘッドを大幅に削減できます。要約表が同じように読み取れることを確認する必要があります。

于 2013-02-05T14:55:19.757 に答える