ORDER BY
句なしの順序付けされた結果セットの外観は、多くの場合、インデックス順で行を取得するスキャンの結果です。通常、デフォルトのREAD COMMITTED
分離レベルの下でインデックス順スキャンが選択される理由の1つは、同じ行に複数回遭遇したり、一部の行を完全にスキップしたりするなど、不要な同時実行の異常の可能性を減らすためです。これについては、分離レベルに関するこの一連の記事を含め、いくつかの場所で詳しく説明されています。
NOLOCK
テーブルヒント、この現象は緩和され、テーブルへのアクセスはより耐性で行われるREAD UNCOMMITTED
ことができる分離レベル、割当順にデータをスキャンする代わりに、インデックス順の。そのリンクで説明されているように、割り当て順スキャンとインデックス順スキャンのどちらを使用するかについての決定は、ストレージエンジンに任されています。この選択は、クエリプランを変更せずに、実行間で変わる可能性があります。
これは非常に抽象的なように聞こえるかもしれませんが、AdventureWorks2012データベースに対して文書化されていない関数を使用するいくつかのクエリでより簡単に示すことができます。
USE AdventureWorks2012;
GO
-- Appears to be ordered by BusinessEntityID
-- File:Page:Slot goes up and down several times
-- Show physical locations with sys.fn_PhysLocFormatter (undocumented)
SELECT
P.BusinessEntityID,
[(File:Page:Slot)] =
sys.fn_PhysLocFormatter(%%physloc%%)
FROM Person.Person AS P;
-- Same query with TABLOCK or NOLOCK
-- Allocation-order (IAM) scan
-- Now appears to be ordered by File:Page:Slot instead of BusinessEntityID
SELECT P.BusinessEntityID,
[(File:Page:Slot)] =
sys.fn_PhysLocFormatter(%%physloc%%)
FROM Person.Person AS P WITH (NOLOCK);
クエリは、Paul Whiteから少し変更して借用しました。
最後に、明確にするために、この答えは順序付けられた結果セットの外観についてです。トップレベルがなければ、保証された表示順序はありませんORDER BY
。
割り当て順スキャンは、テーブルレベルのロックが取得されたときや、データベースが読み取り専用モードになっているときなど、他のさまざまな状況で発生する可能性があります。並列処理は、データが返される順序にも影響を与える可能性があります。重要な点は、を使用しないORDER BY
場合、データが返される順序は設計により時間とともに変化する可能性があるということです。