Re: Commit 86dc90056 - Rework planning and execution of UPDATE and DELETE - Mailing list pgsql-hackers

From Tom Lane
Subject Re: Commit 86dc90056 - Rework planning and execution of UPDATE and DELETE
Date
Msg-id 223770.1618844878@sss.pgh.pa.us
Whole thread Raw
In response to Re: Commit 86dc90056 - Rework planning and execution of UPDATE and DELETE  (Tom Lane <tgl@sss.pgh.pa.us>)
List pgsql-hackers
I wrote:
> Rushabh Lathia <rushabh.lathia@gmail.com> writes:
>> With the commit mentioned in the $subject, I am seeing the
>> change in behaviour with the varlena header size.

> Interesting.  AFAICS, the new behavior is correct and the old is wrong.
> SET STORAGE PLAIN is supposed to disable use of TOAST features, including
> short varlena headers.  So now that's being honored by the UPDATE, but
> before it was not.  I have no idea exactly why that changed though ---
> I'd expect that to be implemented in low-level tuple-construction logic
> that the planner rewrite wouldn't have changed.

Oh, after a bit of tracing I see it.  In v13, the new value gets
short-header-ified when a tuple is constructed here:

        /*
         * Ensure input tuple is the right format for the target relation.
         */
        if (node->mt_scans[node->mt_whichplan]->tts_ops != planSlot->tts_ops)
        {
            ExecCopySlot(node->mt_scans[node->mt_whichplan], planSlot);
            planSlot = node->mt_scans[node->mt_whichplan];
        }

where the target slot has been made like this:

        mtstate->mt_scans[i] =
            ExecInitExtraTupleSlot(mtstate->ps.state, ExecGetResultType(mtstate->mt_plans[i]),
                                   table_slot_callbacks(resultRelInfo->ri_RelationDesc));

So that's using a tupdesc that's been constructed according to the
default properties of the column datatypes, in particular attstorage
will be 'x' for the 'd' column.  Later we transpose the data into
a slot that actually has the target table's rowtype, but the damage
is already done; the value isn't un-short-headerized at that point.
(I wonder if that should be considered a bug?)

86dc90056 got rid of the intermediate mt_scans slots, so the 'ab'
value only gets put into a slot that has the table's real descriptor,
and it never loses its original 4-byte header.

I observe that the INSERT code path still does the wrong thing:

regression=# insert into test_storage_char values('foo');
INSERT 0 1
regression=# SELECT d, pg_column_size(d) FROM test_storage_char;
          d           | pg_column_size
----------------------+----------------
 ab                   |             24
 foo                  |             21
(2 rows)

Maybe we oughta try to fix that sometime.  It doesn't seem terribly
high-priority though.

            regards, tom lane



pgsql-hackers by date:

Previous
From: Fujii Masao
Date:
Subject: Re: track_planning causing performance regression
Next
From: Yulin PEI
Date:
Subject: 回覆: 回复: Core dump happens when execute sql CREATE VIEW v1(c1) AS (SELECT ('4' COLLATE "C")::INT FROM generate_series(1, 10));