2016-04-03 7 views
0

Sub-запрос 1:Избегайте "FileSort" на UNION РЕЗУЛЬТАТ

SELECT * from big_table 
where category = 'fruits' and name = 'apple' 
order by yyyymmdd desc 

Объясните:

table  | key   | extra 
big_table | name_yyyymmdd | using where 

Выглядит здорово!

Sub-запрос 2:

SELECT * from big_table 
where category = 'fruits' and (taste = 'sweet' or wildcard = '*') 
order by yyyymmdd desc 

Объясните:

table  | key    | extra 
big_table | category_yyyymmdd | using where 

Выглядит здорово!

Теперь, если я объединить тех, с UNION:

SELECT * from big_table 
where category = 'fruits' and name = 'apple' 

UNION 

SELECT * from big_table 
where category = 'fruits' and (taste = 'sweet' or wildcard = '*') 

Order by yyyymmdd desc 

Объясните:

table  | key  | extra 
big_table | name  | using index condition, using where 
big_table | category | using index condition 
UNION RESULT| NULL  | using temporary; using filesort 

Не так хорошо, он использует FileSort.

Это урезана версия более в комплекс запроса, вот некоторые факты о big_table:

  • big_table имеет 10M + строки
  • Там находятся 5 уникальной «категории» s
  • Там являются 5 уникального «вкус» s
  • есть около 10000 уникального «имени» s
  • есть около 10000 уникальных «ггггммдда» s
  • Я имею гр один индекс в каждом из этих полей, плюс составной idx, такой как yyyymmdd_category_taste_name, но Mysql его не использует.

ответ

0
SELECT * FROM big_table 
    WHERE category = 'fruits' 
     AND ( name = 'apple' 
      OR taste = 'sweet' 
      OR wildcard = '*') 
    ORDER BY yyyymmdd DESC 

И есть INDEX(catgory) или некоторый индекс начиная с category. Однако, если более 20% таблицы category = 'fruits', вероятно, решит игнорировать индекс и просто выполнить сканирование таблицы. (Так как вы говорите, есть только 5 категорий, я подозреваю, что оптимизатор будет справедливо сторонятся индекс.)

Или это может быть полезным: INDEX(category, yyyymmdd), в это порядка.

UNION должен был сделать вид (либо в памяти на диске, это не ясно), потому что он не смог получить строки в нужном порядке.

Комбинированный индекс INDEX(yyyymmdd, ...) может использоваться, чтобы избежать «filesort», но после yyyymmdd он не будет использовать столбцы.

При построении составного индекса начинаются с любыми столбцами WHERE по сравнению с '='.После этого вы можете добавить один диапазон или group by или order by. More details.

UNION часто является хорошим выбором для избежания медленного OR, но в этом случае потребуется три индекса

INDEX(category, name) 
INDEX(category, taste) 
INDEX(category, wildcard) 

и добавление YYyyMmDd не поможет, если вы не добавите LIMIT.

И запрос будет:

(SELECT * FROM big_table WHERE category = 'fruits' AND name = 'apple') 
UNION DISTINCT 
(SELECT * FROM big_table WHERE category = 'fruits' AND taste = 'sweet') 
UNION DISTINCT 
(SELECT * FROM big_table WHERE category = 'fruits' AND wildcard = '*') 
ORDER BY yyyymmdd DESC 

Добавление предела будет еще грязнее. Во-первых липкости yyyymmdd на конце каждого из трех составных индексов, то

(SELECT ... ORDER BY yyyymmdd DESC LIMIT 10) 
UNION DISTINCT 
(SELECT ... ORDER BY yyyymmdd DESC LIMIT 10) 
UNION DISTINCT 
(SELECT ... ORDER BY yyyymmdd DESC LIMIT 10) 
ORDER BY yyyymmdd DESC LIMIT 10 

Добавление смещение будет еще хуже.

Две другие техники - «покрытие» и «ленивый поиск» могут помочь, но я сомневаюсь.

Еще один способ - поместить все слова в одном столбце и использовать индекс FULLTEXT. Но это может быть проблематично по нескольким причинам.

+0

Еще одна вещь ... «filesort» - это не зло; сложность запроса. –

0

Это должно работать без UNION

SELECT * from big_table 
where 
    (category = 'fruits' and name = 'apple') 
    OR 
    (category = 'fruits' and (taste = 'sweet' or wildcard = '*') 
ORDER BY yyyymmdd desc; 
+0

Мой запрос был без UNION в первую очередь, однако по какой-то причине потребовалось слишком много времени, чтобы найти совпадающие строки во втором условии (подстановочный знак). –

+0

Пожалуйста, отправьте нам полный ОБЪЯВЛЕНИЕ о своем QUERY. Возможно, нет INDEX (COMPOSITE) с полевым вкусом или подстановочным знаком –

 Смежные вопросы

  • Нет связанных вопросов^_^