【发布时间】: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