2016-12-28 8 views
0

У меня проблема с тем, где порядок заказа.Почему порядок выполнения предложений о выполнении?

Я видел от других вопросов, порядок, где положение не влияет на производительность запросов SQL, но мои изменения производительности запросов, как я могу изменить порядок.

select sql_no_cache idx 
from rr 
where (timestamp >= '2016-11-28' and timestamp <= '2016-12-28') 
    and ((select name from xx where midx=rr.midx) like 'test' 

быстрее, чем

select sql_no_cache idx 
from rr 
where ((select name from xx where midx=rr.midx) like 'test' 
    and (timestamp >= '2016-11-28' and timestamp <= '2016-12-28') 

таблицы Гг имеет индекс 'IDX', 'midx' и 'временную метку'

Любая идея, почему ??

+1

Поскольку оптимизатор запросов не является совершенным. –

ответ

0

Если вся информация легко доступна, оптимизатор будет смотреть на все части WHERE, а затем решить, какие части, чтобы сделать первый. Когда заказ семантически неуместен, заказ игнорируется.

Одно правило, на самом деле предназначены в качестве оптимизации, является то, что MATCH...AGAINST будет выполняться первым.

Однако в некоторых ситуациях (например, у вас) Оптимизатор не имеет понятия, какая часть будет лучше. Поэтому он отпал, надеясь, что пользователь лучше знает; короткое замыкание может существенно повлиять на производительность.

Скобки не контролируют порядок, только семантику. (Часто они просто лишние.)

(select name from xx where midx=rr.midx) like 'test' может быть превращены в EXISTS (SELECT * FROM xx WHERE midx=rr.midx AND name = 'test') - Оптимизатор действительно понимает EXISTS(...) и делает работу лучше, чем ваши композиции.

"таблица р-р имеет индекс 'IDX', 'midx' и '' метки времени" - неоднозначное. Это три индекса из 1 столбца? Или один трехкомпонентный составной индекс? (Существует большая разница.) Это желательно:

rr: INDEX(timestamp) 
xx: INDEX(midx, name) 
+0

Отличный ответ! Я попробую с EXISTS. Благодаря! – nolsigan

+0

Я предлагаю использовать IN вместо EXISTS, с тех пор оптимизатор может выбрать преобразование SEMIJOIN и преобразовать подзапрос в соединение. Другими словами, что-то вроде: «SELECT idx FROM rr WHERE timestamp BETWEEN '2016-11-28' AND '2016-12-28' И midx IN (SELECT midx FROM xx WHERE name = 'test'). предложенный Риком, по-прежнему будет полезен. – oysteing

+0

Оптимизация semijoin не была добавлена ​​до 5.6.10 (или, может быть, позже). @nolsigan - какая версия вы используете? –

0

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

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

This SO has some info on this.

And also this one, marked as duplicate as the former.

+0

Благодарим вас за ответ. Не могли бы вы объяснить немного более конкретно? Я понял, что sub select выполняется только тогда, когда условие timestamp истинно для первого запроса, но почему не для второго запроса? Не следует ли оптимизатору запускать сканирование индекса по метке времени независимо от порядка заказа? – nolsigan

+0

«Почему» - это философская проблема. Проблема в том, что у вас действительно философский? – Strawberry

+0

Хм .. Я так не думаю. Я просто хочу быть уверенным, должен ли я учитывать, где порядок заказов каждый раз, когда я пытаюсь написать sql-запрос или просто оптимизировать оптимизацию, что он выполнит эту работу для меня. – nolsigan