1

送信する準備ができており、既に送信されたすべての電子メール メッセージを保持するテーブルがあります。テーブルには 100 万行を超える行が含まれています。

以下は、まだ送信する必要があるメッセージを見つけるためのクエリです。エラーが 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 GB であり、私にはまったく意味がありません。)

私の質問は、この提案されたインデックスは意味がありますか? たとえば、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]

オプティマイザーは本当に賢いのでしょうか、それとも私のインデックスはより効率的でおそらくより優れているでしょうか?

4

1 に答える 1

1

インデックスの選択には 2 つの異なる側面があります。行を検索するために必要なフィールド (= 実際のインデックス付きフィールド) と、その後に必要なフィールド (= 含まれるフィールド) です。常に上位 15 行を処理している場合は、含まれるフィールドを完全に無視できます。これは、15 のキールックアップが高速になるためです。また、メール全体をインデックスに追加すると、インデックスが巨大になります。

インデックス付きフィールドの場合、基準に一致するデータの割合を把握することが非常に重要です。

ほとんどすべての行が ErrorCount < 5 であると仮定すると、それをインデックスに含めるべきではありませんが、まれなケースである場合は、持っておくとよいでしょう。

SentDate がめったに NULL でないと仮定すると、それをインデックスの最初の列にする必要があります。

インデックスに CreatedDate が含まれているかどうかは、ErrorCount および SentDate 基準を使用してテーブルから検出される平均行数によって異なります。数が多い (数千) 場合は、最新のものをすばやく見つけることができるように、そこにあると役立つ場合があります。

ただし、いつものように、いくつかのことがパフォーマンスに影響するため、さまざまなオプションが環境にどのように影響するかをテストする必要があります。

于 2015-06-13T19:55:15.563 に答える