сортировка файлов в MySQL из-за условия OR в предложении WHERE

0

У меня есть этот запрос:

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

Кто-нибудь знает, почему? Мне нужно это ИЛИ, есть ли обходной путь?

Теги:

2 ответа

0
Лучший ответ

Это имеет смысл для меня. Поведение здесь объясняется довольно хорошо:

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.

  • 0
    В этом контексте существует большая разница между 2 и (2 или 3). По сути, это вопрос того, имеют ли все выбранные вами строки общий префикс в индексе. Я добавлю к своему ответу, чтобы лучше проиллюстрировать этот момент.
  • 0
    ОК, это ясно. Спасибо за ваше объяснение :)
0

Существует обходное решение для этого, но для него потребуется версия 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

  • 0
    Не работает Он меняет «тип» на «все». Так что еще хуже :(
  • 0
    не могли бы вы объяснить?

Ещё вопросы

Сообщество Overcoder
Наверх
Меню