0

我有一個表格MY_TABLE約900萬行。查詢性能悖論:獨特的羣集與非唯一的非羣集索引

該表共有38列。這是有關我的問題的列有:

  • RECORD_ID:身份,BIGINT,具有獨特的聚集索引
  • RECORD_CREATED:日期時間,與非唯一&非聚集索引現在

我運行以下兩個查詢,自然期望第一個執行速度更快,因爲數據按具有唯一聚簇索引的列進行排序,但它以某種方式執行了271次(!)較慢。

SELECT TOP 1 
    RECORD_ID 
FROM 
    MY_TABLE 
WHERE 
    RECORD_CREATED >= '20140801' 
ORDER BY 
    RECORD_ID 

SELECT TOP 1 
    RECORD_ID 
FROM 
    MY_TABLE 
WHERE 
    RECORD_CREATED >= '20140801' 
ORDER BY 
    RECORD_CREATED 

執行時間分別爲1630ms和6ms。

請指教。

P.S.:由於環境的安全策略,我看不到執行計劃或使用SQL Profiler

+0

第二個只是一個直接索引尋求。如果索引不覆蓋,則讀取第一行大於或等於查找點以及可能的單個查找。在你的情況下,索引將被覆蓋,因爲NCI總是包含CI密鑰,因此不需要查找。 – 2014-09-10 18:39:26

+0

@馬丁史密斯,我真的很抱歉,但我完全不理解你的評論。你能解釋一下嗎?答案也是受歡迎的。 – 2014-09-10 19:26:28

+0

我不會在PC上提交答案,因爲我不在PC上。通常'RECORD_CREATED> ='20140801'可以通過範圍尋找來滿足。找到索引中的相關點,然後一起掃描。因爲您只想索引順序中的前1位,SQL Server可以在讀取第一行時立即停止範圍查找。您的選擇列表實際上位於不同的列'record_id'上,但它也靜默地包含在非聚集索引中,因爲它是聚簇索引鍵。 – 2014-09-10 19:32:43

回答

2

SQL Server有幾個關於如何執行此查詢的選擇。它可能開始排序所有項目,利用您提到的索引,然後通過篩選出任何不匹配WHERE子句的項目。但是,通常要減少與第一個一起使用的數據集的大小,因此您不必排序儘可能多的項目。

因此,SQL Server最有可能選擇首先執行WHERE過濾器。當它這樣做時,它最有可能通過使用RECORD_CREATED上的非唯一非聚集索引來跳過RECORD_CREATED小於'20140801'的所有項目,然後獲取所有項目。

此時,所有項目都按照它們在RECORD_CREATED索引中找到的順序進行了預先排序,因此第二個查詢不需要額外的努力,但第一個查詢必須對記錄執行排序已被選中。

+0

如果發動機決定先排序,該怎麼辦?其他選項會更快嗎?我想不是,第二種選擇會更快,對嗎? – 2014-09-10 19:31:48

+0

在數據庫優化方面,我不是嚮導,但我猜這取決於一些因素,例如表中有多少項與WHERE子句匹配。 – StriplingWarrior 2014-09-10 19:40:31