7

バージョン:SQL Server 2008 R2

データベース:http://msftdbprodsamples.codeplex.com/releases/view/55926のAdventureWorks 2008R2

クエリ:

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


クエリのヒントがない場合、SQLServerは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.


クエリヒントを使用すると、SQL Serverはインデックスシーク+キールックアップを選択します。これWITH (FORCESEEK)は、より高速に完了し、IOに対して500倍親切です。

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を使用する場合、オプティマイザはインデックスシークではなくテーブルまたはインデックススキャン操作を実行する可能性があります。

4

1 に答える 1

5

これは、FORCESEEKに頼らずに「まともな」IO数値を示すバージョンです。この恐ろしい見た目のクエリが「より良い」パフォーマンスを発揮するのは興味深いことです。

免責事項:これは「Max%」と「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
于 2011-05-10T06:46:36.097 に答える