19

PostgreSQLで複数カラムの組み合わせを指定したPRIMARY KEY場合、レコードはどのように並びますか?

これは、PostgreSQL が主キーの順序でレコードを並べ替えると仮定した場合です。そうですか?

また、PostgreSQLの場合、主キーは自動的にインデックスされますか?

4

1 に答える 1

54

この質問は、主キーがテーブルの順序を強制するという誤った仮定をしています。そうではありません。PostgreSQL テーブルには、主キーの有無にかかわらず、順序が定義されていません。これらは、ページ ブロックに配置された行の「ヒープ」です。ORDER BY順序付けは、必要に応じてクエリ句を使用して課されます。

PostgreSQL テーブルは、主キーの順序でディスクに格納されるインデックス指向のテーブルとして格納されると考えているかもしれませんが、それは Pg の仕組みではありません。InnoDB は主キーによって編成されたテーブルを格納すると思いますが (チェックはしていません)、「クラスター化インデックス」または「インデックス編成テーブル」と呼ばれることが多い機能を使用する他のベンダーのデータベースではオプションです。この機能は、現在 PostgreSQL ではサポートされていません (少なくとも 9.3 以降)。

つまり、PRIMARY KEYはインデックスを使用して実装されており、UNIQUEそのインデックスには順序付けがあります。のように、インデックス (したがって主キー) の左の列から昇順で並べ替えられますORDER BY col1 ASC, col2 ASC, col3 ASC;b+treesを使用して実装されているため、PostgreSQL の他の b-tree (GiST または GIN とは異なる) インデックスにも同じことが当てはまります。

したがって、表では:

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;

これらのどちらも主キー インデックスをまったく使用できません。インデックスがない限り、seqscan を実行しますb

SELECT * FROM demo ORDER BY b, a;
SELECT * FROM demo ORDER BY b;

これは、PostgreSQL が単独でインデックスを使用するのと(a,b)ほぼ同じ速度でインデックスを使用できるため(a)です。(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

于 2012-11-02T07:28:16.907 に答える