Оптимизация: Where перед Union
От: Буравчик Россия  
Дата: 19.09.18 18:00
Оценка:
В таблицах TableA и TableB есть индексы по полю 'a'.
Mysql не смог оптимизировать такой запрос:

SELECT a, t
FROM (
    SELECT a, x as t FROM TableA
    UNION
    SELECT a, y as t FROM TableB)
WHERE a < :p1 AND a > :p2


Вроде ж понятно, что операцию WHERE лучше применить сначала к TableA и TableB (используя индексы), а потом уже делать UNION.

Если ему явно указать WHERE для каждой таблицы, то все работает быстро.
SELECT a, t
FROM (
    SELECT a, x as t FROM TableA WHERE a < :p1 AND a > :p2
    UNION
    SELECT a, y as t FROM TableB WHERE a < :p1 AND a > :p2)


Не ожидал такого. Это нормально для оптимизатора БД не разобраться в этой ситуации?
Best regards, Буравчик
Отредактировано 19.09.2018 18:01 Буравчик . Предыдущая версия .
Re: Оптимизация: Where перед Union
От: Sharov Россия  
Дата: 19.09.18 18:15
Оценка:
Здравствуйте, Буравчик, Вы писали:

Б>
Б>SELECT a, t
Б>FROM (
Б>    SELECT a, x as t FROM TableA
Б>    UNION
Б>    SELECT a, y as t FROM TableB)
Б>WHERE a < :p1 AND a > :p2
Б>


Б>Вроде ж понятно, что операцию WHERE лучше применить сначала к TableA и TableB (используя индексы), а потом уже делать UNION.


А вот непонятно. Where по правилам синтаксиса относится к последнему select, а не ко всем. Что логично, ибо как отделить общий для всех where от специфичного для таблицы?
Кодом людям нужно помогать!
Re: Оптимизация: Where перед Union
От: Слава  
Дата: 19.09.18 18:19
Оценка: +1
Здравствуйте, Буравчик, Вы писали:

Б>Mysql не смог оптимизировать такой запрос:

Б>Не ожидал такого. Это нормально для оптимизатора БД не разобраться в этой ситуации?

Для MySql нормально. Потому что MySql.
Re: Оптимизация: Where перед Union
От: night beast СССР  
Дата: 20.09.18 06:22
Оценка:
Здравствуйте, Буравчик, Вы писали:

Б>В таблицах TableA и TableB есть индексы по полю 'a'.

Б>Mysql не смог оптимизировать такой запрос:

Б>Вроде ж понятно, что операцию WHERE лучше применить сначала к TableA и TableB (используя индексы), а потом уже делать UNION.


Б>Если ему явно указать WHERE для каждой таблицы, то все работает быстро.


если UNION на UNION ALL заменить, ничего не поменяется?
Re[2]: Оптимизация: Where перед Union
От: Olaf Россия  
Дата: 20.09.18 07:10
Оценка: +4
Здравствуйте, Sharov, Вы писали:

S>А вот непонятно. Where по правилам синтаксиса относится к последнему select, а не ко всем. Что логично, ибо как отделить общий для всех where от специфичного для таблицы?


В данном случае автор использует derived table, т.е. вложенный запрос, заключенный в круглые скобки (...) Именно поэтому where относится ко всему запросу, а не только к последнему после union.
Re: Оптимизация: Where перед Union
От: BlackEric http://black-eric.lj.ru
Дата: 20.09.18 07:10
Оценка:
Здравствуйте, Буравчик, Вы писали:

Б>Не ожидал такого. Это нормально для оптимизатора БД не разобраться в этой ситуации?


Оптимизатор MySQL всегда считался слабым. Какая у вас версия?
https://github.com/BlackEric001
Re: Оптимизация: Where перед Union
От: Olaf Россия  
Дата: 20.09.18 07:18
Оценка:
Здравствуйте, Буравчик, Вы писали:

Б>Не ожидал такого. Это нормально для оптимизатора БД не разобраться в этой ситуации?


Все определяется конкретной СУБД. В MySQL это реализовано описанным вами способом, а SQL Server например, в независимости от места нахождения условий, сначала выполнит поиск, а потом объединит данные. Проверенный факт.
Re: Оптимизация: Where перед Union
От: Буравчик Россия  
Дата: 20.09.18 10:00
Оценка:
Здравствуйте, Буравчик, Вы писали:

Б>Не ожидал такого. Это нормально для оптимизатора БД не разобраться в этой ситуации?


В общем, как-то влияет NULL

SELECT table.m 
FROM (
    SELECT m, NULL AS m2 FROM table1 
    UNION 
    SELECT m, m2 FROM table2) AS table
WHERE table.m = :value;


Для table1 применяется индекс, а для table2 — нет. Интересно...
Индекс построен по полю m (+еще несколько полей), поле m2 в индексе отсутствует
Best regards, Буравчик
Отредактировано 20.09.2018 10:11 Буравчик . Предыдущая версия . Еще …
Отредактировано 20.09.2018 10:10 Буравчик . Предыдущая версия .
Отредактировано 20.09.2018 10:02 Буравчик . Предыдущая версия .
Re[2]: Оптимизация: Where перед Union
От: Буравчик Россия  
Дата: 20.09.18 10:04
Оценка:
Здравствуйте, BlackEric, Вы писали:

BE>Оптимизатор MySQL всегда считался слабым. Какая у вас версия?


Версия 5.7
Best regards, Буравчик
Re[2]: Оптимизация: Where перед Union
От: Буравчик Россия  
Дата: 20.09.18 10:05
Оценка:
Здравствуйте, night beast, Вы писали:

NB>если UNION на UNION ALL заменить, ничего не поменяется?


Нет, на использование индексов не повлияло
Best regards, Буравчик
Re[2]: Оптимизация: Where перед Union
От: Olaf Россия  
Дата: 20.09.18 10:28
Оценка:
Здравствуйте, Буравчик, Вы писали:

Б>Для table1 применяется индекс, а для table2 — нет. Интересно...

Б>Индекс построен по полю m (+еще несколько полей), поле m2 в индексе отсутствует

Зависит от вашей структуры и данных. Но предположу, что СУБД решила, что для получения полей m и m2 выгоднее сканирование всей таблицы, чем поиск по индексу построенному по m и уточняющие запросы для извлечения m2 для каждой записи из m. Возможно, необходимо создать покрывающий индекс, который основывался бы на полях m и m2. В SQL Server есть удобный механизм индексов со включенными столбцами. В MySQL насколько я знаю аналога нет.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.