3

SQL Server がクラスター化インデックスのリーフ レベルで行のデータを格納できることを知っています。PostgreSQL はこれを行わないと思います。もしそうなら、そのストレージパラダイムは何ですか?

私の主な質問は次のとおりです。次の設計とデータを検討してください (T-SQL に示されています)。

CREATE TABLE dbo.Tree
    (
    [Key] int NOT NULL,
    ID int NOT NULL
    ) ON [PRIMARY]
GO
ALTER TABLE dbo.Tree ADD CONSTRAINT
    PK_Tree PRIMARY KEY CLUSTERED 
    (
    [Key],
    ID
    ) WITH (...) ON [PRIMARY]

INSERT INTO TREE ([Key], ID) VALUES (1, 1), (1, 2), (1, 3), (1, 4).

これは両方の列を PK とする btree であるため、「[Key] = 1」は 1 回だけ格納され、「ID = [1, 2, 3, 4]」は個々の値になるというのは正しいでしょうか。 PK の一部ではない行列がないため、sé ごとに葉の値はありませんが、btree ですか?

これは PostgreSQL でどのように機能しますか?

4

4 に答える 4

14

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 は同じことを行い、サポートしているインデックスの更新を回避できる場合にのみクラスター化インデックス (またはヒープ) を更新します。

于 2011-03-14T16:53:21.820 に答える
2

SQL Serverは、行のデータをリーフレベルでクラスター化インデックスに格納できることを知っています。PostgreSQLはこれを行わないと思います。もしそうなら、そのストレージパラダイムは何ですか?

SQL Server他のエンジンとは異なりPostgreSQL、レコードを変更したトランザクションのIDをインデックスに格納せず、ヒープにのみ格納します。

インデックスはヒープを指しているだけです(そしてctid、適切なレコードのを行ポインタとして、したがってキーの一部として格納します)。

つまり、クエリごとに、インデックスルックアップで満たすことができたとしても、現在のトランザクションに対するデータの可視性を確保するために、ヒープルックアップを実行する必要があります。

したがって、インデックスをカバーすることは、次の場合にはそれほど有用ではありませんPostgreSQL。ヒープルックアップはとにかく行う必要があるため、エンジンはヒープからすべてのデータを取得できます。

于 2011-03-14T17:04:37.003 に答える
2

インデックス作成全般について詳しく知りたい場合は、私のSQL インデックス作成チュートリアルをご覧ください。

于 2011-03-14T17:53:49.427 に答える
2

あなたは正しいです - Postgresはあなたが求めていることをすることができません. 詳細については、この質問を参照してください。

コマンドを使用して行のクラスタリングを実現できますCLUSTERが、DML を実行すると、データのクラスタリングは維持されません。

于 2011-03-14T08:02:55.017 に答える