Re: Avoid detoast overhead when possible

From: zhihuifan1213(at)163(dot)com
To: Matthias van de Meent <boekewurm+postgres(at)gmail(dot)com>
Cc: pgsql-hackers(at)lists(dot)postgresql(dot)org
Subject: Re: Avoid detoast overhead when possible
Date: 2023-12-05 00:28:21
Message-ID: 87fs0hh2jc.fsf@163.com
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-hackers


Hi,

Matthias van de Meent <boekewurm+postgres(at)gmail(dot)com> writes:

> SELECT toastable_col FROM t1
> WHERE f(t1.toastable_col)
> ORDER BY nonindexed;

Thanks for this example! it's true that the current design requires more
memory to sort since toastable_col is detoasted at the scan stage and it
is output to the sort node. It should be avoided.

> SELECT ev_class
> FROM pg_rewrite
> WHERE octet_length(ev_action) > 1
> ORDER BY ev_class;

This one is different I think, since the ev_action (the toastable_col) is
*NOT* output to sort node, so no extra memory is required IIUC.

* CP_SMALL_TLIST specifies that a narrower tlist is preferred. This is
* passed down by parent nodes such as Sort and Hash, which will have to
* store the returned tuples.

We can also verify this by

explain (costs off, verbose) SELECT ev_class
FROM pg_rewrite
WHERE octet_length(ev_action) > 1
ORDER BY ev_class;
QUERY PLAN
------------------------------------------------------------------
Sort
Output: ev_class
Sort Key: pg_rewrite.ev_class
-> Seq Scan on pg_catalog.pg_rewrite
Output: ev_class
Filter: (octet_length((pg_rewrite.ev_action)::text) > 1)
(6 rows)

Only ev_class is output to Sort node.

So if we want to make sure there is performance regression for all the
existing queries in any case, we can add 1 more restriction into the
saved-detoast-value logic. It must be (NOT under CP_SMALL_TLIST) OR (the
toastable_col is not in the output list). It can be a planner decision.

If we code like this, the result will be we need to dotoast N times
for toastable_col in qual for the below query.

SELECT toastable_col FROM t
WHERE f1(toastable_col)
AND f2(toastable_col)
..
AND fn(toastable_col)
ORDER BY any-target-entry;

However

SELECT
f1(toastable_col),
f2(toastable_col),
..
fn(toastable_col)
FROM t
ORDER BY any-target-entry;

the current path still works for it.

This one is my favorite one so far. Another option is saving the
detoast-value in some other memory or existing-slot-in-place for
different sistuation, that would requires more expr expression changes
and planner changes. I just checked all the queries in my hand, the
current design can cover all of them.

--
Best Regards
Andy Fan

In response to

Responses

Browse pgsql-hackers by date

  From Date Subject
Next Message Jeff Davis 2023-12-05 00:55:40 Re: CREATE FUNCTION ... SEARCH { DEFAULT | SYSTEM | SESSION }
Previous Message Michael Paquier 2023-12-04 23:45:03 Re: PATCH: Add REINDEX tag to event triggers