Postgresql 9.1 - 子查询计数(*)seq扫描 - 低性能

时间:2015-08-12 08:01:44

标签: postgresql

我的查询需要花费很长时间才能执行; s限制和orderer按整数值索引。我红了,问题在于子查询中的count(*) - 但我找不到解决方案

POSTGRESQL 9.1

QUERY:

SELECT
   sms.id,
  (select count(*) 
   from sms_received, sms_recipient 
   where sms.id = sms_recipient.sms_id
     and sms_recipient.id = sms_received.sms_recipient_id ) as pocet_resp
FROM "sms" WHERE done = true
ORDER BY "sms"."id" desc limit 100;

EXPLAIN ANALYZE输出:

Limit  (cost=0.00..377992.17 rows=100 width=4) (actual time=58.566..5549.074 rows=100 loops=1)
   ->  Index Scan using sms_id on sms  (cost=0.00..1701422117.01 rows=450121 width=4) (actual time=58.564..5548.913 rows=100 loops=1)
         Filter: done
         SubPlan 1
           ->  Aggregate  (cost=3778.61..3778.62 rows=1 width=0) (actual time=55.471..55.471 rows=1 loops=100)
                 ->  Hash Join  (cost=660.83..3778.59 rows=6 width=0) (actual time=55.276..55.456 rows=0 loops=100)
                       Hash Cond: (sms_received.sms_recipient_id = sms_recipient.id)
                       ->  Seq Scan on sms_received  (cost=0.00..2656.33 rows=123033 width=4) (actual time=0.002..30.758 rows=123039 loops=100)
                       ->  Hash  (cost=658.73..658.73 rows=168 width=4) (actual time=0.060..0.060 rows=27 loops=100)
                             Buckets: 1024  Batches: 1  Memory Usage: 1kB
                             ->  Bitmap Heap Scan on sms_recipient  (cost=5.92..658.73 rows=168 width=4) (actual time=0.036..0.047 rows=27 loops=100)
                                   Recheck Cond: (sms.id = sms_id)
                                   ->  Bitmap Index Scan on sms_rec_sms_id  (cost=0.00..5.87 rows=168 width=0) (actual time=0.026..0.026 rows=140 loops=100)
                                         Index Cond: (sms.id = sms_id)
 Total runtime: 5549.237 ms

2 个答案:

答案 0 :(得分:0)

也许这会有所帮助:

select    sms.id,
          count(*) 
from      sms
left join sms_received on sms.id            = sms_recipient.sms_id
left join sms_recipient on sms_recipient.id = sms_received.sms_recipient_id
where     sms.done = true and
          sms.id in (select id from sms order by id desc limit 100)
group by  sms.id
order by  sms.id desc

您也可以尝试:

select    sms.id,
          count(*) 
from      sms
left join sms_received on sms.id            = sms_recipient.sms_id
left join sms_recipient on sms_recipient.id = sms_received.sms_recipient_id
where     sms.done = true and
group by  sms.id
order by  sms.id desc
limit     100

......但我不确定它会如此高效。

答案 1 :(得分:0)

我用触发器解决了这个问题 - 触发计数插入行,所以我不需要使用count(*)。