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

postgres類似性クエリの最適化(pg_trgm + ginインデックス)

    大いに期待しています このアプローチでより速い結果:

    1。

    連結された値を保持する1つの列を持つGiSTインデックスを作成します:

    CREATE INDEX users_search_idx ON auth_user
    USING gist((username || ' ' || first_name || ' ' || last_name) gist_trgm_ops);
    

    これは、3つの列すべてがNOT NULLで定義されていることを前提としています。 (指定しませんでした)。それ以外の場合は、さらに多くのことを行う必要があります。
    concat_ws()で単純化してみませんか ?

    2。

    適切な最近傍 を使用します クエリ、上記のインデックスに一致:

    SELECT username, email, first_name, last_name
         , similarity(username  , $1) AS s_username
         , similarity(first_name, $1) AS s_first_name
         , similarity(last_name , $1) AS s_last_name
         , row_number() OVER () AS rank  -- greatest similarity first
    FROM   auth_user
    WHERE     (username || ' ' || first_name || ' ' || last_name) %   $1  -- !!
    ORDER  BY (username || ' ' || first_name || ' ' || last_name) <-> $1  -- !!
    LIMIT  $2;
    

    WHEREの式 およびORDER BY インデックス式と一致する必要があります!

    特にORDER BY rank (あなたが持っていたように)小さなLIMITでは常にパフォーマンスが低下します インデックスを直接使用できないため、修飾行のはるかに大きなプールから選択します。rankの背後にある洗練された式 すべてについて計算する必要があります 適格な行の場合、最適な一致の小さな選択を返す前に、すべてを並べ替える必要があります。これははるかに高価です 残りの部分を見なくても、インデックスから直接最良の結果を選択できる真の最近傍クエリよりも。

    row_number() 空のウィンドウ定義では、ORDER BYによって生成された順序が反映されます。 同じSELECTの 。

    関連する回答:

    アイテムは3. 、あなたが参照した質問に答えを追加しました。それはそれを説明するはずです:




    1. Oracleの日付にAD/BCインジケーターを追加する方法

    2. データをロードするファイルのデフォルト値がテーブルに挿入されない

    3. mysqlでnull<>null=nullなのはなぜですか

    4. Python経由でXAMPPmysqlにアクセスする