T-SQL SELECT с дочерними строками существует оптимизировать - PullRequest
0 голосов
/ 29 августа 2011

Я пытаюсь оптимизировать свой запрос.В основном у меня есть таблица отдела и таблица документов.Каждый документ принадлежит отделу, и каждый документ может быть определенного типа.

В настоящее время запрос mu выглядит следующим образом

SELECT  DepartmentID,
        [Description] = DepartmentNo + ' (' + DepartmentName + ')',
        hasInvoice = CASE WHEN EXISTS(SELECT DocID FROM Document WHERE DepartmentID = Department.DepartmentID AND TypeID = 1) > 0 THEN 1 ELSE 0 END,
        hasCreditNote = CASE WHEN EXISTS(SELECT DocID FROM Document WHERE DepartmentID = Department.DepartmentID AND TypeID = 2) > 0 THEN 1 ELSE 0 END,
        hasQuote = CASE WHEN EXISTS(SELECT DocID FROM Document WHERE DepartmentID = Department.DepartmentID AND TypeID = 3) > 0 THEN 1 ELSE 0 END
FROM  Department
ORDER BY DepartmentName

Проблема, с которой я столкнулся, заключается в том, что для каждого поиска документов, относящихся кОтдел по их типу заставляет запрос повторно сканировать таблицу документов, что замедляет процесс.Есть ли более оптимизированный способ сделать это?Я попытался использовать CTE, делая левое соединение для каждого типа.но, похоже, это никак не повлияет на ускорение запроса.

У нас примерно 200000 документов, поэтому очень важно оптимизировать этот запрос.

Спасибо

1 Ответ

3 голосов
/ 29 августа 2011

Какими бы ни были индексы, у вас слишком много «касаний» к таблице «Документ»: 3 раза на строку в таблице «Отдел». Таким образом, он будет плохо масштабироваться, и оптимизатор не сможет изменить коррелированные подзапросы на JOIN.

Вы можете сделать это одним прикосновением к таблице документов, например, с помощью JOIN

SELECT
    D.DepartmentID,
    [Description] = D.DepartmentNo + ' (' + D.DepartmentName + ')',
    hasInvoice = SIGN(COUNT(CASE WHEN doc.TypeID = 1 THEN 1 END)),
    hasCreditNote = SIGN(COUNT(CASE WHEN doc.TypeID = 2 THEN 1 END)),
    hasQuote = SIGN(COUNT(CASE WHEN doc.TypeID = 3 THEN 1 END))
FROM 
    Department D
    LEFT JOIN
    Document doc ON D.DepartmentID = doc.DepartmentID
ORDER BY
    D.DepartmentName, D.DepartmentID, D.DepartmentNo

Вы также можете 3 раза ЛЕВО ПРИСОЕДИНИТЬСЯ к отфильтрованной + агрегированной производной таблице документа или использовать CROSS APPLY 3 раза: но это все еще 3 варианта использования таблицы документа

Вам нужен индекс DepartmentID, TypeID в Документах для любого решения. Без этого я только переставил шезлонги так сказать

Я предполагаю, что Department.DepartmentID также является кластерным индексом.

...