MySql拒绝使用索引

Tin*_*Tin 6 mysql indexing explain

我是查询优化的新手,所以我承认我还不了解所有内容,但我不明白为什么即使这个简单的查询也没有按预期进行优化。

我的桌子:

+------------------+-----------+------+-----+-------------------+----------------+
| Field            | Type      | Null | Key | Default           | Extra          |
+------------------+-----------+------+-----+-------------------+----------------+
| tasktransitionid | int(11)   | NO   | PRI | NULL              | auto_increment |
| taskid           | int(11)   | NO   | MUL | NULL              |                |
| transitiondate   | timestamp | NO   | MUL | CURRENT_TIMESTAMP |                |
+------------------+-----------+------+-----+-------------------+----------------+
Run Code Online (Sandbox Code Playgroud)

我的索引:

+-----------------+------------+-------------------+--------------+------------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table           | Non_unique | Key_name          | Seq_in_index | Column_name      | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+-----------------+------------+-------------------+--------------+------------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| tasktransitions |          0 | PRIMARY           |            1 | tasktransitionid | A         |         952 |     NULL | NULL   |      | BTREE      |         |               |
| tasktransitions |          1 | transitiondate_ix |            1 | transitiondate   | A         |         952 |     NULL | NULL   |      | BTREE      |         |               |
+-----------------+------------+-------------------+--------------+------------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
Run Code Online (Sandbox Code Playgroud)

我的查询:

SELECT taskid FROM tasktransitions WHERE transitiondate>'2013-09-31 00:00:00';
Run Code Online (Sandbox Code Playgroud)

给出这个:

+----+-------------+-----------------+------+-------------------+------+---------+------+------+-------------+
| id | select_type | table           | type | possible_keys     | key  | key_len | ref  | rows | Extra       |
+----+-------------+-----------------+------+-------------------+------+---------+------+------+-------------+
|  1 | SIMPLE      | tasktransitions | ALL  | transitiondate_ix | NULL | NULL    | NULL | 1082 | Using where |
+----+-------------+-----------------+------+-------------------+------+---------+------+------+-------------+
Run Code Online (Sandbox Code Playgroud)

如果我正确理解所有内容Using where,则ALL意味着所有行都是从存储引擎检索并在服务器层过滤的。这是次优的。为什么它拒绝使用索引而只从存储引擎(innoDB)检索请求的范围?

干杯

Bil*_*win 11

如果 MySQL 估计会选择表的很大一部分,并且它认为在这些情况下表扫描实际上更有效,则它不会使用索引。

打个比方,这就是一本书的索引不包含像“the”这样非常常见的单词的原因——因为在索引中查找单词并找到页码列表是浪费时间。很长的清单,甚至是书中的每一页。简单地从头到尾地阅读这本书会更有效率。

我的经验是,如果查询的搜索条件与表的 20% 以上匹配,MySQL 中就会发生这种情况,这通常是正确的交叉点。根据数据类型、表大小等,可能会有一些变化。

你可以给 MySQL 一个提示,让它相信表扫描的成本会高得令人望而却步,因此它更有可能使用索引。这通常不是必需的,但您可以这样做:

SELECT taskid FROM tasktransitions FORCE INDEX (transitiondate_ix)
WHERE transitiondate>'2013-09-31 00:00:00';
Run Code Online (Sandbox Code Playgroud)

  • “使用where”仅仅意味着SQL执行正在应用一个条件来过滤掉一些行。换句话说,并非返回所有检查的行。 (2认同)