为澄清我的问题,我创建了具有以下结构的测试表。
CREATE TABLE public.test_large (
id int4 NOT NULL, -- Primary Key
grp int4 NULL, -- Group ID
descr text NULL,
CONSTRAINT pk_test_large PRIMARY KEY (id)
);
CREATE INDEX ix_tl_grp ON public.test_large USING btree (grp);
分配了grp列中的值,以便最多有1000条记录,每条记录具有相同的值。 总共有1.000.000条记录。
以下更新语句是真实语句的简化版本:
update
test_large d
set
descr = s.descr
from
(
select
ctid,
*
from
test_large
where
grp = 1) s
where
s.ctid = d.ctid;
执行计划是:
Update on test_large d (cost=139792.82..144832.96 rows=1000 width=53)
-> Merge Join (cost=139792.82..144832.96 rows=1000 width=53)
Merge Cond: (d.ctid = test_large.ctid)
-> Sort (cost=136816.68..139329.25 rows=1005029 width=14)
Sort Key: d.ctid
-> Seq Scan on test_large d (cost=0.00..19443.29 rows=1005029 width=14)
-> Sort (cost=2976.14..2978.64 rows=1000 width=39)
Sort Key: test_large.ctid
-> Bitmap Heap Scan on test_large (cost=20.18..2926.31 rows=1000 width=39)
Recheck Cond: (grp = 1)
-> Bitmap Index Scan on ix_tl_grp (cost=0.00..19.93 rows=1000 width=0)
Index Cond: (grp = 1)
如您所见,将对所有1,000,000行进行Seq扫描以进行更新,以便随后执行合并联接,而不是直接通过CTID访问该行。
有什么办法可以影响这一点?我当然可以在WHERE条件下使用主键,但是随后将需要其他索引访问。