PostgreSQL查询因语句超时而突然终止

时间:2014-10-29 18:30:14

标签: performance postgresql query-optimization

我试图优化需要花费太多时间的查询。这就是我所拥有的

  • table1(field1,field2 ... field14):包含大约850万行
  • table2(f1,f2,f3):包含约250万行

查询就是这个

SELECT 
   value1,
   value2,
   value3,
   value4,
   value5, 
   hstore(
       ARRAY['field9', 'field10', 'field11', 'field12', 'field13', 'field14'],     
       ARRAY[field9, field10, field11, field12, field13, field14) as metadata, 
   value7, 
  (select array((select row(f1, f2) from table2 p where p.f3 = field7))) as values_array 
FROM table1

解释分析告诉我这个

                                     QUERY PLAN                                                                   
-------------------------------------------------------------------------------------------
 Index Scan using table1_pkey on table1  (cost=67846.38..395773.45 rows=8419127 width=88) (actual time=7122.704..22670.680 rows=8419127 loops=1)
   InitPlan 2 (returns $1)
     ->  Result  (cost=67846.29..67846.29 rows=1 width=0) (actual time=7009.063..7009.065 rows=1 loops=1)
           InitPlan 1 (returns $0)
             ->  Seq Scan on table2 p  (cost=0.00..67846.29 rows=12689 width=20) (actual time=14.971..5069.840 rows=2537787 loops=1)
                   Filter: (f3 = field7)

因此,顺序扫描table2 (在查询中获取values_array),而不是索引扫描。可能是因为SELECT返回表中所有行的大约5-10%? (我听说在这种情况下,顺序扫描比索引扫描更快,因为每行需要的I / O操作量。)

无论如何,该查询中有什么明显的错误吗?服务器只是因为超时而终止

如果我通过添加 LIMIT 1000 OFFSET 0 来限制行返回量,则需要 3分钟,但覆盖整个表格(请记住:850万条记录)通过移动OFFSET,我需要大约8000次迭代。每个3分钟意味着超过15天......这是不可接受的。此外,大的OFFSETS也意味着表现不佳。

任何见解?在PostgreSQL列表中,他们建议我用JOIN替换内部查询,并使用复合类型而不是数组。我正在努力,但我有点坚持这个,欢迎任何评论。

非常感谢!

1 个答案:

答案 0 :(得分:0)

通过表前缀所有列解决。查询现在看起来像这样

SELECT 
   a.value1,
   a.value2,
   a.value3,
   a.value4,
   a.value5, 
   hstore(
       ARRAY['field9', 'field10', 'field11', 'field12', 'field13', 'field14'],     
       ARRAY[a.field9, a.field10, a.field11, a.field12, a.field13, a.field14) as metadata, 
  a.value7, 
  (select array((select row(p.f1, p.f2) from table2 p where p.f3 = a.field7))) as values_array 
FROM table1 a

问题是table2.f3和table1.field7真的有相同的名字。有关this post of PostgreSQL general list

的更多信息