Почему объединение ON ложно намного медленнее, чем соединение с условием ON, которое ссылается на столбцы, но всегда оценивается как ложное в Snowflake? - PullRequest
1 голос
/ 17 февраля 2020

Эти два запроса имеют одинаковый результат, но очень разные времена выполнения, в обоих случаях предложение ON всегда оценивается как ложное. В первом запросе есть явный ON false, а во втором запросе ON t1.c1 = t2.c2 также всегда будет иметь значение false.

-- query 1
with t1 as (
  select seq4()*2 as c1 from table(generator(rowcount => 1000000))
)
,t2 as (
  select (seq4()*2)+1 as c2 from table(generator(rowcount => 1000000))
)
select * from t1 FULL JOIN t2 ON false; -- takes 16 minutes on a small warehouse


--query 2
with t1 as (
  select seq4()*2 as c1 from table(generator(rowcount => 1000000))
)
,t2 as (
  select (seq4()*2)+1 as c2 from table(generator(rowcount => 1000000))
)
select * from t1 FULL JOIN t2 ON t1.c1 = t2.c2 -- Instantaneous , same results 
;

Согласно профайлеру снежинки единственное отличие состоит в том, что в запросе 1 мы получаем узел соединения FULL OUTER с дополнительным условием соединения 1=0, а в запросе 2 мы получаем узел соединения FULL OUTER с равенством соединения Состояние SYS_VW.C1_0 = SYS_VW.C2_0.

Я предполагаю, что запрос 1 действительно сначала выполняет CROSS JOIN (1000000 * 1000000 = 10-12 строк), а затем фильтрует его. В то время как query2 выполняет просто UNION, оценивая только 1000000 + 1000000 = 2M строк.

Но вопрос в том, почему? Я имею в виду, это поведение указано / требуется SQL в целом, или это просто ошибка в планировщике / оптимизаторе запросов Snowflake?

Ответы [ 2 ]

1 голос
/ 18 февраля 2020

После консультации со службой поддержки Snowflake (случай 96930) я получил начальные баллы

  • ON FALSE - это не тот синтаксис, который они сейчас поддерживают.
  • Снежинка не интерпретирует ключевое слово FALSE, как другие SQL языки, и она зарезервирована за пределами предложений JOIN. Таким образом, он переводится в 1=0
  • Так как он не поддерживается, именно поэтому query1 приводит к 56 дополнительным шагам оптимизации по сравнению с query2.

К счастью, инженер поддержки соглашается с тем, что есть возможность выполнить эти условия ON FALSE, ON t1.c1=t2.c2 точно так же, и он доставит предложение в инженерный отдел.

Короче говоря, ON FALSE не поддерживается , хотя и не выдает ошибку. Они рекомендуют использовать правильное предложение ON для всех JOIN , кроме CROSS JOIN. И возможно, в будущем они распознают ON FALSE и оптимизируют его.

0 голосов
/ 18 февраля 2020

Похоже, что это было пропущено планировщиком запросов Снежинки. Я не вижу никаких документов, указывающих c на этот пример, хотя. Исходя из моего опыта, основанного на опыте в других dbms, моя теория заключается в том, что это имеет отношение к сарказуемости.

Быстрый поиск в Google по sargable сделает для вас больше, чем ответ. Короче говоря, предикаты, которые могут использовать индекс, считаются допустимыми. У большинства dbms есть ситуации, когда предикат, очевидно, не будет вмешиваться в индекс (ваш пример - хороший пример), но оптимизатору не будет задана конкретная ситуация c, и он примет решение: «Ну, я не уверен» если индекс все еще может быть использован, поэтому я предполагаю, что они не могут и делают это долгий путь "

Так что мне интересно, происходит ли что-то подобное здесь, поскольку Snowflake делает что-то другое под капот для оптимизации и «индексации», чем большинство других систем. В вашем примере я бы предположил, что в случае 2 он может определить, что у него два отсортированных списка чисел, и ему просто нужно пройти по двум спискам по порядку. Тогда как в первом списке он решает: «У меня есть два отсортированных списка номеров, но это не относится к моему предикату соединения ... лучше сравнивать каждую строку с каждой другой строкой и проверять предикат каждый раз»

Я бы порекомендовал отправить это Snowflake в тикете поддержки.

...