2013-02-05 91 views
1

我想在一个大型的表(超过800万行)上生成一个组查询。不过,我可以减少按日期分组所有数据的需要。我有一个观点,捕捉我需要的日期,这限制了查询BU它并不好多了。 最后,我需要加入到另一张桌子来选择一个字段。GROUP BY查询 - 为什么这么慢

我正在显示查询,主表上的创建和查询下面的解释。

主查询:

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 

索引的任何帮助都会有所帮助。

+0

“pgi_summary_table”上的索引是什么? – Dancrumb

回答

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

+0

我读空订阅是有效的,因为如果它不存在查询试图排序它本身,我不需要。 将添加这些索引 - event_id是一个主键,因此不确定需要一个 – user1479891

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

如果这个工作,然后做聚合后的连接。另外,考虑获得更多的内存,所以整个桌子将适合内存。第二,如果您必须处理这种类型的数据,那么按日期对表进行分区可能证明是一个非常有用的选项。这将允许您显着减少阅读大表的开销。您必须确保汇总表可以以相同的方式读取。