查询mysql值的范围时如何索引

时间:2013-01-10 11:08:28

标签: mysql indexing

我有一个SQL查询

 SELECT level, data, string, soln, uid 
 FROM user_data 
 WHERE level = 10 AND (timetaken >= 151 AND timetaken <= 217) AND uid != 1
 LIMIT 8852, 1;

从一个包含150万个条目的表中获取。

我已使用

编入索引
alter table user_data add index a_idx (level, timetaken, uid); 

所以我面临的问题是在某些情况下查询需要超过30秒,在某些情况下查询时间小于0.01秒。

此处的索引是否存在任何问题。

编辑: 添加了解释查询详细信息

+----+-------------+------------------+-------+---------------+------------+---------+------+-------+--------------------------+
| id | select_type | table            | type  | possible_keys | key        | key_len | ref  | rows  | Extra                    |
+----+-------------+------------------+-------+---------------+------------+---------+------+-------+--------------------------+
|  1 | SIMPLE      | user_data | range | a_idx    | a_idx | 30      | NULL | 24091 | Using where; Using index |
+----+-------------+------------------+-------+---------------+------------+---------+------+-------+--------------------------+

表格中的数据字段是文本字段。在大多数情况下,它的长度大于255个字符。这会导致问题吗?

2 个答案:

答案 0 :(得分:0)

首先,您应该尝试使用EXPLAIN获取此查询的执行计划:

 EXPLAIN SELECT level, data, string, soln, uid 
 FROM user_data 
 WHERE level = 10 AND (timetaken >= 151 AND timetaken <= 217) AND uid != 1
 LIMIT 8852, 1;

这是关于此主题的一个很好的幻灯片: http://www.slideshare.net/phpcodemonkey/mysql-explain-explained

尝试添加不同的索引:

  • 一个关于uid和关卡
  • 一个单独的timetaken

答案 1 :(得分:0)

问题在于高偏移量。为了选择8853rd结果,MySQL必须在此之前扫描所有8852行。

顺便说一下,使用没有订单的限制可能会导致意外结果。

为了加快具有高偏移量的查询,您应该转到since..until分页策略