Запрос с несколькими левыми соединениями занимает так много времени для выполнения

#sql #query-optimization #snowflake-cloud-data-platform

Вопрос:

В snowflake у меня есть таблица Table_A, которая получает свои данные на основе различных условий соединения слева из 4 других таблиц (Table_1, Table_2, Table_3, Table_4). Каждая исходная таблица содержит около 20 миллионов строк, и ожидается, что после выполнения запроса в Table_A будет вставлено не менее 10 миллионов строк.

Я использую приведенное ниже условие с несколькими левыми соединениями и ИЛИ .

 Insert into Table_A (x,y,z)
select "column names"
    FROM "Table_1" T1
    LEFT JOIN "Table_2" T2 ON T1.ID = T2.ID
    LEFT JOIN "Table_3" T3 ON  T1.ID = T3.ID or T2.ID = T3.ID
    LEFT JOIN "Table_4" T4 ON T1.ID = T4.ID or T2.ID = T4.ID or T3.ID = T4.ID
 

Запрос с вышеуказанным условием занимает так много времени. Я попытался использовать ограничение на 5, и мне потребовалось 5 минут, чтобы вставить всего 5 строк (при большом размере склада). Я оставил его работать без ограничений, и мне пришлось прервать его через 12 часов, потому что он все еще работал. Есть ли какой-либо способ оптимизировать это условие запроса/логики, чтобы уменьшить время его выполнения? ТИА

Комментарии:

1. Ваш запрос не имеет условий фильтрации, поэтому он считывает все строки Table_1 и связанные с ними данные. Массовый запрос, подобный этому, потребует времени . Если вы хотите, чтобы запрос был быстрым, вам, вероятно, следует получить доступ только к ограниченному диапазону данных.

2. @TheImpaler, но table_A должен хранить все столбцы из исходных таблиц

3. Когда вы переходите на вкладку История в веб-интерфейсе Snowflake и проверяете профиль запроса, где он проводит большую часть своего времени? Ищите что-нибудь неожиданное, например, взрыв в рядах. Проверьте количество строк, выходящих из каждого шага (сокращенно k, M, G для тысяч, миллионов, миллиардов строк), чтобы найти что-нибудь неожиданное.

4. Вы выбираете из Table_1 , а затем делаете left join в том же столбце. Какова цель or этого ? Если T1.ID = T3.ID равно false, то T2.ID = T3.ID очевидно, что это ложь, потому что этот запрос не может создавать строки, где T2.id не равно T1.id . То же самое для других условий

5. Если вам нужно объединить все таблицы id , то рассмотрите join ... using(id)

Ответ №1:

OR убивает оптимизацию JOIN s. Вы могли бы использовать USING , чтобы избежать этой проблемы с внешними соединениями. Однако в этом нет необходимости (и это может быть сложно, если столбцы объединения не имеют одного и того же имени).

Цепочка соединений равна LEFT JOIN s, поэтому у вас есть все данные в первой таблице. Итак, просто используйте идентификатор из этой таблицы для всех соединений:

 Insert into Table_A (x,y,z)
    SELECT "column names"
        FROM "Table_1" T1 LEFT JOIN
             "Table_2" T2 
             ON T1.ID = T2.ID LEFT JOIN
             "Table_3" T3
             ON  T1.ID = T3.ID LEFT JOIN
             "Table_4" T4
             ON T1.ID = T4.ID;