优化PSQL查询的执行时间

时间:2014-04-08 05:54:37

标签: sql postgresql postgresql-performance

这是我第一次遇到query执行的长时间问题。问题实际上非常大,因为查询正在执行超过20秒,这对端点用户来说是高度可见的。

我有一个非常大的topics(~8k)数据库,主题有它的参数(这是有关的 - 我有8个主题的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

有没有办法优化此查询的执行时间?

3 个答案:

答案 0 :(得分:1)

简单的分组应该做同样的事情(如果我理解你的查询正确。

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;

顺便说一下:date是一个可怕的名字。出于一个原因,因为它也是一个保留字,但更重要的是因为它没有记录列包含的内容。 A"开始日期","结束日期","截止日期","录制日期","发布约会",......?

答案 1 :(得分:0)

对我而言DISTINCT + SUBQUERY正在扼杀你的表现。 您应该以{{1​​}}两种方式使用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"对于别名或表字段。

答案 2 :(得分: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