首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用索引时,MySQL查询速度会变慢

使用索引时,MySQL查询速度会变慢
EN

Stack Overflow用户
提问于 2019-10-09 04:32:06
回答 4查看 83关注 0票数 0

当我在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)

如果有任何线索,我将不胜感激!

EN

回答 4

Stack Overflow用户

发布于 2019-10-09 18:03:41

我使用"explain“来检查上面的查询是否可以使用索引。因此,索引对" or“运算符或"IN”都不起作用,所以我认为"UNION“是更好的选择。我认为你不需要为"deleted“列添加索引,因为它不能很好地工作。

IN运算符的"explain“结果:

OR运算符的"explain“结果:

联合“”结果:

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

票数 1
EN

Stack Overflow用户

发布于 2019-10-09 04:57:30

(编辑:显然,对于这种特殊情况,这是错误的。只有当涉及不同fields....or的OR条件创建了一个范围检查,以防止在索引中更深入地利用字段时,这个答案才适用。有关详细信息,请参阅注释。)

当使用OR条件时,MySQL不能很好地利用索引。通常,您可以加快查询速度,例如

代码语言:javascript
复制
SELECT a FROM b WHERE y = n1 OR y = n2

通过将其扩展为像这样的联盟

代码语言:javascript
复制
SELECT a FROM b WHERE y = n1
UNION 
SELECT a FROM b WHERE y = n2

我听说最近的版本使以y IN (n1, n2)形式表示的条件变得更有效率,但我在过去几年的主要工作是在MS中,所以我不能说它有多大的改进。

这甚至可以用在直接求和的情况下,并进行更多的扩展……

代码语言:javascript
复制
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
票数 0
EN

Stack Overflow用户

发布于 2019-10-09 20:55:16

我想我想出了一个合乎逻辑的想法,为什么使用索引列会导致延迟。问题应该出在该列的数据中,尤其是其唯一值的高度畸形分布-分别是二进制三个节点。它包含4.8M行和30K行,其中4.8M行具有相同的空值,而30K行具有3K唯一值。

  1. 当删除索引用于查找NULL值时,它对减少MySQL将进一步处理的行子集没有显着影响,但增加了处理二叉树索引的大量开销活动。我怀疑在没有索引求和操作的情况下,即使进行全表扫描,它的性能也超过了索引可以提供的减少行子集的好处,但代价是显著的索引开销。
  2. 删除的列中的数据提升了删除的索引基数,并使优化器优先于基数只有10的类型列索引。如果两列中的值分布是正常的,那么合理的做法是优先使用基数较高的列,并产生较小的子集以供进一步处理。然而,这个删除的列值的分布非常不符合NULL值。以与上述相同的方式,使用deleted索引查找NULL值会增加大量开销,但对性能影响不大,会阻止使用其他更相关的索引,从而导致结果延迟。
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/58293713

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档