从优化更新... Postgres 9.1

时间:2014-02-18 14:05:49

标签: sql postgresql sql-update temp-tables

我有两张大桌子:

tbl_a
id(int), cnt(int default:0)

tbl_b
id(int), a_id(int)

我需要在tbl_b中计算所有具有相同a_id的行,并将该值放入tbl_a。

我找到了方法:

update tbl_a
set cnt = tb.c
from (select count(*) c,a_id from tbl_b group by a_id) tb
where tb.a_id = tbl_a.id

但该查询适用于每1000行约 8s 。这是不可接受的,因为我有大约6M的。

试图创建临时表

... AS (select count(*),a_id from tbl_b group by a_id)

甚至添加了b-tree索引,但没有任何变化。

可以在同一硬件上执行得更快吗?

UPD1:

"Update on tbl_a  (cost=0.00..343357.80 rows=40000 width=459)"
"  ->  Nested Loop  (cost=0.00..343357.80 rows=40000 width=459)"
"        ->  Seq Scan on tbl_b_temp  (cost=0.00..617.00 rows=40000 width=18)"
"        ->  Index Scan using tbl_a_pkey on tbl_a  (cost=0.00..8.55 rows=1 width=445)"
"              Index Cond: (id = tbl_b_temp.a_id)"

rows = 40000因为我创建了较小的临时表。

查询:

create temporary table tbl_b_temp as 
select count(*) as c, a_id from tbl_b group by a_id order by a_id limit 40000;

CREATE INDEX a_id_ind on tbl_b using btree (a_id);

1 个答案:

答案 0 :(得分:2)

使用(大)临时表时,请确保在创建或更改后运行ANALYZE,因为autovacuum不包括临时表。这可能会改进Postgres提出的查询计划。

Quoting the manual:

  

autovacuum无法访问临时表。因此,   适当的真空和分析操作应通过   session SQL命令。