通过ctid的JOIN UPDATE FROM导致Seq扫描

时间:2019-06-27 06:20:41

标签: sql postgresql sql-execution-plan postgresql-11

为澄清我的问题,我创建了具有以下结构的测试表。

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条件下使用主键,但是随后将需要其他索引访问。

0 个答案:

没有答案