当我在where子句中使用索引时,我不能理解为什么下面的MySQL查询变慢了。让我抓狂的那一栏叫做删除。该表包含4.8M行。
查询:
SELECT SQL_NO_CACHE SUM(amount)/100 FROM transactions WHERE (type="Payment" or type="Refund") and deleted is NULL
当列是索引时,查询花费的时间略高于11秒,当列没有索引时,查询耗时为3秒,或者当我使用USE INDEX()时,它会告诉优化器不要使用任何索引。
MySQL版本5.6,在AWS Aurora db.r5.xlarge (4CPU/32 in )中测试
表结构:
id int(11) NOT NULL, type enum('Charge','Payment','Refund','Credit Adjustment','Debit Adjustment','Transfer') NOT NULL, amount int(11) NOT NULL, deleted datetime DEFAULT NULL, deleted_by int(11) DEFAULT NULL ENGINE=InnoDB DEFAULT CHARSET=utf8; ADD KEY type (type), ADD KEY deleted (deleted)
如果有任何线索,我将不胜感激!
发布于 2019-10-09 18:03:41
我使用"explain“来检查上面的查询是否可以使用索引。因此,索引对" or“运算符或"IN”都不起作用,所以我认为"UNION“是更好的选择。我认为你不需要为"deleted“列添加索引,因为它不能很好地工作。
IN运算符的"explain“结果:

OR运算符的"explain“结果:

联合“”结果:

“已删除”列的索引不起作用:

发布于 2019-10-09 04:57:30
(编辑:显然,对于这种特殊情况,这是错误的。只有当涉及不同fields....or的OR条件创建了一个范围检查,以防止在索引中更深入地利用字段时,这个答案才适用。有关详细信息,请参阅注释。)
当使用OR条件时,MySQL不能很好地利用索引。通常,您可以加快查询速度,例如
SELECT a FROM b WHERE y = n1 OR y = n2通过将其扩展为像这样的联盟
SELECT a FROM b WHERE y = n1
UNION
SELECT a FROM b WHERE y = n2我听说最近的版本使以y IN (n1, n2)形式表示的条件变得更有效率,但我在过去几年的主要工作是在MS中,所以我不能说它有多大的改进。
这甚至可以用在直接求和的情况下,并进行更多的扩展……
SELECT SUM(subt)
FROM (
SELECT SUM(amount)/100 AS subt FROM transactions WHERE type="Payment" and deleted is NULL
UNION
SELECT SUM(amount)/100 AS subt FROM transactions WHERE type="Refund" and deleted is NULL
) AS subq发布于 2019-10-09 20:55:16
我想我想出了一个合乎逻辑的想法,为什么使用索引列会导致延迟。问题应该出在该列的数据中,尤其是其唯一值的高度畸形分布-分别是二进制三个节点。它包含4.8M行和30K行,其中4.8M行具有相同的空值,而30K行具有3K唯一值。
https://stackoverflow.com/questions/58293713
复制相似问题