2016-03-24 9 views
0

私は非常に単純なテーブルクエリを手に入れました。私はうんざりしている。私が選択トップから200の代わりに50に変更すると、はるかに速くなります。テーブルには約100万行があります。SQL Serverのパフォーマンスが期待していたものではない

私は上記のすべての列にインデックスを持っています。 ORDER BYと一緒SELECT TOP xを使用すると、すべて同じ結果を保証するために、一般的に推奨されている間

CREATE TABLE dbo.EmailDetails (
     Id int IDENTITY(1, 1) NOT NULL, 
     AttendeesId int NOT NULL, 
     SponsorListContactId int NULL, 
     MessageUniqueId nvarchar(512) COLLATE SQL_Latin1_General_CP1_CI_AS NULL, 
     EmailSendStatus nvarchar(16) COLLATE SQL_Latin1_General_CP1_CI_AS NULL, 
     EmailSendStartTime datetime NULL, 
     EmailSendFinishTime datetime NULL, 
     EmailSendLogMessage nvarchar(max) COLLATE SQL_Latin1_General_CP1_CI_AS NULL, 
     Subject nvarchar(2048) COLLATE SQL_Latin1_General_CP1_CI_AS NULL, 
     BodyText nvarchar(max) COLLATE SQL_Latin1_General_CP1_CI_AS NULL, 
     SentDateTime datetime NULL, 
     EmailFrom nvarchar(128) COLLATE SQL_Latin1_General_CP1_CI_AS NULL, 
     EmailTo nvarchar(128) COLLATE SQL_Latin1_General_CP1_CI_AS NULL, 
     EmailDetailsTopicId int NULL, 
     EmailDetailsGuid uniqueidentifier NULL, 
     EmailReadCount int NULL, 
     EmailReadDate datetime NULL, 
     EmailSendStatusChange datetime NULL, 
     EmailSendPriority int NULL, 
     TextTo varchar(64) COLLATE SQL_Latin1_General_CP1_CI_AS NULL, 
     CONSTRAINT EmailDetails_pk PRIMARY KEY CLUSTERED (Id) 
     WITH (
      PAD_INDEX = OFF, IGNORE_DUP_KEY = OFF, STATISTICS_NORECOMPUTE = OFF, 
      ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) 
    ) 
    ON [PRIMARY] 
    GO 

    CREATE NONCLUSTERED INDEX EmailDetails_AttendeesIds_idx ON dbo.EmailDetails 
     (AttendeesId) 
    WITH (
     PAD_INDEX = OFF, 
     DROP_EXISTING = OFF, 
     STATISTICS_NORECOMPUTE = OFF, 
     SORT_IN_TEMPDB = OFF, 
     ONLINE = OFF, 
     ALLOW_ROW_LOCKS = ON, 
     ALLOW_PAGE_LOCKS = ON) 
    ON [PRIMARY] 
    GO 

    CREATE NONCLUSTERED INDEX EmailDetails_idx ON dbo.EmailDetails 
     (EmailDetailsGuid) 
    WITH (
     PAD_INDEX = OFF, 
     DROP_EXISTING = OFF, 
     STATISTICS_NORECOMPUTE = OFF, 
     SORT_IN_TEMPDB = OFF, 
     ONLINE = OFF, 
     ALLOW_ROW_LOCKS = ON, 
     ALLOW_PAGE_LOCKS = ON) 
    ON [PRIMARY] 
    GO 

    CREATE NONCLUSTERED INDEX EmailDetails_idx2 ON dbo.EmailDetails 
     (EmailDetailsTopicId) 
    WITH (
     PAD_INDEX = OFF, 
     DROP_EXISTING = OFF, 
     STATISTICS_NORECOMPUTE = OFF, 
     SORT_IN_TEMPDB = OFF, 
     ONLINE = OFF, 
     ALLOW_ROW_LOCKS = ON, 
     ALLOW_PAGE_LOCKS = ON) 
    ON [PRIMARY] 
    GO 

    CREATE NONCLUSTERED INDEX EmailDetails_idx3 ON dbo.EmailDetails 
     (SentDateTime) 
    WITH (
     PAD_INDEX = OFF, 
     DROP_EXISTING = OFF, 
     STATISTICS_NORECOMPUTE = OFF, 
     SORT_IN_TEMPDB = OFF, 
     ONLINE = OFF, 
     ALLOW_ROW_LOCKS = ON, 
     ALLOW_PAGE_LOCKS = ON) 
    ON [PRIMARY] 
    GO 

    CREATE NONCLUSTERED INDEX EmailDetails_priority_status_idx4 ON dbo.EmailDetails 
     (EmailSendPriority, EmailSendStatus) 
    WITH (
     PAD_INDEX = OFF, 
     DROP_EXISTING = OFF, 
     STATISTICS_NORECOMPUTE = OFF, 
     SORT_IN_TEMPDB = OFF, 
     ONLINE = OFF, 
     ALLOW_ROW_LOCKS = ON, 
     ALLOW_PAGE_LOCKS = ON) 
    ON [PRIMARY] 
    GO 

    CREATE NONCLUSTERED INDEX EmailDetails_SentStatus_idx ON dbo.EmailDetails 
     (EmailSendStatus) 
    WITH (
     PAD_INDEX = OFF, 
     DROP_EXISTING = OFF, 
     STATISTICS_NORECOMPUTE = OFF, 
     SORT_IN_TEMPDB = OFF, 
     ONLINE = OFF, 
     ALLOW_ROW_LOCKS = ON, 
     ALLOW_PAGE_LOCKS = ON) 
    ON [PRIMARY] 
    GO 

    CREATE NONCLUSTERED INDEX EmailDetails_topicid_attendeeid ON dbo.EmailDetails 
     (EmailDetailsTopicId, AttendeesId) 
    WITH (
     PAD_INDEX = OFF, 
     DROP_EXISTING = OFF, 
     STATISTICS_NORECOMPUTE = OFF, 
     SORT_IN_TEMPDB = OFF, 
     ONLINE = OFF, 
     ALLOW_ROW_LOCKS = ON, 
     ALLOW_PAGE_LOCKS = ON) 
    ON [PRIMARY] 
    GO 

    CREATE NONCLUSTERED INDEX EmailDetails_topicid_sponsorcontactid_idx ON dbo.EmailDetails 
     (EmailDetailsTopicId, SponsorListContactId) 
    WITH (
     PAD_INDEX = OFF, 
     DROP_EXISTING = OFF, 
     STATISTICS_NORECOMPUTE = OFF, 
     SORT_IN_TEMPDB = OFF, 
     ONLINE = OFF, 
     ALLOW_ROW_LOCKS = ON, 
     ALLOW_PAGE_LOCKS = ON) 
    ON [PRIMARY] 
    GO 
+0

具体的な質問がありますか? – B540Glenn

+0

クエリプランは何ですか? EXPORT IT(.sqlplan)を実行してください。 – TomTom

+0

200のほうが高速だったのは、たぶんメモリ内の行/インデックスでした。 50対200はまだソートしなければならない。 – Paparazzi

答えて

3

enter image description here

とフルDDLは次のとおりです。

SELECT TOP 50 dbo.EmailDetails.Id, 
FROM dbo.EmailDetails WITH (NOLOCK) 
WHERE (dbo.EmailDetails.EmailSendStatus = 'NEEDTOSEND' OR 
    dbo.EmailDetails.EmailSendStatus = 'NEEDTOTEXT') AND 
    dbo.EmailDetails.EmailDetailsTopicId IS NOT NULL 
ORDER BY dbo.EmailDetails.EmailSendPriority, 
    dbo.EmailDetails.Id DESC 

プランの生成は、 ORDER BYは結果セット全体をソートし、その後にTOP xをfそれをロム。

SELECT TOP xの代わりにSELECT COUNT(*)を実行すれば、どうなるか分かりますか?

インデックスを使用すると高速ソートが保証されますが、このクエリの正確なORDER BYをカバーするインデックスはであり、インデックスはではありません。その上、WHERE句とSELECT句のフィールドを取得するには、おそらくディスク全体に広がるデータページに入る必要があります。このクエリだけを最適化するには、WHERE句とORDER BY句とSELECT句を新しいインデックスに(その順序で)追加することができます。もちろん、重複はありません。かなり大きなインデックスが作成されるため、挿入/更新が遅くなる可能性がありますが、SELECTを非常に高速にすることができます。これは、データページに入らずにインデックス全体を使用できるためです。

+0

誰もが入力に感謝します。私は私の机に戻ってカウント(*)のテストもやって、計画を掲示します。 select count(*)を行う –

+0

は非常に高速です(瞬時)ので、インデックスの問題ではないと思います。私が検索している列の数を減らすにつれて、より高速かつ高速になります。これは私のデータがディスクの周りに散らばっていなければならないと思いますか?とにかく、最後のエントリをすべて互いに近づけるには?一番上のレコードは、ちょうど私が挿入した10または20,000です。 –

+0

count(\ *)の値は、特にORDER BYフィールドをカバーする単一のインデックスがない場合、ORDER BYがTOP xを実行する前に行う必要のある作業の量を示します。カウント(\ *)の速度自体はあまり意味がなく、カウント(\ *)が要求され、他のフィールドがない場合は、ORDER BYがスキップされる可能性さえあります。もっと重要なことは、私が指摘したように、多かれ少なかれインデックスを作成することです。 –

関連する問題