web-dev-qa-db-ja.com

順序指定が指定されていない場合、SELECT TOPはどのように機能しますか?

msdn documentation は、

SELECT TOP(N) ..... ORDER BY [COLUMN]

columnascまたはdescの選択に応じて)でソートされたtop(n)行を取得します。

しかし、順序を指定しない場合、msdnはrandomGail Erickson指摘 ここ 。彼が指摘するように、それはunspecifiedではなくrandomであるべきです。しかし、Thomas Leeが指摘している

TOPをORDER BY句と組み合わせて使用​​すると、結果セットは順序付けられた行の最初のN個に制限されます。それ以外の場合は、最初のN行をランダムに返します

そのため、インデックスを持たないテーブルでこのクエリを実行しました。最初にこれを実行しました。

SELECT *
FROM
    sys.objects so
WHERE
    so.object_id NOT IN (SELECT si.object_id
                         FROM
                             sys.index_columns si)
    AND so.type_desc = N'USER_TABLE'

そして、それらのテーブルの1つで(実際、上記のクエリで返されたすべてのテーブルで以下のクエリを試しました)、常に同じ行を取得しました

SELECT TOP (2) *
FROM
    MstConfigSettings

これは常に同じ2行を返し、クエリ1によって返される他のすべてのテーブルにも同じことが当てはまります。これで、実行プランは3つのステップを示します。

enter image description here

ご覧のとおり、インデックスルックアップはありません。これは単なるテーブルスキャンであり、

enter image description here

Topは、実際の行数が2であることを示しているため、Table Scan;これはそうではありません(行がたくさんあります)。

しかし、私が何かを実行すると

SELECT TOP (2) *
FROM
    MstConfigSettings
ORDER BY
    DefaultItemId

実行計画は

enter image description here

そして

enter image description here

だから、私が適用しないときはORDER BY手順が異なります(並べ替えはありません)。しかし、問題は、TOPがない場合にこのSortがどのように機能するか、そしてなぜ、どのようにalwaysが得られるかです。同じ結果ですか?

19
Razort4x

どの2つの行が取得されるかは保証されません。これは、テーブルスキャンから取得された最初の2つにすぎません。

実行プランのTOPイテレーターは、2行が返されると行の要求を停止します。

ヒープのスキャンの場合、これは割り当て順の最初の2行になりますが、これは保証されていません。たとえば、SQL Serverは 高度なスキャン 機能を使用する場合があります。これは、スキャンが別の同時スキャンから最近読み取られたページを読み取ることを意味します。

20
Martin Smith