Прежде всего, некоторые фоне.Speed up sql JOIN
У нас есть система обработки заказов, в которой сотрудники вводят платежные данные о заказах в приложении, которое хранит его в базе данных SQL Server 2000. Эта база данных не является реальной биллинговой системой: это просто место для хранения, так что записи могут быть запущены в систему мейнфреймов посредством ночного пакетного процесса.
Этот пакетный процесс представляет собой законсервированный сторонний пакет, предоставляемый сторонним поставщиком. Часть того, что он должен делать, это предоставить отчет для любых записей, которые были отклонены. Отчет об отказе обрабатывается вручную.
К сожалению, стороннее программное обеспечение не обнаруживает ошибок. У нас есть отдельные процессы, которые извлекают данные из мейнфрейма в другую таблицу в базе данных и загружают отклоненные платежи в другую таблицу.
Затем выполняется процесс аудита, чтобы убедиться, что все, что изначально было введено персоналом, можно отчитаться где-то. Эта проверка принимает форму запроса SQL мы бежим, и это выглядит примерно так:
SELECT *
FROM [StaffEntry] s with (nolock)
LEFT JOIN [MainFrame] m with (nolock)
ON m.ItemNumber = s.ItemNumber
AND m.Customer=s.Customer
AND m.CustomerPO = s.CustomerPO -- purchase order
AND m.CustPORev = s.CustPORev -- PO revision number
LEFT JOIN [Rejected] r with (nolock) ON r.OrderID = s.OrderID
WHERE s.EntryDate BETWEEN @StartDate AND @EndDate
AND r.OrderID IS NULL AND m.MainFrameOrderID IS NULL
Вот сильно модифицированные, конечно, но я считаю, представлены важные части. Проблема в том, что этот запрос начинает слишком долго работать, и я пытаюсь выяснить, как его ускорить.
Я уверен, что проблема заключается в ПРИСОЕДИНЕНИИ от таблицы StaffEntry
до таблицы MainFrame
. Так как данные сохраняются для каждого порядка с начала времени (2003 год в этой системе), они, как правило, немного большие. Значения OrderID
и EntryDate
, используемые в таблице StaffEntry
, не сохраняются при импорте в мэйнфрейм, поэтому это соединение немного сложнее. И, наконец, поскольку я ищу записи в таблице MainFrame
, которых не существует, после выполнения JOIN у нас есть этот уродливый IS NULL
в предложении where.
Таблица StaffEntry
индексируется EntryDate (сгруппировано) и отдельно по адресу Customer/PO/rev. MainFrame
индексируется клиентом и номером зарядки мейнфрейма (сгруппированы, это необходимо для других систем) и отдельно заказчиком/PO/Rev. Rejected
не индексируется вообще, но он небольшой, и тестирование показывает, что это не проблема.
Итак, мне интересно, есть ли другой (надеюсь, более быстрый) способ выразить эти отношения?
Какие показатели у вас на столах? – 2008-11-07 16:46:43
Не могли бы вы предоставить нам план выполнения запроса? – kasperjj 2008-11-07 16:49:42
Индексы теперь включены, но план выполнения не будет работать, потому что он не будет хорошо соответствовать запутанной версии запроса, который я опубликовал. – 2008-11-07 17:22:23