Mysql 分组查询-为什么这么慢
我试图在一个大表(超过800万行)上生成一个组查询。但是,我可以减少按日期分组所有数据的需要。我有一个视图可以捕获我需要的日期,这限制了查询,但这并不是更好。 最后,我需要连接到另一个表以拾取字段 我将在下面显示查询、主表上的create和查询解释 主要查询:Mysql 分组查询-为什么这么慢,mysql,group-by,Mysql,Group By,我试图在一个大表(超过800万行)上生成一个组查询。但是,我可以减少按日期分组所有数据的需要。我有一个视图可以捕获我需要的日期,这限制了查询,但这并不是更好。 最后,我需要连接到另一个表以拾取字段 我将在下面显示查询、主表上的create和查询解释 主要查询: SELECT pgi_raw_data.wsp_channel, 'IOM' AS wsp, pgi_raw_data.dated, pgi_accounts.`master`,
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
1个主节点全部6个使用临时节点
1个主pgi_原始_数据参考idx_帐户,idx_WSP通道idx_WSP通道
7总结\u max.wsp\u通道470690使用何处
1个主要pgi_账户参考主要3个gf3data_momutech.pgi_raw_data.account 29使用索引
2个衍生pgi_摘要_tbl所有42282个使用临时文件;使用文件排序
任何有关索引的帮助都会有所帮助。至少您需要这些字段的索引:
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\u summary\u tbl.wsp
另外,为什么要按null排序?第一件事是确保在
pgi_摘要_表(wsp_频道,比赛日期)
和pgi_帐户(帐户)上有索引。
对于此查询,您不需要原始数据中这些列的索引
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操作
如果这样做有效,那么在聚合之后进行连接。另外,考虑更多内存,这样整个表就可以放入内存中。
其次,如果必须处理这种类型的数据,那么按日期对表进行分区可能是一个非常有用的选项。这将允许您显著减少读取大表的开销。您必须确保汇总表可以以相同的方式读取。pgi_summary_table上的索引是什么??我按null读取排序是有效的,就像它不在那里一样。查询尝试自行排序,而我不需要它。将添加这些索引-event_id是主键,因此不确定是否需要