我有这个问题:
SELECT * FROM article
WHERE (state = 2 OR state = 3) AND category_id = 100
ORDER BY mod_date DESC
我已经定义了这个索引:
category_id_idx:
state
category_id
mod_date
当我使用EXPLAIN运行查询时,它会返回:
id: 1
select_type: SIMPLE
table: article
type: range
possible_keys: category_id_idx
key: category_id_idx
key_len: 3
ref: (NULL)
rows: 4
Extra: Using where; Using filesort
所以...它正在使用一个文件排序。但是,如果我更改WHERE删除OR并且只允许一个字段,这样:
SELECT * FROM article
WHERE state = 2 AND category_id = 100
ORDER BY mod_date DESC
然后EXPLAIN返回NO filesort:
id: 1
select_type: SIMPLE
table: article
type: ref
possible_keys: category_id_idx
key: category_id_idx
key_len: 3
ref: const,const
rows: 3
Extra: Using where
任何人都知道为什么?我需要那个OR,有解决方法吗?
答案 0 :(得分:0)
这对我有意义。这个行为很好地解释了:
http://dev.mysql.com/doc/refman/5.0/en/order-by-optimization.html
基本上,只有在将所有前面的关键部分与常量进行比较时才能避免使用filesort。由于您按kay第3部分进行排序,并将关键部分2与常量进行比较,但将关键部分3(状态)与2 OR 3进行比较,因此它不是常数,因此MySQL需要为排序执行额外的传递。
例如,考虑一下包含4个索引记录的样本集:
a) [2,100,2010-10-01]
b) [2,100,2010-10-20]
c) [3,100,2010-10-10]
d) [3,100,2010-11-01]
如果你只是在寻找状态2,那么你会想要行b,a在索引中是连续的,避免使用filesort。 如果你只是在寻找状态3,那么你会希望行d,c在索引中是连续的,避免使用filesort。
但是你要求的是状态2 OR 3,这意味着你想要在索引中不连续的行d,b,c,a。这就是需要filesort的原因。
答案 1 :(得分:0)
有一种解决方法,但它需要mysql版本5.1
FORCE {INDEX|KEY}
[{FOR {JOIN|ORDER BY|GROUP BY}] (index_list)