1

У нас есть таблица, в которой хранятся все сообщения электронной почты, готовые к отправке и которые уже отправлены. Таблица содержит более 1 миллиона строк.Улучшение предложения советника по настройке двигателя DB

Ниже приведен запрос, чтобы найти сообщения, которые еще нужно отправить. После 5 ошибок сообщение больше не предпринимается, и его необходимо исправить вручную. SentDate остается null до тех пор, пока сообщение не будет отправлено.

SELECT TOP (15) 
    ID, 
    FromEmailAddress, 
    FromEmailDisplayName, 
    ReplyToEmailAddress, 
    ToEmailAddresses, 
    CCEmailAddresses, 
    BCCEmailAddresses, 
    [Subject], 
    Body, 
    AttachmentUrl 
FROM sysEmailMessage 
WHERE ErrorCount < 5 
AND SentDate IS NULL 
ORDER BY CreatedDate 

Запрос медленный, я предположил из-за отсутствия индексов. Я предложил запрос советнику по настройке ядра базы данных. Это предполагает ниже индекс (и некоторые статистические данные, которые я вообще игнорировать):

SET ANSI_PADDING ON 

CREATE NONCLUSTERED INDEX [_dta_index_sysEmailMessage_7_1703677117__K14_K1_K12_5_6_7_8_9_10_11_15_17_18] ON [dbo].[sysEmailMessage] 
(
    [SentDate] ASC, 
    [ID] ASC, 
    [ErrorCount] ASC 
) 
INCLUDE ( [FromEmailAddress], 
    [ToEmailAddresses], 
    [CCEmailAddresses], 
    [BCCEmailAddresses], 
    [Subject], 
    [Body], 
    [AttachmentUrl], 
    [CreatedDate], 
    [FromEmailDisplayName], 
    [ReplyToEmailAddress]) WITH (SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF) ON [PRIMARY] 

(На заметка на поля: этот показатель имеет рекомендуемый размер 5,850,573 KB(), который Нрайте 6 Гб и не делает? любой смысл для меня вообще.)

Мой вопрос заключается в том, что этот предлагаемый индекс имеет смысл? Почему, например, включен столбец ID, в то время как он не нужен в запросе (насколько я могу судить)? Насколько я знаю об индексах, они предназначены для быстрого поиска подходящей строки. Если бы мне пришлось разработать индекс сам я бы придумать что-то вроде:

SET ANSI_PADDING ON 

CREATE NONCLUSTERED INDEX [index_alternative_a] ON [dbo].[sysEmailMessage] 
(
    [SentDate] ASC, 
    [ErrorCount] ASC 
) 
WITH (SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF) ON [PRIMARY] 

Является ли оптимизатор действительно умный или мой индекс более эффективным и, вероятно, лучше?

+1

Это может быть предложение ID, чтобы быстрее просмотреть индекс кластеров. Однако я бы пошел с вашим индексом, но добавил CreateDate в индексированные столбцы и, возможно, INCLUDE (все остальные столбцы в вашем списке выбора). –

+1

Лучшим индексом для этого запроса будет 'CREATE INDEX ix в sysEmailMessage (CreatedDate) WHERE ErrorCount <5 AND SentDate IS NULL'. Это не покрытие, но вы получите только 15 запросов, так как просто нужно обработать отфильтрованный индекс по порядку и остановиться после 15 строк. –

ответ

1

Существует два разных аспекта выбора индекса, поля, необходимые для поиска строк (= фактические индексированные поля) и поля, которые необходимы после этого (= включены поля). Если вы всегда делаете топ-15 строк, вы можете полностью игнорировать включенные поля, потому что 15 keylookups будут быстрыми - и добавление всей электронной почты к индексу сделает ее огромной.

Для индексированных полей очень важно знать, насколько большой процент данных соответствует вашим критериям.

Предполагая, что почти все ваши строки имеют ErrorCount < 5, вы не должны иметь его в индексе, но если это редкий случай, то это хорошо.

Предполагая, что SentDate действительно редко имеет значение NULL, тогда вы должны иметь это как первый столбец индекса.

Наличие CreateDate в индексе зависит от того, сколько строк в среднем найдено из таблицы с критериями ErrorCount и SentDate. Если это много (тысячи), то это может помочь найти его там, чтобы новейшие можно было найти быстро.

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

Смежные вопросы