2013-11-27 115 views
1

我有一個需要超過400萬行持有的電子郵件調度表。一個特別的報告還需要參考該表產生一些統計數據,而且它花費的時間比我想運行(目前大約30秒)。SQL Server查詢優化 - 這裏的最佳索引是什麼?

我已經檢查了估計的執行計劃,其示出了成本的94%是由一個單一謂詞發生(如果我正確地解釋這一點)。

注意以下示例所示小片段,以保持簡潔。其他索引適用於其他查詢。

enter image description here

謂:

[EmsDb].[dbo].[MailDispatchPending].[MailCampaignId]=[@MailCampaignId] OR [@MailCampaignId] IS NULL 

我相信這是指着下面的SQL:

WHERE @MailCampaignId IS NULL OR MailCampaignId = @MailCampaignId -- Restrict to mail campaign where parameter passed 

我試圖提高通過測試以下索引的性能。既不影響執行計劃輸出,也不提高查詢速度。

/****** Object: Index [IX_MailCampaignId] Script Date: 11/27/2013 11:21:00 ******/ 
CREATE NONCLUSTERED INDEX [IX_MailCampaignId] ON [dbo].[MailDispatchPending] 
(
    [MailCampaignId] ASC 

)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] 
GO 

/****** Object: Index [IX_MailCampaignId] Script Date: 11/27/2013 11:21:00 ******/ 
CREATE NONCLUSTERED INDEX [IX_MailCampaignId] ON [dbo].[MailDispatchPending] 
(
    [Id] ASC, 
    [MailCampaignId] ASC 

)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] 
GO 

任何人都可以提出更好的索引類型或不同的策略來幫助我提高性能嗎?

回答

3

不要使用這種方法:

WHERE @MailCampaignId IS NULL OR MailCampaignId = @MailCampaignId 

而是使用:

IF @MailCampaignId IS NULL 
    BEGIN 
     SELECT .. 
     FROM ... 
    END 
ELSE 
    BEGIN 
     SELECT .. 
     FROM ... 
     WHERE MailCampaignId = @MailCampaignId 
    END 

它可能會覺得更多的工作,但SQL-Server使用緩存的執行計劃,除非你強行重新編譯它將使用相同的執行計劃,無論參數是否爲空。如果你使用上面的方法,你保證使用正確的計劃取決於參數是否爲空

+0

無論參數值如何,這都是關於使用相同執行計劃的方便信息 – gb2d

2

IS NULL OR部分是做什麼用你的表現搞亂,因爲如果輸入爲NULL你問的每一行是掃描。

如果可能的話我會刪除部分,看看是否有沒有幫助,如果沒有可能,那麼我會重新考慮的時候我需要所有這些,例如考慮多個查詢的另一種方法,而不是一個甚至存儲的變化。

0

可以這是一個由@GarethD提出的替代解決方案嗎?

WHERE MailCampaignId = COALESCE(@MailCampaignId,MailCampaignId)