Vertica SQL: «или» в соединении приводит к огромному замедлению? - PullRequest
0 голосов
/ 28 апреля 2018

У меня есть запрос типа

select count(distinct tab1.id)
from tab1 join tab2 on tab1.email = tab2.email_a

но когда я изменяю его на

select count(distinct tab1.id)
from tab1 join tab2 on tab1.email = tab2.email_a or tab1.email = tab2.email_b

тогда вдруг это как-то дико неэффективно. Я знаю, что могу написать запрос, используя два оператора соединения, но что именно Vertica делает во втором операторе, чтобы сделать его таким ужасным?

Ответы [ 3 ]

0 голосов
/ 08 мая 2018

Я бы ожидал, что предикат OR будет работать хуже, независимо от того, какая СУБД, на самом деле:

Оптимизированная операция JOIN будет - по крайней мере обычно - полагаться на физический дизайн (индексы в других базах данных, проектирование проекций в Vertica), который может поддерживать это соединение - хотя бы частично.

Но это выходит из окна, как только вы применяете какое-либо выражение к любой из функций объединения перед сравнением - и это включает CAST, функции, математические операции и, в этом отношении, логические операции, такие как OR.

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

Следовательно, я бы ожидал, что оптимизатор выберет неоптимальный план ...

@ Hanmyo - вы можете найти способ выполнить объяснение по запросу, который вы намереваетесь - один раз, один раз без ИЛИ в предикате, чтобы мы могли проиллюстрировать различия?

Приветствия - Марко

0 голосов
/ 13 мая 2018

Если вы добавите ключевое слово «объяснять» перед каждым из ваших утверждений по очереди, то вы увидите план запроса для каждого из них. Показанные числа затрат показывают относительную сложность выполнения каждой части запроса. Таким образом, в той части, где вы видите, что последняя имеет более высокие затраты, чем это, вы увидите, что заставляет ее работать медленнее.

Если результаты показывают, что предикат находится вне допустимого диапазона, это означает, что у вас нет статистики, собранной для таблиц, что она устарела с момента последнего обновления или просто значение вы ищете не существует. Выполните такой оператор, чтобы обновить статистику: выберите analysis_statistics ('tab1');

Вы также можете обновить статистику для одного столбца в таблице, например: выберите analysis_statistics ('tab1.email');

0 голосов
/ 28 апреля 2018

or - убийца производительности.

Как это работает?

select count(tab1.id)
from tab1 
where exists (select 1 from tab2 where tab1.email = tab2.email_a) or 
      exists (select 1 from tab2 where tab1.email = tab2.email_b);

Я предполагаю, что tab1.id уникально, поэтому вам не нужно select distinct.

...