1

Person、Names、Notesの3つのテーブルがあります。各人には複数の名前があり、オプションのメモがあります。名前とメモのいくつかの列で全文検索を行っています(以下を参照)。検索する単語が結果セットまたはdbにある場合、これらは完全に機能しています。これは、カスタム関数、php、およびpsql用です。問題は、検索した単語がデータベースに存在しない場合、phpとカスタム関数ではクエリが非常に遅くなりますが、psqlでは高速になることです。psqlでは1秒未満、その他は10秒以上です。

テーブル:

Person | id, birthday  
Name   | person_id, name, fs_name  
Notes  | person_id, note, fs_note  

PKおよびFKインデックスのほかに、fs_nameおよびfs_noteのGinインデックス。

関数/クエリ

create or replace function queryNameFunc (TEXT)
returns TABLE(id int, name TEXT) as $$

    select id, name
    from person_name pnr
    inner join person pr on (pnr.person_id=pr.id) 
    left join personal_notes psr on (psr.person_id = pr.id) 
    where pr.id in 
        (select distinct(id)
         from person_name pn
         inner join person p on (p.id = pn.person_id)
         left join personal_notes ps on (ps.person_id = p.id)
         where tname @@ to_tsquery($1)
         limit 20);

$$ language SQL;

where条件はここで切り捨てられます。たとえば、$ 1で「john&james」を実行し、データがdbにある場合、結果は高速ですが、「john and james」がdbにない場合は、低速になります。個人に100万件、名前に300万件以上のレコード(すべてダミーレコード)があるため、これは遅くなりました。これを修正する方法について何かアイデアはありますか?サーバーを再起動して、postgresqlを再起動してみました。

4

1 に答える 1

3

データベースは、パラメータに関する知識を得る前に、内部クエリを事前に準備する必要があります。これにより、クエリプランが不適切になる可能性があります。関数でこの問題を回避するには、plpgsql-languageを使用し、関数内でEXECUTEを使用します。

CREATE OR REPLACE FUNCTION queryNameFunc (TEXT) RETURNS TABLE(id INT, name TEXT) AS $$
BEGIN
    RETURN QUERY EXECUTE '
        SELECT 
            id, 
            name 
        FROM 
            person_name pnr
                INNER JOIN person pr ON (pnr.person_id=pr.id)
                LEFT JOIN personal_notes psr ON (psr.person_id = pr.id)
               WHERE 
            pr.id IN(
                SELECT 
                    DISTINCT(id) 
                FROM 
                    person_name pn
                        INNER JOIN person p ON (p.id = pn.person_id)
                        LEFT JOIN personal_notes ps ON (ps.person_id = p.id)
                        WHERE tname @@ to_tsquery($1)
                        LIMIT 20)' USING $1;
END;
$$ LANGUAGE plpgsql;

これはバージョン8.4で機能し、plpgsqlをインストールする必要があります。

CREATE LANGUAGE plpgsql;
于 2010-07-27T11:14:54.040 に答える