我有一个包含近4.000.000行的MySQL表,其中包含超过100.000名员工的收入交易。
其中涉及三列:
我想做的事情对我来说似乎很简单。我想对每个雇员分组的所有收入发生总数进行汇总,并按一种类型进行过滤。 为此,我使用了以下代码:
SELECT
SUM(`value`) AS `SumofValue`,
`type`,
`EmployeeID`
FROM
`Revenue`
GROUP BY `EmployeeID`
HAVING `type` = 'X'
结果应该是这样的:
SUM TYPE EMPLOYEE ID
R$ 250,00 X 250000008377
R$ 5.000,00 X 250000004321
R$ 3.200,00 X 250000005432
R$ 1.600,00 X 250000008765
....
但是,这需要很长时间。我决定使用LIMIT命令将结果限制为仅1.000行,并且它可以正常工作,但是如果我要对整个表进行操作,则根据我的预测大约需要1小时。对于我来说似乎不太需要的东西,这似乎花了太多时间(但是我假设我可能是错的)。不仅如此,这还只是我打算将来进行的更为复杂的查询的第一步,在该查询中,除了员工ID之外,我还将按雇主ID分组(一个人可以从多个雇主)。
有什么方法可以优化这个?我的代码有什么问题吗?是否有任何秘密途径可以提高此操作的速度?我是否也应该为收入值的列编制索引?如果这是MySQL的限制,是否有任何选项可以更好地解决此问题? 我真的很感谢您。
预先感谢
披露:这是一个开放的政府数据库。所有这些数据均合法地向公众开放。
答案 0 :(得分:1)
首先,使用WHERE
而不是HAVING
短语查询-在进行汇总之前过滤 :
SELECT SUM(`value`) AS `SumofValue`,
MAX(type) as type,
EmployeeID
FROM Revenue r
WHERE `type` = 'X'
GROUP BY EmployeeID;
接下来,尝试使用以下索引:(type, EmployeeId, value)
。至少,这是查询的覆盖索引。 MySQL(取决于版本)可能足够聪明,也可以将其用于聚合。
答案 1 :(得分:0)
根据您定义的模式,为什么要使用VARCHAR数据类型作为Employee ID和Type。
您可以使用1-> X,2-> Y ...为Type创建引用表,因此基本上整数引用将用于事务表中的类型。
只需创建一个下面的虚拟表,然后执行耗时数小时的相同查询即可。即使您也会看到执行计划的重大变化。
CREATE TABLE test_transaction
(
Employee_ID BIGINT,
Type SMALLINT,
Income DECIMAL(10,2)
)
在Employee_ID和Type列上创建单独的索引。