2013-05-29 6 views
2

Извините, что это такой специфический и, вероятно, вопрос о клише, но это действительно вызывает у меня серьезные проблемы.Почему этот запрос MySQL не использует индекс правильно?

Каждый день я должен сделать несколько сотен тысяч операторов выбора, которые выглядят как эти два (это один из примеров, но все они в значительной степени то же самое только с разными word1):

SELECT pibn,COUNT(*) AS aaa FROM research_storage1 
USE INDEX (word21pibn) 
WHERE word1=270299 AND word2=0 
GROUP BY pibn 
ORDER BY aaa DESC 
LIMIT 1000; 

SELECT pibn,page FROM research_storage1 
USE INDEX (word12num) 
WHERE word1=270299 AND word2=0 
ORDER BY num DESC 
LIMIT 1000; 

Первое утверждение быстро-как-вспышка и занимает долю секунды. Второе утверждение занимает около 2 секунд, что слишком долго, учитывая, что у меня есть сотни тысяч.

индексов являются:

word21pibn: word2, word1, pibn 
word12num: word1, word2, num 

Результаты объяснить (для обоих продлен и перегородки):

mysql> explain extended SELECT pibn,COUNT(*) AS aaa FROM research_storage1 USE INDEX (word21pibn) WHERE word1=270299 AND word2=0 GROUP BY pibn ORDER BY aaa DESC LIMIT 1000; 
+----+-------------+-------------------+------+---------------+------------+---------+-------------+------+----------+-----------------------------------------------------------+ 
| id | select_type | table    | type | possible_keys | key  | key_len | ref   | rows | filtered | Extra              | 
+----+-------------+-------------------+------+---------------+------------+---------+-------------+------+----------+-----------------------------------------------------------+ 
| 1 | SIMPLE  | research_storage1 | ref | word21pibn | word21pibn | 6  | const,const | 1549 | 100.00 | Using where; Using index; Using temporary; Using filesort | 
+----+-------------+-------------------+------+---------------+------------+---------+-------------+------+----------+-----------------------------------------------------------+ 
1 row in set, 1 warning (0.00 sec) 

mysql> explain partitions SELECT pibn,COUNT(*) AS aaa FROM research_storage1 USE INDEX (word21pibn) WHERE word1=270299 AND word2=0 GROUP BY pibn ORDER BY aaa DESC LIMIT 1000; 
+----+-------------+-------------------+------------+------+---------------+------------+---------+-------------+------+-----------------------------------------------------------+ 
| id | select_type | table    | partitions | type | possible_keys | key  | key_len | ref   | rows | Extra              | 
+----+-------------+-------------------+------------+------+---------------+------------+---------+-------------+------+-----------------------------------------------------------+ 
| 1 | SIMPLE  | research_storage1 | p99  | ref | word21pibn | word21pibn | 6  | const,const | 1549 | Using where; Using index; Using temporary; Using filesort | 
+----+-------------+-------------------+------------+------+---------------+------------+---------+-------------+------+-----------------------------------------------------------+ 
1 row in set (0.00 sec) 

mysql> explain extended SELECT pibn,page FROM research_storage1 USE INDEX (word12num) WHERE word1=270299 AND word2=0 ORDER BY num DESC LIMIT 1000; 
+----+-------------+-------------------+------+---------------+-----------+---------+-------------+------+----------+-------------+ 
| id | select_type | table    | type | possible_keys | key  | key_len | ref   | rows | filtered | Extra  | 
+----+-------------+-------------------+------+---------------+-----------+---------+-------------+------+----------+-------------+ 
| 1 | SIMPLE  | research_storage1 | ref | word12num  | word12num | 6  | const,const | 818 | 100.00 | Using where | 
+----+-------------+-------------------+------+---------------+-----------+---------+-------------+------+----------+-------------+ 
1 row in set, 1 warning (0.00 sec) 

mysql> explain partitions SELECT pibn,page FROM research_storage1 USE INDEX (word12num) WHERE word1=270299 AND word2=0 ORDER BY num DESC LIMIT 1000; 
+----+-------------+-------------------+------------+------+---------------+-----------+---------+-------------+------+-------------+ 
| id | select_type | table    | partitions | type | possible_keys | key  | key_len | ref   | rows | Extra  | 
+----+-------------+-------------------+------------+------+---------------+-----------+---------+-------------+------+-------------+ 
| 1 | SIMPLE  | research_storage1 | p99  | ref | word12num  | word12num | 6  | const,const | 818 | Using where | 
+----+-------------+-------------------+------------+------+---------------+-----------+---------+-------------+------+-------------+ 
1 row in set (0.00 sec) 

Единственное различие я вижу в том, что второе утверждение не имеет Using index в дополнительный столбец описания. Хотя это не имеет смысла, потому что индекс был разработан для этого утверждения, поэтому я не понимаю, почему он не будет использоваться.

Любая идея?

+0

Вы уверены, что этот индекс определен на столе? Из того, что я прочитал, использование индекса по-прежнему требует, чтобы индекс был явно создан в таблице. – Robbert

+0

Да, это определено на таблице, как вы можете видеть из столбца 'key' на объяснении. – Alasdair

ответ

3

Попробуйте добавить таблицу pbin и page в список word12num. Тогда вся информация, которая вам нужна для вашего запроса, будет указана в индексе, как в первом запросе.

Редактировать Я пропустил колонку pbin, которую вы выбираете; Извини за это.

Если ваш составной индекс содержит (word1, word2, num, pbin, page), тогда все в вашем втором запросе может исходить из индекса.

Если вы посмотрите на столбец Extra под вашим первым запросом EXPLAIN, один из рекламных сообщений Using index. @sebas указал на это. Это означает, что на самом деле Using index only. Это означает, что сервер может удовлетворить ваш запрос, просто обратившись к индексу, не проконсультировавшись с таблицей. Вот почему это так быстро: серверу не нужно бить головки дисков вокруг случайного доступа к таблице, чтобы получить дополнительные столбцы. Using index нет в вашем втором запросе EXPLAIN.

Столбцы, упомянутые в WHERE, приходят первыми. Затем у нас есть столбцы в ORDER BY. Наконец, у нас есть столбцы, которые вы просто SELECT ing. Зачем использовать этот конкретный порядок для столбцов в индексе? Сервер находит путь к первому элементу индекса, соответствующему SELECT, а затем может считывать индекс последовательно для удовлетворения запроса.

Действительно дорого построить и поддерживать составной индекс на большом столе. Вы рассматриваете базовый компромисс в дизайне СУБД: хотите ли вы потратить время на построение таблицы или поиск в ней вещей? Только вы знаете, лучше ли брать на себя расходы при построении стола или при поиске вещей в нем.

+1

«страница» - это выбранный столбец, поэтому он не обязательно должен находиться в индексе. – Alasdair

+2

@Alasdair: «необходимость» спорна; запрос не нуждается в странице в индексе, чтобы определить, какая строка будет выбрана, но затем «нужно» прочитать таблицу, чтобы определить значение страницы (где страница не указана в индексе). Напротив, если страница была частью индекса, запрос не «нуждался» в чтении таблицы вообще - вместо этого он мог бы получить все необходимые данные из индекса. –

+0

ОК, я этого не знал. Я попробую, спасибо. – Alasdair

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