Оптимизация запросов T-SQL - PullRequest
0 голосов
/ 14 сентября 2018

У меня запрос с очень низкой производительностью. В производственной базе данных есть десятки миллионов строк данных.

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

Я уже пытался решить проблему с производительностью с помощью индексов, JOIN и CTE. Но поскольку используются агрегатные функции и коррелированные подзапросы, я не ставлю ничего, что улучшало бы производительность.

У кого-нибудь есть идеи, как я могу это улучшить?

План запроса:

https://www.brentozar.com/pastetheplan/?id=SJSUd1pOX

enter image description here

Ответы [ 2 ]

0 голосов
/ 14 сентября 2018

Это, конечно, не скомпилируется, однако, если поля Colxxx правильно проиндексированы, вы, возможно, сможете набрать скорость, агрегируя суммы и флаги и выполняя некоторые из этих условий в отличие от строки за строкой.

SELECT
    MinFlag = MIN(MinFlag)
FROM
(
    SELECT 
        Table1Column2 = tab1.Col2,
        MinFlag = CASE WHEN tab1.col1 = 0 THEN 0 ELSE 1 END,
        SumTable3Column1= tab3.col1 ,
        ConditionThreeFlag = CASE WHEN tab1.col3 = 1 OR tab2.col1 = 0 THEN 1 ELSE 0 END,
        Tabel1Column5 = tab1.col5
    FROM 
        tab2
        INNER JOIN tab1 ON tab1.col2 = tab2.col2 
        LEFT OUTER JOIN tab3 ON tab3.col1 = tab2.col2
    WHERE 
        (tab2.col1 <> 1 OR tab1.col4 IS NULL)

)AS X
GROUP BY
        X.Table1Column2 
HAVING 
    ((MAX(ConditionThreeFlag) = 1) AND (SUM(SumTable3Column1) < MAX(Tabel1Column5)))

РЕДАКТИРОВАТЬ: Я потерян здесь, я немного подумал и решил, что это всегда будет ложным (подсчет всех col4, соединенных снова на col4, где count == 0) или вы говоритегде col4 = количество всех записей в tab1 ??

0 голосов
/ 14 сентября 2018

Без плана запроса, и так как все имена ваших столбцов являются общими, и я не уверен, что именно вы пытаетесь создать, я не могу сказать вам вещи, которые есть или не нужны втам.Но вот несколько общих советов:

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

Сначала я бы порекомендовал выделить другие ORдел в своих собственных ветках if / else.Таким образом, каждый оператор может получить план запроса в соответствии с тем, что он делает.

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

...