我正在尝试在一个大表(超过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
任何有关索引的帮助都会有所帮助。
答案 0 :(得分: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
?
答案 1 :(得分: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操作。
如果这样做,那么在聚合之后进行连接。另外,考虑获得更多内存,因此整个表格将适合内存。
其次,如果你必须处理这种类型的数据,那么按日期对表进行分区可能是一个非常有用的选择。这将允许您显着减少读取大表的开销。您必须确保可以以相同的方式读取摘要表。