1

我有 3 个表 Person、Names 和 Notes。每个人都有多个名字并有可选的注释。我在名称和注释的某些列上进行了全文搜索(见下文),如果我搜索的单词在结果集中或在 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 中,则速度很慢。这变慢了,因为我有 1M 的人记录和 3M+ 的名字(所有虚拟记录)。关于如何解决这个问题的任何想法?我尝试重新启动服务器,重新启动 postgresql。

4

1 回答 1

3

数据库必须在对参数有任何了解之前准备好内部查询。这可能会导致错误的查询计划。要在函数中避免此问题,请使用 plpgsql 语言并在函数内使用 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 回答