| From: | Greg Burd <greg(at)burd(dot)me> |
|---|---|
| To: | Greg Burd <greg(at)burd(dot)me> |
| Cc: | Matthias van de Meent <boekewurm+postgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>, Heikki Linnakangas <hlinnaka(at)iki(dot)fi>, Tom Lane <tgl(at)sss(dot)pgh(dot)pa(dot)us>, Chris Cleveland <ccleveland(at)dieselpoint(dot)com> |
| Subject: | Re: Let an ordering index scan hand its ORDER BY value to the target list |
| Date: | 2026-10-06 16:29:12 |
| Message-ID: | C1aJFkKX_SZd8wPwbcNDkqio1c1akB89mIQi46GJvkjsOnMSL0V0HWZu6rodRRtzhnPIslgDCJNppQ8cVFOkHErbYopEg2pOA5N66bnYPNo=@burd.me |
| Views: | Whole Thread | Raw Message | Download mbox | Resend email |
| Thread: | |
| Lists: | pgsql-hackers |
On Monday, October 5th, 2026 at 2:14 PM, Greg Burd <greg(at)burd(dot)me> wrote:
>
> I've not yet measured performance or memory difference due to this change,
> net should be better but I should quantify that at some point.
I've run a test in EC2 to answer this question, details at the end but this
change is significant for some important shapes. For a cheap operator
(point <-> point, 100k rows) the patch is 3-6% faster. The slot fetch is
cheaper than re-evaluating hypot(). For an expensive one it removes the
re-evaluation entirely: a 128-dim float8[] distance over 10k rows goes from
197 ms to 4 ms, a plpgsql expression index from 139 ms to 8 ms. box_ops is a
wash (+0.1%). The circle_ops control, which doesn't qualify and gets no
rewrite, is unchanged (-0.9%, within the 1% stdev), so an opclass that
answers no pays nothing.
What this means is a) this is a good performance win, and b) I now need to see
if it makes sense to adjust the costing of this pattern given that some shapes
are ~97% faster now. For instances, a vec_10k the plan costs ~50× what it
actually does with this fix in place. I'll poke around and see if I come up
with something that avoids tipping the decision in the wrong direction (away
from an index scan) and add a patch in if I do.
best.
-greg
Results
=======
c7i.4xlarge (Xeon 8488C, 1 NUMA node), AL2023, gcc 11.5, -O2, no cassert.
master e8f4f9e3ce2 vs v3. 1M-row tables, fully prewarmed, shared_buffers=4GB,
JIT off, parallelism off, server+client pinned to one core, A/B alternated
per-run, 11 runs each, median. Plans verified: every patched query shows
Order By Values Used: 1 except the circle control as expected.
query ORDER BY key master patched delta
(ms) (ms)
----------------- ----------------------------- ------- -------- -------
gist_point_1k p <-> pt 2.08 2.01 -3.2%
gist_point_100k p <-> pt 70.58 66.18 -6.2%
spg_point_100k p <-> pt (SP-GiST) 75.07 70.64 -5.9%
gist_box_100k b <-> pt 68.49 68.58 +0.1%
gist_circle_100k c <-> pt (lossy, no rewrite) 117.93 116.88 -0.9%
slow_1k plpgsql expr index (~13us) 15.64 2.26 -85.6%
slow_10k plpgsql expr index (~13us) 139.17 8.14 -94.2%
vec_1k 128-dim float8[] L2 distance 20.12 0.59 -97.1%
vec_10k 128-dim float8[] L2 distance 197.38 4.16 -97.9%
Stdev <= 3.3% for all rows.
| From | Date | Subject | |
|---|---|---|---|
| Next Message | Alvaro Herrera | 2026-10-06 16:39:25 | Re: REPACK (CONCURRENTLY) can't complete after ~105M concurrent updates/deletes |
| Previous Message | David Geier | 2026-10-06 16:27:58 | Re: Improving scalability of Parallel Bitmap Heap/Index Scan |