2016-03-24 27 views
0

我有一個非常簡單的一個表查詢,需要幾秒鐘才能完成。我很困惑。當我從選擇頂端變爲50而不是200時,它變得更快。該表有大約一百萬行。Sql服務器性能不是我所期望的

我在所有提到的列上都有索引。

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 

該計劃生成是:

enter image description here

和全DDL是:

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

你知道查詢計劃是什麼嗎?導出IT(.sqlplan),然後我們可以提供幫助。 – TomTom

+0

更快在200只是可能在內存中的行/索引。 50與200仍然需要排序。 – Paparazzi

回答

3

在使用SELECT TOP xORDER BY一起一般建議,以確保相同的結果,每一個時間,ORDER BY將排序整個結果集,然後只有TOP x被採取f rom它。

我想知道你會看到如果你做SELECT COUNT(*)而不是SELECT TOP x:可能是一個相當高的數字?

雖然使用索引保證快速排序,但有沒有索引涵蓋了此查詢的確切ORDER BY。最重要的是,獲取WHERE和SELECT子句的字段需要進入可能遍佈磁盤的數據頁。爲了優化這個查詢,你可以將WHERE-和ORDER BY-和SELECT-字段添加到一個新的索引(按照這個順序),當然沒有重複。它會產生一個相當大的索引,這可能會減慢插入/更新速度,但也會使SELECT速度非常快,因爲只需使用索引即可滿足整個查詢,而無需進入數據頁。

+0

謝謝大家的意見。當我回到我的辦公桌後,我會公佈計劃,並進行計數(*)測試。 –

+0

做select count(*)非常快(即時),所以我認爲這不是索引問題。當我減少我檢索的列數時,它變得越來越快。我認爲這意味着我的數據必須散佈在磁盤周圍?無論如何,讓所有的最後條目彼此接近?最高紀錄總是我剛剛插入的10或20萬。 –

+0

count(\ *)的值表示ORDER BY在可以採用TOP x之前必須完成的工作量,特別是如果沒有包含ORDER BY字段的單個索引。 count(\ *)本身的速度本身並不相關,如果請求count(\ *)並且沒有其他字段,則甚至有可能跳過ORDER BY。更重要的是如我所指出的那樣創建一個或多或少的索引。 –