Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Microsoft SQL Server Новый топик    Ответить
 Оптимизация SQL запроса с коррелированными подзапросами  [new]
Valentina.Yu
Member

Откуда:
Сообщений: 3
Всем привет!

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

SELECT (SELECT MIN(CASE WHEN tab1.col1 = 0 THEN 0 ELSE 1 END) 
        FROM tab1 
		WHERE tab1.col2 = tab2.col2
          AND (tab2.col1 <> 1 OR (SELECT COUNT(*) FROM tab1 AS p1 WHERE tab1.col4 = p1.col4) = 0)
          AND (tab1.col3 = 1 OR tab2.col1 = 0 AND ISNULL((SELECT SUM(tab3.col1) FROM tab3 WHERE tab3.col1 = tab2.col2),0) < tab1.col5)
		) col_alias
FROM tab2



Также прикрепляю Execution plan


Может у кого-то есть идеи в какое русло вообще двигать все это?

К сообщению приложен файл. Размер - 72Kb
14 сен 18, 19:23    [21675050]     Ответить | Цитировать Сообщить модератору
 Re: Оптимизация SQL запроса с коррелированными подзапросами  [new]
Valentina.Yu
Member

Откуда:
Сообщений: 3


К сообщению приложен файл (execplan.sqlplan - 73Kb) cкачать
14 сен 18, 19:23    [21675051]     Ответить | Цитировать Сообщить модератору
 Re: Оптимизация SQL запроса с коррелированными подзапросами  [new]
alexeyvg
Member

Откуда: Moscow
Сообщений: 30711
Valentina.Yu
Может у кого-то есть идеи в какое русло вообще двигать все это?
Вообще то никаких условий в запросе нет, поэтому должны просканироваться все участвующие таблицы, и во всем строкам сделаны вычисления. Это будет небыстро, в любом случае.
А так - делать индексы по колонкам, участвующим в связях, делать include-индексы, может, получится использовать индексированные представления для агрегатов.

PS Кстати, у вас условие (SELECT COUNT(*) FROM tab1 AS p1 WHERE tab1.col4 = p1.col4) = 0) всегда ложно.
14 сен 18, 20:51    [21675120]     Ответить | Цитировать Сообщить модератору
 Re: Оптимизация SQL запроса с коррелированными подзапросами  [new]
aleks222
Member

Откуда:
Сообщений: 847
alexeyvg
PS Кстати, у вас условие (SELECT COUNT(*) FROM tab1 AS p1 WHERE tab1.col4 = p1.col4) = 0) всегда ложно.


И, как следствие, второй подзапрос
 ISNULL((SELECT SUM(tab3.col1) FROM tab3 WHERE tab3.col1 = tab2.col2),0) < tab1.col5

тоже бесполезен. Можно убрать.

Вот и оптимизировали.
15 сен 18, 18:19    [21675611]     Ответить | Цитировать Сообщить модератору
 Re: Оптимизация SQL запроса с коррелированными подзапросами  [new]
aleks222
Member

Откуда:
Сообщений: 847
Эквивалент исходного запроса
SELECT (SELECT MIN(CASE WHEN tab1.col1 = 0 THEN 0 ELSE 1 END) 
        FROM tab1 
		WHERE tab1.col2 = tab2.col2
          AND (tab2.col1 <> 1 )
          AND (tab1.col3 = 1 )
		) col_alias
FROM tab2
15 сен 18, 18:24    [21675616]     Ответить | Цитировать Сообщить модератору
 Re: Оптимизация SQL запроса с коррелированными подзапросами  [new]
alexeyvg
Member

Откуда: Moscow
Сообщений: 30711
aleks222
И, как следствие, второй подзапрос
 ISNULL((SELECT SUM(tab3.col1) FROM tab3 WHERE tab3.col1 = tab2.col2),0) < tab1.col5

тоже бесполезен. Можно убрать.
Хм, а почему это? Вы не спутали tab1.col3 и tab3.col1?
16 сен 18, 13:55    [21675928]     Ответить | Цитировать Сообщить модератору
 Re: Оптимизация SQL запроса с коррелированными подзапросами  [new]
aleks222
Member

Откуда:
Сообщений: 847
AND (tab2.col1 <> 1 OR (SELECT COUNT(*) FROM tab1 AS p1 WHERE tab1.col4 = p1.col4) = 0)
          AND (tab1.col3 = 1 OR tab2.col1 = 0 AND ISNULL((SELECT SUM(tab3.col1) FROM tab3 WHERE tab3.col1 = tab2.col2),0) < tab1.col5)


AND (tab2.col1 <> 1 OR FALSE)
          AND (tab1.col3 = 1 OR tab2.col1 = 0 AND ISNULL((SELECT SUM(tab3.col1) FROM tab3 WHERE tab3.col1 = tab2.col2),0) < tab1.col5)


AND tab2.col1 <> 1 
          AND (tab1.col3 = 1 OR tab2.col1 = 0 AND ISNULL((SELECT SUM(tab3.col1) FROM tab3 WHERE tab3.col1 = tab2.col2),0) < 
tab1.col5)


AND tab2.col1 <> 1 
          AND (tab1.col3 = 1 OR (tab2.col1 = 0 AND ISNULL((SELECT SUM(tab3.col1) FROM tab3 WHERE tab3.col1 = tab2.col2),0) < 
tab1.col5) )


AND tab2.col1 <> 1 
          AND (tab1.col3 = 1 OR (FALSE AND ISNULL((SELECT SUM(tab3.col1) FROM tab3 WHERE tab3.col1 = tab2.col2),0) < 
tab1.col5) )


AND tab2.col1 <> 1 
          AND tab1.col3 = 1
16 сен 18, 14:21    [21675945]     Ответить | Цитировать Сообщить модератору
 Re: Оптимизация SQL запроса с коррелированными подзапросами  [new]
alexeyvg
Member

Откуда: Moscow
Сообщений: 30711
aleks222
AND tab2.col1 <> 1 
          AND (tab1.col3 = 1 OR (tab2.col1 = 0 AND ISNULL((SELECT SUM(tab3.col1) FROM tab3 WHERE tab3.col1 = tab2.col2),0) < 
tab1.col5) )

AND tab2.col1 <> 1 
          AND (tab1.col3 = 1 OR (FALSE AND ISNULL((SELECT SUM(tab3.col1) FROM tab3 WHERE tab3.col1 = tab2.col2),0) < 
tab1.col5) )
Всё равно не понял, почему tab2.col1 = 0 всегда FALSE?
Если бы tab2.col1 имел тип BIT, то tab2.col1 = 0 было бы всегда TRUE, потому что выше tab2.col1 <> 1
Но его тип неизвестен, и уж тем более выражение не FALSE
16 сен 18, 15:37    [21675981]     Ответить | Цитировать Сообщить модератору
Все форумы / Microsoft SQL Server Ответить