2012-08-23 34 views
3

我調整SQL Server上查詢2005年 請注意,真正的問題是在年底。 我有以下查詢,pto和ph都有大約3000萬行。查詢最初運行非常慢(3分鐘)。所以我在pto,ph分別加了兩個指數。查詢中使用覆蓋指數,合併聯接,哈希聯接

 SELECT 
      MAX(ph.txn_date_time) 
     FROM 
      pto AS pto WITH (NOLOCK) 
      INNER JOIN ph AS ph WITH (NOLOCK) ON ph.receipt_id = pto.receipt_id 
     WHERE 
       pto.subtype = 'ff' 
      AND pto.Units_No > 0 
      AND ph.branch_id = 5 



CREATE NONCLUSTERED INDEX [IX_pto_subTypeUnitReceipt] ON [dbo].[pto] 
(
    [SUBTYPE] ASC, 
    [Units_No] ASC, 
    [RECEIPT_ID] ASC 

)WITH (SORT_IN_TEMPDB = OFF, DROP_EXISTING = ON, IGNORE_DUP_KEY = OFF, ONLINE = OFF) ON [Indexes] 


CREATE NONCLUSTERED INDEX [IX_ph_branchReceiptTxn] ON [dbo].[ph] 
(
    [BRANCH_ID] ASC, 
    [RECEIPT_ID] ASC, 
    [TXN_DATE_TIME] ASC 
)WITH (SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, IGNORE_DUP_KEY = OFF, ONLINE = OFF) ON [Indexes] 

現在查詢在350ms內運行。大。執行計劃也非常簡單,它使用兩個表中創建的索引,並在receipt_id列上執行Hash連接,然後在Stream Aggregate上執行MAX(ph.txn_date_time)。因此查詢中的每一列都被兩個添加的索引覆蓋。

的問題是,爲什麼它用在receipt_id列散列連接?我的意思是,由於兩個索引中的RECEIPT_ID都是排序的,所以優化器應該使用合併連接。要弄清楚爲什麼我將第一個索引更改爲以下(在Units_No前放置RECEIPT_ID)。

CREATE NONCLUSTERED INDEX [IX_pto_subTypeUnitReceipt] ON [dbo].[pto] 
(
[SUBTYPE] ASC, 
[RECEIPT_ID] ASC, 
[Units_No] ASC 


)WITH (SORT_IN_TEMPDB = OFF, DROP_EXISTING = ON, IGNORE_DUP_KEY = OFF, ONLINE = OFF) ON [Indexes] 

現在我看到了RECEIPT_ID列上的合併連接。查詢也運行在170ms。現在很明顯,優化器認爲兩個索引中的RECEIPT_ID都是有序的,所以使用了合併連接。但我不明白爲什麼在第一種情況下它不這麼認爲?

回答

3

的原因是,RECEIPT_ID是不是在你有索引的第一個排序項。你有units_no的方式。

想象一下,你有一排由出版商,然後由作者,然後按顏色訂購的書籍。如果您想查找特定顏色的所有書籍,則需要訪問每個出版者部分,然後訪問每個作者部分,然後查找正確顏色的書籍。因此,'索引'不適合按顏色掃描,即使您可以一口氣說書籍按顏色排序。

當您添加最後一個索引時,RECEIPT_ID可用排序,因爲您正在通過SUBTYPE限制查詢。因此,來自雙方的所有RECEIPT_ID值都是簡單可用的,成本較低並且合併連接被選中。

+0

我明白了。如果不是訂單列中的第一列,那麼receipt_id無法保證被排序。在這種情況下,子類型是固定的,所以receipt_id保證在它是第二列時被排序。 謝謝。 – thotwielder

+0

@thotwielder - 現貨,是的。 –