У меня есть этот запрос:
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
Кто-нибудь знает, почему? Мне нужно это ИЛИ, есть ли обходной путь?
Это имеет смысл для меня. Поведение здесь объясняется довольно хорошо:
http://dev.mysql.com/doc/refman/5.0/en/order-by-optimization.html
По сути, fileort можно избежать только при сравнении всех предыдущих ключевых частей с константами. Поскольку вы заказываете kay part 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, которые являются consective в индексе, избегая fileort. Если вы просто искали состояние 3, тогда вам нужны строки d, c, которые являются consective в индексе, избегая файлового управления.
Но то, что вы просите, это состояние 2 ИЛИ 3, что означает, что вам нужны строки d, b, c, a, которые не являются последовательными в индексе. Для этого требуется файл filesport.
Существует обходное решение для этого, но для него потребуется версия mysql 5.1
FORCE {INDEX|KEY}
[{FOR {JOIN|ORDER BY|GROUP BY}] (index_list)
см. здесь http://dev.mysql.com/doc/refman/5.1/en/index-hints.html