【问题标题】:MySQL Index sometimes not being usedMySQL 索引有时不被使用
【发布时间】:2017-08-09 13:35:51
【问题描述】:

我有一个包含 150k 行数据的表,我有一个带有 UNIQUE INDEX 的列,它的类型为 VARCHAR(10) 并存储 10 位数的帐号。

现在每当我查询时,就像一个简单的:

SELECT * FROM table WHERE account_number LIKE '0103%'

结果超过 30,000 行,当我对查询运行 EXPLAIN 时,它显示没有使用 INDEX。

但是当我这样做时:

SELECT * FROM table WHERE account_number LIKE '0104%'

它产生 4,000+ 行,使用了 INDEX。

谁能解释一下?

I'm using MySQL 5.7 Percona XtraDB.

【问题讨论】:

  • 30k+/150k > 20% 我猜做表扫描会更快。
  • 为什么使用 4k 行索引?但它小于 30k。
  • Why with 4k rows, index is still not being used? vs It results 4,000+ ROWS, with the INDEX used. 请决定
  • 因此,如果数据库引擎知道查询何时匹配 x 条目,它无论如何都必须遍历索引,那么为什么不直接使用它而不是在使用索引后进行全表扫描!?对我来说没有意义,但我不确定 percona 是如何工作的。
  • 对不起,我提醒is used

标签: mysql percona


【解决方案1】:

30k+/150k > 20%,我猜做表扫描会更快。来自8.2.1.19 Avoiding Full Table Scans

MySQL 使用全表扫描来解析查询时,EXPLAIN 的输出在 type 列中显示 ALL。 这通常发生在以下情况下:

您正在通过另一列使用具有低基数的键(许多行与键值匹配)。 在这种情况下,MySQL 假设通过使用键,它可能会进行多次键查找,并且表扫描会更快。

如果您不需要所有值,请尝试使用:

SELECT account_number FROM table WHERE account_number LIKE '0103%'

而不是SELECT *。然后您的索引将成为覆盖索引,优化器应该始终使用它(只要 WHERE 条件是 SARGable)。

【讨论】:

  • 谢谢,我也是这么想的,索引也显示在 possible_keys 但没有被使用,我想我不应该质疑优化器。
  • @JohnPangilinan 优化器并不总是正确的。有时它会产生非常愚蠢的计划。
【解决方案2】:

大多数数据库使用B树进行索引。在这种情况下,数据库优化器不使用索引,因为它在没有索引的情况下扫描速度更快。就像@lad2025 解释的那样。

您的数据库列是唯一的,我认为您的索引基数很高。但是由于您的查询使用 like 过滤器,因此数据库优化器会决定您选择不使用索引。

您可以使用 try force index 来查看结果。您使用具有唯一索引的 varchar。我会选择另一种数据类型或更改您的索引类型。如果您的表格仅包含数字,请将其更改为数字。这将有助于优化您的查询。

在某些情况下当你不得不使用like时你可以使用全文索引。

如果您在优化查询和表格方面需要帮助。向我们提供更多信息以及您想从表中获取哪些信息。

【讨论】:

    【解决方案3】:

    lad2025 是正确的。数据库正在尝试进行智能优化。

    基准测试:

    SELECT * FROM table FORCE INDEX(table_index) WHERE account_number LIKE '0103%'  
    

    看看谁更聪明 :-) 您可以随时尝试质疑优化器。这就是索引提示的用途...
    https://dev.mysql.com/doc/refman/5.7/en/index-hints.html

    【讨论】:

      猜你喜欢
      • 2017-12-03
      • 1970-01-01
      • 2018-08-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-01-28
      相关资源
      最近更新 更多