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

Postgresqlでの外部キーのインデックス作成

    tl; dr item_idにインデックスを追加する必要があります 。 Postgresインデックス作成の「黒魔術」は、11で説明されています。インデックス

    (topic_id、item_id)に複合インデックスがあります 列の順序は重要です。 Postgresはこれを使用して、 topic_idのクエリにインデックスを付けることができます 、両方の topic_idに対するクエリ およびitem_id 、ただし item_id ではありません(または効率が低下します) 一人で。

    11.3から。複数列のインデックス ...

    -- indexed
    select *
    from topics_items
    where topic_id = ?
    
    -- also indexed
    select *
    from topics_items
    where topic_id = ?
      and item_id = ?
    
    -- probably not indexed
    select *
    from topics_items
    where item_id = ?
    

    これは、(topic_id、item_id)のような複合インデックスが原因です。 最初にトピックIDを格納し、次にそのトピックIDも持つアイテムIDを格納します。このインデックスでアイテムIDを効率的に検索するには、Postgresは最初にトピックIDで検索を絞り込む必要があります。

    Postgresはできます 努力する価値があると思われる場合は、インデックスを逆にします。可能なトピックIDの数が少なく、可能なインデックスIDの数が多い場合、各トピックIDでインデックスIDが検索されます。

    たとえば、10個の可能なトピックIDと1000個の可能なアイテムIDがあり、インデックスが(topic_id、index_id)であるとします。 。これは、明確にラベル付けされたトピックIDバケットが10個あり、それぞれに明確にラベル付けされたアイテムIDバケットが1000個あるようなものです。アイテムIDバケットにアクセスするには、各トピックIDバケットの内部を調べる必要があります。 where item_id =23でこのインデックスを使用するには Postgresは、10個のトピックIDバケットのそれぞれで、アイテムID23のすべてのバケットを検索する必要があります。

    ただし、1000個の可能なトピックIDと10個の可能なアイテムIDがある場合、Postgresは1000個のトピックIDバケットを検索する必要があります。ほとんどの場合、代わりに全表スキャンを実行します。この場合、インデックスを逆にして(item_id、topic_id)にします。 。

    これは、適切なテーブル統計があるかどうかに大きく依存します。つまり、自動バキュームが正しく機能していることを確認します。

    したがって、1つの列の変動が他の列よりもはるかに少ない場合は、2つの列に対して1つのインデックスを使用する必要があります。

    Postgresは、クエリを実行すると思われる場合は、複数のインデックスを使用することもできます。より速く 。たとえば、 topic_idにインデックスがある場合 およびitem_idのインデックス 、できます 両方のインデックスを使用して、結果を組み合わせます。たとえば、 where topic_id=23またはitem_id=42 topic_idインデックスを使用してトピックID23を検索し、item_idインデックスを使用してアイテムID 42を検索し、結果を組み合わせることができます。

    これは通常、複合(topic_id、item_id)を使用するよりも時間がかかります。 索引。また、単一のインデックスを使用するよりも遅くなる可能性があるため、Postgresが複数のインデックスを使用しないことを決定しても驚かないでください。

    一般に、bツリーインデックスの場合、2つの列がある場合、3つの可能な組み合わせがあります。

    • a + b
    • a
    • b

    そして、2つのインデックスが必要です。

    • (a、b)-aおよびa + b
    • (b)-b

    (a、b) aとa+bの両方の検索をカバーします。 (b) bの検索について説明します 。

    3つの列がある場合、7つの可能な組み合わせがあります。

    • a + b + c
    • a + b
    • a + c
    • a
    • b + c
    • b
    • c

    ただし、必要なインデックスは3つだけです。

    • (a、b、c)-a、a + b、a + b + c
    • (b、c)-b、b + c
    • (c、a)-c、c + a

    ただし、実際には、3つの列にインデックスを作成することは避けたいと思うでしょう。多くの場合、遅い 。実際に欲しいのはこれです。

    • (a、b)
    • (b、c)
    • (c、a)

    インデックスからの読み取りは、テーブルからの読み取りよりも遅くなります。インデックスで読み取る必要のある行数を減らす必要がありますが、Postgresで必要以上のインデックススキャンを実行する必要はありません。



    1. Rails 3、will_paginate、ランダム、繰り返しレコード、Postgres、setseedの失敗

    2. Dockerはpostgresqlが実行されるのを待ちます

    3. Railsでpostgresの生のクエリにパラメータを渡す方法はありますか?

    4. 重複しない日時イベントの設計