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

トリグラムインデックスを使用しないLATERALJOIN

    なぜですか?

    クエリはプリンシパルのインデックスを使用できません。テーブルのlocationsにインデックスが必要になります 、しかしあなたが持っているものはテーブルaddressesにあります 。

    次の設定で私の主張を確認できます:

    SET enable_seqscan = off;
    

    (セッションのみ、デバッグのみ。本番環境では絶対に使用しないでください。)インデックスがシーケンシャルスキャンよりも高価になるわけではなく、Postgresがクエリに使用する方法はまったくありません

    余談:[INNER] JOIN ... ON true CROSS JOIN ...の厄介な言い方です

    ORDERを削除した後にインデックスが使用されるのはなぜですか およびLIMIT

    Postgresはこの単純なフォームを次のように書き換えることができるため:

    SELECT *
    FROM   addresses a
    JOIN   locations l ON a.address ILIKE '%' || l.postalcode || '%';
    

    まったく同じクエリプランが表示されます。 (少なくとも、Postgres 9.5でのテストでは行います。)

    ソリューション

    locations.postalcodeにインデックスが必要です 。そして、LIKEを使用している間 またはILIKE また、インデックス付きの式(postalcode)を持参する必要があります ) オペレーターの側。 ILIKE 演算子~~*で実装されます この演算子にはCOMMUTATORがありません (論理的に必要)、したがって、オペランドを反転させることはできません。これらの関連する回答の詳細な説明:

    解決策は、トリグラム類似性演算子 % またはその逆、距離演算子<-> 最も近い隣人で 代わりにクエリを実行します(それぞれがそれ自体の整流子であるため、オペランドは場所を自由に切り替えることができます):

    SELECT *
    FROM   addresses a
    JOIN   LATERAL (
       SELECT *
       FROM   locations
       ORDER  BY postalcode <-> a.address
       LIMIT  1
       ) l ON address ILIKE '%' || postalcode || '%';

    最も類似したpostalcodeを見つける addressesごとに 、次にそのpostalcodeかどうかを確認します 実際には完全に一致します。

    このように、より長いpostalcode 短いpostalcodeよりも類似している(距離が短い)ため、自動的に優先されます それも一致します。

    少し不確実性が残っています。考えられる郵便番号によっては、文字列の他の部分のトリグラムが一致するために誤検知が発生する可能性があります。質問には、詳細を述べるのに十分な情報がありません。

    ここ[INNER] JOIN CROSS JOINの代わりに 実際の結合条件を追加するので、理にかなっています。

    マニュアル:

    だから:

    CREATE INDEX locations_postalcode_trgm_gist_idx ON locations
    USING gist (postalcode gist_trgm_ops);
    


    1. Oracleでのステートメントの最大長はどれくらいですか

    2. SSRS:SSRSドロップダウンフィルターにすべてのオプションを追加するにはどうすればよいですか?

    3. 列のすべての値を小文字に更新します

    4. MySQLの選択/挿入/更新、列の順序は重要ですか?