この質問は、主キーがテーブルの順序をまったく課していないという誤った仮定をします。そうではありません。 PostgreSQLテーブルには、主キーの有無にかかわらず、定義された順序はありません。それらは、ページブロックに配置された行の「ヒープ」です。注文はORDER BY
を使用して行われます 必要に応じてクエリの句。
PostgreSQLテーブルは、主キーの順序でディスクに保存されるインデックス指向のテーブルとして保存されていると思われるかもしれませんが、それはPgの動作方法ではありません。 InnoDBは、主キーで整理されたテーブルを格納していると思います(ただし、チェックされていません)。他のベンダーのデータベースでは、「クラスター化インデックス」または「インデックス整理テーブル」と呼ばれる機能を使用するオプションです。この機能は現在PostgreSQLではサポートされていません(少なくとも9.3以降)。
そうは言っても、PRIMARY KEY
UNIQUE
を使用して実装されます インデックス、およびそのインデックスへの順序があります。 ORDER BY col1 ASC, col2 ASC, col3 ASC;
のように、インデックスの左の列(したがって主キー)から昇順で並べ替えられます。 。同じことがPostgreSQLの他のbツリー(GiSTやGINとは異なる)インデックスにも当てはまります。これらはb+ツリーを使用して実装されているからです。
したがって、表では:
CREATE TABLE demo (
a integer,
b text,
PRIMARY KEY(a,b)
);
システムは自動的に次のものに相当するものを作成します:
CREATE UNIQUE INDEX demo_pkey ON demo(a ASC, b ASC);
これは、テーブルを作成するときに報告されます。例:
regress=> CREATE TABLE demo (
regress(> a integer,
regress(> b text,
regress(> PRIMARY KEY(a,b)
regress(> );
NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "demo_pkey" for table "demo"
CREATE TABLE
テーブルを調べると、このインデックスを確認できます:
regress=> \d demo
Table "public.demo"
Column | Type | Modifiers
--------+---------+-----------
a | integer | not null
b | text | not null
Indexes:
"demo_pkey" PRIMARY KEY, btree (a, b)
CLUSTER
できます このインデックスで主キーに従ってテーブルを並べ替えますが、これは1回限りの操作です。システムはその順序を維持しません-ただし、デフォルト以外のFILLFACTOR
が原因でページに空きがある場合は、 しようと思います。
インデックス(ヒープではない)の固有の順序の1つの結果は、それが多くであるということです。 検索が速くなります:
SELECT * FROM demo ORDER BY a, b;
SELECT * FROM demo ORDER BY a;
より:
SELECT * FROM demo ORDER BY a DESC, b;
これらはどちらも主キーインデックスをまったく使用できません。b
にインデックスがない限り、seqscanを実行します。 :
SELECT * FROM demo ORDER BY b, a;
SELECT * FROM demo ORDER BY b;
これは、PostgreSQLが(a,b)
のインデックスを使用できるためです。 (a)
のインデックスとほぼ同じ速さ 1人。 (a,b)
のインデックスは使用できません (b)
のインデックスであるかのように 一人で-ゆっくりではなく、それはできません。
DESC
は そのため、1つのPgは逆インデックススキャンを実行する必要があります。これは、通常の順インデックススキャンよりも低速です。 EXPLAIN ANALYZE
で多くの逆インデックススキャンが表示されている場合 また、DESC
のフィールドにインデックスを作成できる、追加のインデックスのパフォーマンスコストを支払う余裕があります。 注文します。
これはWHERE
にも当てはまります ORDER BY
だけでなく句 。 (a,b)
でインデックスを使用できます WHERE a = 4
を検索するには またはWHERE a = 4 AND b = 3
しかし、 WHERE b = 3
を検索するには 1人。