MySql требует много времени для оптимизации запроса без объединения - PullRequest
2 голосов
/ 28 января 2010

У нас есть простой запрос, который выглядит так:

SELECT a,b,c,d FROM table WHERE a=1 and b IN ('aaa', 'bbb', 'ccc', ...)

Нет объединений, 5000 константных значений в предложении IN.

Теперь этот запрос выполняется на очень сильном (16-ядерном) сервере за 1-20 секунд. У таблицы есть индекс на (a, b), и мы также попытались обратить индекс на (b, a). Сервер имеет тонны памяти, и никто не пишет в эту таблицу - только 5 процессов, выполняемых, выбирают, как я описал выше.

Мы провели некоторое профилирование и увидели, что некоторые запросы тратят 3,5 секунды на «JOIN :: optimize» (. \ Sql_select.cc 977). Напоминаю, что в запросах вообще не используются объединения.

Что может быть причиной такого большого времени, затрачиваемого на оптимизацию объединений в таблице без объединения?

Вот результат EXPLAIN SELECT:

id select_type table type   possible_keys key    key_len ref rows   Extra
1  SIMPLE     table range    IX_A_B       IX_A_B 65      \N  5000   Using where

Ответы [ 6 ]

5 голосов
/ 28 января 2010

Попробуйте поместить 5000 значений во временную таблицу:

declare @t table (b varchar(10))
insert into b select 'aaa'
union all select 'bbb'
union all select 'c'
....

select table.*
from table
join @t t on table.b = t.b
where table.a = 1
2 голосов
/ 28 января 2010

b IN (x, y, ...) переводится в: (b = x ИЛИ b = y ИЛИ b = ...)

это означает, что у вас есть 5000 проверок if длякаждое значение в таблице.

1 голос
/ 28 января 2010

Использование такого предложения IN также может быть объединением, поэтому оно не является полностью безлимитным.

Довольно хорошо, что у вас есть индекс для (a, b), но вам нужно задаться вопросом, как он получит значения c и d ... в конце концов, он, вероятно, будет игнорировать индекс просто сканирую всю таблицу.

Попробуйте создать индекс для (a, b, c, d ), чтобы в индексе содержались все необходимые данные. В SQL Server вы бы делали это с включенными столбцами, но я думаю, что в mysql вам нужно будет просто включить и другие. Это должно означать, что ваш запрос может перейти прямо к записям a = 1 и начать поиск записей b, соответствующих списку, а затем он получит всю необходимую информацию.

1 голос
/ 28 января 2010

Есть ли у вас индексы по полю а и особенно б?

Если вы запрашиваете помощь в оптимизации SQL, вы должны прикрепить

EXPLAIN SELECT a,b,c,d FROM table WHERE a=1 and b IN ('aaa', 'bbb', 'ccc', ...)

а без этого люди могут только догадываться.

0 голосов
/ 28 января 2010

Ваш ответ будет заключаться в рассмотрении предложений в обоих следующих ответах:
MySql долго оптимизирует запрос без объединения
MySql долго оптимизирует запрос без объединения

Кроме того, вы упомянули, что b очень избирателен; так:

Я предлагаю вам изменить порядок столбцов в вашем индексе на (b, a). Если оптимизатор сможет сузить ваши результаты быстрее, будет лучше использовать индекс. (Как правило, рекомендуется указывать наиболее селективные столбцы ранее в своих индексах; редко, если вообще когда-либо требуется отклониться от этого принципа.)

0 голосов
/ 28 января 2010
...