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_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 操作。

如果这可行,那么在聚合之后进行连接。此外,考虑获得更多内存,以便整个表适合内存。

其次,如果您必须处理这种类型的数据,那么按日期对表进行分区可能被证明是一个非常有用的选项。这将允许您显着减少读取大表的开销。您必须确保可以以相同的方式阅读汇总表。

于 2013-02-05T14:55:19.757 回答
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 回答