1

我有3個表人名,名稱和註釋。每個人有多個名字並有可選的筆記。我在名稱和註釋的某些列上進行了全文搜索(請參見下文),如果搜索詞位於結果集中或位於db中,那麼它們可以很好地工作,這是針對自定義函數,php和psql的。現在的問題是,當我搜索的單詞不在數據庫中時,該查詢在php和自定義函數中速度超慢,但在psql上仍然很快。在psql上它不到1秒,其他則超過10秒。Postgresql緩慢的自定義功能,但速度快,如果直接輸入在psql上使用杜松子酒索引文本搜索

表:

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

除了PK和FK指數,杜松子酒指數fs_name和fs_note。

功能/查詢

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和數據是對DB則結果是快,但如果'約翰和詹姆斯'不在db那麼它很慢。由於我在人身上有1M個記錄,名稱上有3M +(所有虛擬記錄),因此速度變慢。任何想法如何解決這個問題?我嘗試重新啓動服務器,重新啓動postgresql。

回答

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; 
+0

很大,其工作很好,問題,什麼是使用$ 1的部分,這是否意味着如果我有多個參數,我會使用$ 1,$ 2,$ 3做什麼?如果我有多個參數,最好在if-else或where條件部分變成參數時執行它? ($ 1 ==「tname @@ ..」)非常感謝 – monmonja 2010-07-28 02:48:02

+0

是的,使用$ 1,$ 2,$ 3是您如何使用多個參數。 USING避免了函數內部的SQL注入,這就是爲什麼當你有動態查詢時需要這個(EXECUTE)的原因。 – 2010-07-28 05:26:25