2014-04-08 102 views
0

我第一次遇到query執行長時間的問題。問題實際上很大,因爲查詢在超過20秒內執行,對於端點用戶來說這是非常明顯的。優化PSQL查詢的執行時間

我有相當大的數據庫topics(〜8K),主題的有它的參數(這是dictionared - 我有8K主題113個不同的參數)。

我想顯示有關這些主題的重複次數的報告。

topic table: 
----------------+---------+----------------------------------------------------- 
id    | integer | nextval('topic_id_seq'::regclass) 
topicengine_id | integer | 
description | text | 
topicparam_id | integer | 
date   | date | 

topicparam table: 
----------------+---------+---------------------------------------------------------- 
id    | integer | nextval('topicparam_id_seq'::regclass) 
name   | text | 

和我的查詢:結果

select distinct tp.id as tpid, tp.name as desc, (select count(*) from topic where topic.topicparam_id = tp.id) as count, t.date 
from topicparam tp, topic t where t.topicparam_id =tp.id 

Total runtime: 22372.699 ms 

片段:

tpid |      topicname    | count | date 
------+---------------------------------------------+-------+--------- 
3823 | Topic1          |  6 | 2014-03-01 
3756 | Topic2          | 14 | 2014-03-01 
3803 | Topic3          | 28 | 2014-04-01 
3780 | Topic4          | 1373 | 2014-02-01 

有什麼辦法,以優化執行時間,這個查詢?

+0

請張貼的輸出'解釋analyze'(或上傳到http://explain.depesz.com)。還有哪些索引是在表格中定義的?你正在使用哪個精確的Postgres版本? –

+0

請閱讀http://stackoverflow.com/tags/postgresql-performance/info,然後適當地編輯您的問題。 –

回答

1

一個簡單GROUP BY應該做同樣的事情(如果我理解正確的查詢

select tp.id as tpid, 
     max(tp.name) as desc, 
     count(*) as count, 
     max(t.date) as date 
from topicparam tp 
    join topic t on t.topicparam_id = tp.id 
group by tp.id; 

BTW:。date是一列一個可怕的名字對於一個原因,因爲它也是一個保留詞,但更重要的是因爲它沒有記錄該列包含的內容。「開始日期」,「結束日期」,「到期日期」,「記錄日期」,「發佈日期」,...?

+0

tp.name上的max()沒有任何意義。 如果有不同日期,但根據原始查詢,max()或min()可能很有趣,可以獲得第一個主題日期或最後一個。 – Ryx5

+0

@ Ryx5:原始查詢使用'distinct',其中_seems_表示OP只需要*某些*獨特的組合。它確實看起來像是試圖獲得團隊的成就 - 但由於原始問題缺乏我必須猜測的大量必要信息。就像你在答案中所做的那樣,它也可以是所有列上的「group by」。 –

0

對我來說DISTINCT + SUBQUERY正在殺死你formance。 您應該使用GROUP BY兩種方法來「解密」您的數據並「計數」。

SELECT 
    tp.id as tpid 
    , tp.name as description 
    , count(*) as numberOfTopics 
    , t.date 
FROM 
    topicparam tp 
    INNER JOIN topic t 
     ON t.topicparam_id = tp.id 
GROUP BY 
    tp.id 
    , tp.name 
    , t.date 

考慮到大量的數據,你必須在索引注意:

在這種情況下,使用索引上topicparam.idtopic.id

上是從來沒有使用join子句列刪除索引。

儘量不要使用sql保留字,如「date,desc,count」作爲別名或表字段。

0

你可以試試這個查詢:

SELECT tp.id AS tpid, 
     tp.name AS DESC, 
     topic.cnt AS count, 
     t.date 
FROM topicparam tp 
JOIN topic t 
    ON t.topicparam_id =tp.id 
JOIN (SELECT topicparam_id, 
      count(*) cnt 
     FROM topic 
     GROUP BY topicparam_id) topic 
    ON topic.topicparam_id = tp.id 
GROUP BY tp.id, 
     tp.name, 
     t.date, 
     topic.cnt