我有两张大桌子:
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);
答案 0 :(得分:2)
使用(大)临时表时,请确保在创建或更改后运行ANALYZE
,因为autovacuum不包括临时表。这可能会改进Postgres提出的查询计划。
autovacuum无法访问临时表。因此, 适当的真空和分析操作应通过 session SQL命令。