【问题标题】:PostgreSQL query terminating abruptly because statement timeout由于语句超时,PostgreSQL 查询突然终止
【发布时间】:2014-10-29 18:30:13
【问题描述】:

我正在尝试优化耗时过多的查询。这就是我所拥有的

  • 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 替换内部查询,并使用复合类型而不是数组。我正在努力,但我有点坚持,欢迎任何评论。

非常感谢!

【问题讨论】:

  • "在他们推荐的 postgresql 列表中......"
  • 是的,对不起。看我的回答。

标签: performance postgresql query-optimization


【解决方案1】:

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

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

【讨论】:

  • 我认为“前缀”是指使用别名?
  • 是的,为表使用别名并做 alias.column
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-04-02
  • 2013-01-13
  • 1970-01-01
  • 2018-10-22
  • 2018-11-24
  • 2022-01-15
相关资源
最近更新 更多