2012-06-20 87 views
2

我正在改進一些SQL查詢腳本的性能。例如:索引字段和索引與包含字段之間的差異

SELECT * 
FROM Book b, Library l, [Order] o 
WHERE o.bookid = b.bookID 
AND o.mode = 'A' 
AND o.library_ID = l.library_ID 
AND l.library_ID > 19 
AND b.publisher_id > 1000 
AND b.print_id > 800 
AND NOT EXISTS (
    SELECT * 
    FROM ExtBOOK 
    WHERE b.bookid = extbookid 
    AND library_ID = l.library_ID 
) 
AND o.activated = 'Y' 
AND b.eisbn13 LIKE '978%' 
AND len(o.ext_user_id) > 3 
AND b.bookid > 200000 
AND b.bookid in (
    SELECT bookid 
    FROM category 
    WHERE categoryid > 2 
) 
ORDER BY o.orderid DESC 

當我搜索在SQL Management Studio中使用此SQL腳本「包括實際的執行計劃」,結果讓我補充以下指數

CREATE NONCLUSTERED INDEX [<Name of Missing Index, sysname,>] 
ON [dbo].[Order] ([MODE],[ACTIVATED],[LIBRARY_ID],[BOOKID]) 
INCLUDE ([OrderID],[EXT_USER_ID],[APPROVAL_DATE]) 

Howevery如果我刪除一些有條件的地方,如下圖所示:

SELECT * FROM Book b, Library l, [Order] o 
WHERE o.bookid = b.bookID 
AND o.mode = 'A' 
AND o.library_ID = l.library_ID 
AND l.library_ID > 19 
ORDER BY o.orderid DESC 

我得到了另一個不同的推薦,如下圖所示:

CREATE NONCLUSTERED INDEX [<Name of Missing Index, sysname,>] 
ON [dbo].[ORDER] ([MODE]) 
INCLUDE ([LIBRARY_ID],[BOOKID]) 

因爲條件是可變的,我應該創建哪個索引?我理解索引是做什麼的,但不是索引字段和被包含字段之間的好處。爲什麼在第一個建議索引中,BOOKID和LIBRARY_ID位於索引字段中,但在第二個建議索引中,BOOKID和LIBRARY_ID位於包含字段中?有什麼區別,我應該用什麼來涵蓋所有可能的條件?

另外,從我的測試中,我添加了其中的每一個來測試性能,但看不到任何區別。我感謝任何幫助。

+2

**索引列**是實際的索引導航結構的一部分,例如你可以在'WHERE'子句中使用它們。 **包含的**列只存在於索引的葉級別 - 您不能使用它們來選擇行 - 並且它們在那裏,因此您的查詢可以從索引結構中滿足(查詢請求的所有列),因此您無需對實際表格數據進行昂貴的密鑰查找即可獲得您需要的一個或兩個額外列。 –

+0

@danmiao:哪個表是別名「m」引用(m.libary_ID = l.library_ID)?這是一個錯字或查詢中是否有另一個表? – 8kb

+0

嗨8kb,對不起,這是我的打字錯誤,它是'o',我已經更新,謝謝 – danmiao

回答

1

您的索引策略在一定程度上取決於數據的預期波動性 - 如果您的數據穩定並且很少更新,則可以添加更多索引以幫助查詢性能。但是,如果您的數據是易失性的並且頻繁更改,則更多索引會導致性能降低,因爲索引在數據更改時會重新生成。

它也取決於您的查詢的可預測性 - 它們是可預測的,在這種情況下將它們封裝在存儲過程或參數化查詢中,還是完全臨時?

我假設你已經有Order.BookIDOrder.Library_ID的索引?

此外,我會改寫查詢使用的內聯接語法 - 即:

SELECT * 
FROM [Order] o 
    INNER JOIN Library l 
      ON o.library_ID = l.library_ID 
    INNER JOIN Book b 
      ON o.bookid = b.bookID 
WHERE 
    o.mode = 'A' 
AND 
    l.library_ID > 19 
+0

嗨podiluska,實際上,我有'Order.BookID'和'Order.Library_ID'索引,但是,我看到你只是改變隱式內部連接到顯式內部連接,它們之間對於查詢性能是有區別的。 – danmiao

+0

不正常,但我認爲它使意圖更清楚,這可能會提高可維護性 – podiluska