2013-11-04 44 views
3

我是新来查询优化,所以我接受我不明白的一切,但我不明白为什么即使这个简单的查询没有按预期优化。MySql拒绝使用索引

我的表:

+------------------+-----------+------+-----+-------------------+----------------+ 
| 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)中检索请求的范围?

干杯

+0

你试过强迫索引了吗? – Kermit

+0

@FreshPrinceOfSO不,但我为什么要?我希望预处理器足够聪明,给定高基数以自动选择索引。 – Tin

+0

可能因为索引是无用的。 – Kermit

回答

3

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

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

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

您可以给MySQL一个提示,说服它表扫描会过于昂贵,所以它会更有可能使用该指数。这通常不是必需的,但你可以这样做:

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

谢谢@Bill,这似乎确实是原因。查询返回987行中的186行。当我改变日期,只有10行匹配时,它使用索引。我仍然不明白的是,当使用密钥时,使用where'是解释的输出。 – Tin

+0

'使用where'只是表示SQL执行正在应用一个条件来过滤掉一些行。换句话说,并不是所有被检查的行都被返回。 –

+0

我正在读Baron Schwartz的高性能MySql一书。根据这本书“使用where”意味着从存储引擎读取的行太多,更好的索引可能会解决这个问题。但我不明白如何。 – Tin