sql >> データベース >  >> RDS >> Sqlserver

SQL Server はどのようにデータをソートしますか?

    同じ順序が頻繁に見られることをどのように説明できるか疑問に思うのは良いことですが、基礎となるデータベース エンジンの特定の実装によって引き起こされる暗黙の順序に依存することは決して良い考えではないことを指摘しておきます。言い換えれば、その理由を知ることは良いことですが、決してそれに頼るべきではありません. MS SQL の場合、行を特定の順序で確実に配信する唯一のものは、明示的な ORDER BY です。

    異なる RDMBS の動作が異なるだけでなく、更新 (パッチ) によって特定のインスタンスの動作が異なる場合があります。それだけでなく、RDBMS ソフトウェアの状態も影響を与える可能性があります。「ウォーム」データベースは「コールド」データベースとは異なる動作をし、小さなテーブルは大きなテーブルとは異なる動作をします。

    実装に関する背景情報がある場合でも (例:「クラスター化インデックスがあるため、クラスター化インデックスの順序でデータが返される可能性が高い」)、別のメカニズムが存在する可能性が常にあります。それが原因で行が異なる順序で返されることを知らない (例 1:「別のセッションが明示的な ORDER BY を使用して完全なテーブル スキャンを実行した場合 結果セットがキャッシュされている可能性があります。後続のフル スキャンでは、キャッシュから行を返そうとします"; ex2:"GROUP BY データをソートすることで実装できるため、行が返される順序に影響を与える可能性があります"; ex3:"選択した列がすべて、メモリに既にキャッシュされているセカンダリ インデックスにある場合、エンジンはテーブルではなくセカンダリ インデックスをスキャンする可能性があります。ほとんどの場合、セカンダリ インデックスの順序で行を返します").

    これは、私のポイントのいくつかを示す非常に簡単なテストです。

    まず、SQL サーバーを起動します (私は 2008 を使用しています)。このテーブルを作成します:

    create table test_order (id int not null identity(1,1) primary key, name varchar(10) not null )  

    テーブルを調べて、主キー をサポートするためにクラスター化インデックスが作成されたことを確認します。 id で 桁。たとえば、SQL Server Management Studio では、ツリー ビューを使用して、テーブルの下にあるインデックス フォルダーに移動できます。 PK__test_ord__3213E83F03317E3D (Clustered) のような名前のインデックスが 1 つ表示されます。

    次のステートメントで最初の行を挿入します:

    insert into test_order(name)select RAND()  

    このステートメントを 16 回繰り返して、さらに行を挿入します。

    insert into test_order(name)select RAND() from test_order  

    これで 65536 行になるはずです:

    test_order から COUNT(*) を選択  

    ここで、order by を使用せずにすべての行を選択します:

    select *from test_order  

    ほとんどの場合、結果は主キーの順序で返されます (保証はありませんが)。私が得た結果は次のとおりです (これは実際には主キーの順序です):

    # id name1 1 0.6058312 2 0.5172513 3 0.52326. . .......65536 65536 0.902214  

    (# は列ではなく、結果における行の序数位置です)

    次に、name にセカンダリ インデックスを作成します。 列:

    test_order(name) にインデックス idx_name を作成  

    すべての行を選択しますが、name のみを取得します 列:

    select namefrom test_order  

    ほとんどの場合、結果はセカンダリ インデックス idx_name の順序で返されます。これは、インデックスをスキャンするだけでクエリを解決できるためです (i.o.w. idx_name カバーです 索引)。これは私が得た結果です。これは実際には name の順序です .

    # name1 0.01857322 0.0185732. .........65536 0.981894  

    次に、すべての列とすべての行をもう一度選択します:

    select * from test_order  

    これが私が得た結果です:

    # id name1 17 0.01857322 18 0.01857323 19 0.0185732... .. .........  

    ご覧のとおり、このクエリを最初に実行したときとはかなり異なります。 (行はセカンダリ インデックスによって並べ替えられているように見えますが、なぜそうすべきかについての説明はありません)。

    とにかく、肝心なのは、暗黙の順序に頼らないことです。特定の順序が観察される理由を考えることはできますが、それでも実装と実行時の状態に関する詳細な知識がなければ (後者の場合のように) 常に予測できるとは限りません。



    1. 単純なパラメータ化と簡単な計画—パート3

    2. 大規模なMySQLデータベースの移動とバックアップ

    3. 2つの日付の間のすべての週をリストするストアドプロシージャ

    4. oracleconnectbyを使用して隣接リストモデル内のすべてのノードを検索します。