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

複合主キーを持つテーブルのレコードの順序は何ですか

    この質問は、主キーがテーブルの順序をまったく課していないという誤った仮定をします。そうではありません。 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人。




    1. 列にNULLが含まれるレコードを検索する方法

    2. MySQLiを使用してデータベースにデータを挿入する

    3. 挿入できません:エラー:配列値は{またはディメンション情報で始まる必要があります

    4. OracleのNLS_COLLATION_ID()関数