MySql拒绝使用索引

时间:2013-11-04 17:46:38

标签: 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 |                |
+------------------+-----------+------+-----+-------------------+----------------+

我的索引:

+-----------------+------------+-------------------+--------------+------------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| 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      |         |               |
+-----------------+------------+-------------------+--------------+------------------+-----------+-------------+----------+--------+------+------------+---------+---------------+

我的查询:

SELECT taskid FROM tasktransitions WHERE transitiondate>'2013-09-31 00:00:00';

给出了这个:

+----+-------------+-----------------+------+-------------------+------+---------+------+------+-------------+
| 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 |
+----+-------------+-----------------+------+-------------------+------+---------+------+------+-------------+

如果我理解了所有内容Using whereALL表示从存储引擎检索所有行并在服务器层进行过滤。这是次优的。为什么它拒绝使用索引并仅从存储引擎(innoDB)中检索请求的范围?

干杯

3 个答案:

答案 0 :(得分:3)

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

通过类比,这就是书的索引不包含像“the”这样的非常常见的单词的原因 - 因为在索引中查找单词并找到页面列表会浪费时间数字是一个很长的列表,甚至书中的每一页。简单地阅读书籍封面会更有效率。

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

您可以给MySQL一个提示,以说服表扫描费用过高,因此更有可能使用该索引。这通常不是必需的,但您可以这样做:

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

答案 1 :(得分:0)

以防万一,它可以帮助别人。

我有一个带有varchar列_id(长整数编码为字符串)的表。我为此列添加了索引,但是查询仍然很慢。我正在执行此查询:

select * from table where (_id = 2221835089) limit 1

我意识到_id列不是作为字符串生成的(作为数据库框架,我是Laravel)。好吧,如果在where子句中使用正确的数据类型执行查询,那么一切都将像一个符咒一样

select * from table where (_id = '2221835089') limit 1

答案 2 :(得分:0)

我是 MySQL 8.0 新手,已经完成了 2 个简单的教程,只有两个主题对我没有用,其中之一是索引。我阅读了标有“2 个答案”的部分,发现使用 在该部分末尾建议的声明似乎击败了 以下原始 USE INDEXFORCE INDEX 语句的目的。建议的语句类似于使用 WHEREUSE INDEX 通过 FORCE INDEX 语句而不是 MySQL 对表进行排序。它有效,但在我看来它与使用自然的 USE INDEXFORCE INDEX 不同。有谁知道为什么 MySQL 会忽略我在 Lname 列上索引 10 行表的简单请求?

<头>
字段 类型 默认 额外
身份证 内部 没有 PRI 自动增量
名字 varchar(20) 没有
名字 varchar(20) 没有
城市 varchar(15) 没有
出生日期 日期 没有
CREATE INDEX idx_Lname ON TestTable (Lname);
SELECT * FROM TestTable USE INDEX (idx_Lname);
SELECT * From Testtable FORCE INDEX (idx_LastFirst);