TL;DR バージョン - DBMS の実装に関係なく、キー値は常にディスクに格納されます。
PostgreSQL は、挿入した行ごとに 1 行ずつ、ディスク上のページに 4 行を格納します。SQL Server は、4 行もディスクに格納します。B ツリーはルックアップ構造であり、ページ レベルのストレージ構造ではありません。
基盤となるディスク レベルでは、PostgreSQL は順序付けられていないディスク構造を使用してデータを格納します。これは、MVCC トランザクション セマンティクスにより、PostgreSQL が常に行の複数のコピーを保持している可能性があるために発生します。各行には、現在の行の作成および破棄トランザクション ID の詳細を示す xmin および xmax があります。自動バキューム プロセスは、ゴースト レコードのクリーンアップ操作を実行します。PostgreSQL のインデックスは、ヒープ テーブル構造の行を指しています。この一連のスライドは、プロセスの詳細を示しています。特に、b ツリー ルックアップがどのように発生するかについてはスライド 29 を、データがディスクに格納される方法の理論的な説明については 48 ~ 52 を参照してください。
SQL Server では、リーフ ページにレコードがありますが、行が 4 つしかないため、クラスター化インデックスには 1 つのインデックス レベル (リーフ レベル) しかありません。を実行すると、これを確認できますSELECT * FROM sys.dm_db_index_physical_stats(DB_ID(), OBJECT_ID('dbo.Tree'), NULL, NULL, NULL)
。次のような方法で、SQL Server の物理ページ レベルを確認することもできます。
-- Locate the first page of the index
DBCC IND('test', 'Tree', 1);
GO
-- tell SQL Server to show DBCC output in the message page, not the SQL Server log
DBCC TRACEON (3604);
GO
-- look at nasty, dirty, on page data.
DBCC PAGE(test, 1,155,3);
DBCC PAGE の出力を見れば、すぐに私を嫌うでしょう。最後に、次のような 4 つの行が表示されます。
Slot 0 Offset 0x60 Length 15
Record Type = PRIMARY_RECORD Record Attributes = NULL_BITMAP Record Size = 15
Memory Dump @0x000000006D6FA060
0000000000000000: 10000c00 01000000 01000000 020000††††...............
Slot 0 Column 1 Offset 0x4 Length 4 Length (physical) 4
Key = 1
Slot 0 Column 2 Offset 0x8 Length 4 Length (physical) 4
ID = 1
Slot 0 Offset 0x0 Length 0 Length (physical) 0
KeyHashValue = (e2338e2f4a9f)
これは、SQL Server が格納している実際の行データです。出力全体に Key = 1 の複数のコピーが表示され、その後に ID 情報が続きます。これらのコマンドのサポート情報は、ここにあります。
PostgreSQL と SQL Server の違いの背後にある理由は、PostgreSQL の MVCC 実装に由来します。PostgreSQL には行の複数のコピーが存在する可能性があるため、サポートするインデックス構造を変更するよりも、データの複数のコピーをディスクに保持する方が最適です。可能な限り、PostgreSQL はヒープのみの更新を行い、基礎となるテーブルの更新のみを発行します。SQL Server は同じことを行い、サポートしているインデックスの更新を回避できる場合にのみクラスター化インデックス (またはヒープ) を更新します。