2011-05-10 44 views
3

版:SQL Server 2008 R2的獲取SQL Server使用索引查找+鍵查找,而不是聚集索引掃描,而不(FORCESEEK)

數據庫:AdventureWorks的2008R2從http://msftdbprodsamples.codeplex.com/releases/view/55926

查詢:

SELECT TOP 10 
    * 
FROM 
    Person.Person --WITH (FORCESEEK) 
WHERE 
    LastName like 'Max%' 
    OR EXISTS (
     SELECT 
      1 
     FROM 
      Person.PersonPhone 
     WHERE 
      Person.PersonPhone.BusinessEntityID = Person.Person.BusinessEntityID 
      AND Person.PersonPhone.PhoneNumber LIKE '122%' 
    ) 
ORDER BY Person.Person.BusinessEntityID DESC 


沒有任何的查詢提示,SQL Server將使用聚集索引掃描,這是IO密集型:

Table 'PersonPhone'. Scan count 14170, logical reads 28446, physical reads 15, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0. 
Table 'Person'. Scan count 1, logical reads 2844, physical reads 3, read-ahead reads 3215, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0. 


隨着WITH (FORCESEEK)查詢提示,SQL Server將選擇索引查找+鍵查找,完成速度更快,是500X親切的IO:

Table 'Person'. Scan count 1, logical reads 59, physical reads 22, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0. 
Table 'PersonPhone'. Scan count 1, logical reads 2, physical reads 2, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0. 


我的問題是,是否有任何如何讓SQL Server在沒有任何查詢提示的情況下使用更好的計劃?可能添加索引?或者更改配置參數?還是SQL Server的查詢優化器無能爲力?

下面是從http://msdn.microsoft.com/en-us/library/bb510478.aspx寶石:

查詢優化規則和基數的不良估計也會導致優化器執行表或索引掃描操作,而不是一個索引時查詢使用IN或LIKE作爲搜索尋求謂詞。

+1

SQL Server將自動參數化一些查詢 - 我不知道具體情況,但是,它可能是它試圖優化上面的任何LIKE ...值,並且因此正在爲此做出糟糕的計劃選擇特定的搜索。 – 2011-05-10 06:36:59

+0

@marc_s,如果您閱讀了這個問題,您可以看到沒有任何查詢提示,查詢優化器將選擇需要500倍以上IO的計劃。也許它發現我的磁盤閒置並渴望工作?這可能是一個很好的理由。無論如何,假設你再次讀過這個問題,你可以看到我正在尋求一種方法來幫助查詢優化器在沒有FORCESEEK的情況下選擇更好的計劃。 – sayap 2011-05-10 06:38:43

+0

我不認爲SQL Server會查找硬件,並決定特定的計劃是好的,因爲硬件目前閒置 - 計劃創建是昂貴的。資源 - 並且計劃通常是在考慮到重用的情況下創建的。 – 2011-05-10 06:57:32

回答

3

這是一個版本,展示'體面'的IO數字,而不訴諸FORCESEEK。 有趣的是,這個可怕的查詢執行「更好」。

免責聲明:本可以執行的「馬克斯%」和「122%」更好,但如果該計劃被重用爲「M%」和「%」是另一回事,它會表現如何?

SELECT TOP 10 * 
FROM Person.Person P 
INNER JOIN (
SELECT BusinessEntityID 
FROM Person.Person --WITH (FORCESEEK) 
WHERE LastName like 'Max%'  

UNION 

SELECT BusinessEntityID 
FROM Person.Person --WITH (FORCESEEK) 
WHERE EXISTS (  SELECT   *  FROM   
    Person.PersonPhone  WHERE   Person.PersonPhone.BusinessEntityID = Person.Person.BusinessEntityID   AND Person.PersonPhone.PhoneNumber LIKE '122%' ) 
) NOTNICE 
ON NOTNICE.BusinessEntityID = P.BusinessEntityID 
ORDER BY P.BusinessEntityID DESC 
+0

謝謝,這個工程。不幸的是,它不是很「友好」。 – sayap 2011-05-10 07:32:03

+1

那麼,在SQLAlchemy中,沒有「不ORM友好」之類的東西。我已經成功實現了這一點。再次感謝您的答覆。 – sayap 2011-05-10 08:56:10

相關問題