#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;