至於爲什麼查詢速度較慢,查詢需要按順序返回行,因此它需要進行排序,或者需要使用索引。
使用帶有CreatedDate前導列的索引,SQL Server可以避免排序。但是,SQL Server還需要訪問底層表中的頁面,以評估是否要返回該行,查看「狀態」和「名稱」列中的值。
如果優化器選擇不使用帶有CreatedDate的索引作爲前導列,那麼它需要首先找到滿足謂詞的所有行,然後執行排序操作以按順序獲取這些行。然後它可以返回排序集合中的前五十行。 (SQL Server不一定需要對整個集合進行排序,但它需要遍歷整個集合,並進行足夠的排序以確保它具有需要返回的「前五十個」。
注意:我懷疑你已經知道這一點,但要澄清:SQL Server在TOP 50
之前認可ORDER BY
。如果你想要任何50行滿足謂詞,但不一定是具有最低DateCreated值的50行,則可以重構/重寫你的查詢,得到(最多)50行,然後執行那些。
一對夫婦的意見,以改進性能
添加一個綜合指數(如其他答案建議)可能會提供一些改進,例如:
ON Documents (Status, DateCreated, Name)
SQL Server可能能夠使用該索引來滿足狀態上的相等謂詞,並且還可以在沒有排序操作的情況下以DateCreated順序返回行。 SQL服務器也可能能夠滿足來自索引的對謂詞的謂詞,限制查找到基礎表中的頁面的查找次數,這需要對要返回的行進行查找,以獲得行的「全部」列。
對於SQL Server 2008或更高版本,我會考慮篩選索引...依賴狀態的基數=「新」(即,如果滿足謂詞Status='New'
是一個相對較小的子集行表。
CREATE NONCLUSTERED INDEX Documents_FIX
ON Documents (Status, DateCreated, Name)
WHERE Status = 'New'
我還要修改查詢指定ORDER BY Status, DateCreated, Name
使order by子句的索引相匹配,它並沒有真正改變各行中返回的順序。
作爲一個更復雜的選擇,我會考慮加入一個持久化計算列,並增加對
ALTER TABLE Documents
ADD new_none_date_created AS
CASE
WHEN Status = 'New' AND COALESCE(Name,'') IN ('','None') THEN DateCreated
ELSE NULL
END
PERSISTED
;
CREATE NONCLUSTERED INDEX Documents_FIXP
ON Documents (new_none_date_created)
WHERE new_none_date_created IS NOT NULL
;
篩選索引然後查詢可以被改寫:
SELECT TOP 50 *
FROM Documents
WHERE new_none_date_created IS NOT NULL
ORDER BY new_none_date_created
;
您是否嘗試過使用索引調整嚮導? – Tarzan
數據庫在Azure中,無法對其運行。 – pmeyer