1
0
mirror of https://github.com/postgres/postgres.git synced 2025-11-03 09:13:20 +03:00

Improve nbtree unsatisfiable RowCompare detection.

Move nbtree's detection of RowCompare quals that are unsatisfiable due
to having a NULL in their first row element: rather than detecting these
cases at the point where _bt_first builds its insertion scan key, do so
earlier, during preprocessing proper.  This brings the RowCompare case
in line every other case involving an unsatisfiable-due-to-NULL qual.

nbtree now consistently detects such unsatisfiable quals -- even when
they happen to involve a key that isn't examined by _bt_first at all.
Affected cases thereby avoid useless full index scans that cannot
possibly return any matching rows.

Author: Peter Geoghegan <pg@bowt.ie>
Reviewed-By: Matthias van de Meent <boekewurm+postgres@gmail.com>
Discussion: https://postgr.es/m/CAH2-WzmySVXst2hFrOATC-zw1Byg1XC-jYUS314=mzuqsNwk+Q@mail.gmail.com
This commit is contained in:
Peter Geoghegan
2025-01-07 10:38:30 -05:00
parent 428a99b589
commit ec986020de
6 changed files with 248 additions and 16 deletions

View File

@@ -110,6 +110,85 @@ SELECT b.*
FROM bt_f8_heap b
WHERE b.seqno = '4500'::float8;
--
-- Add coverage of RowCompare quals whose row omits a column ("proargtypes")
-- that's after the first column, but before the final column. The scan's
-- initial positioning strategy must become >= here (it's not the > strategy,
-- since the absence of "proargtypes" makes that tighter constraint unsafe).
--
explain (costs off)
SELECT proname, proargtypes, pronamespace
FROM pg_proc
WHERE (proname, pronamespace) > ('abs', 0)
ORDER BY proname, proargtypes, pronamespace LIMIT 1;
SELECT proname, proargtypes, pronamespace
FROM pg_proc
WHERE (proname, pronamespace) > ('abs', 0)
ORDER BY proname, proargtypes, pronamespace LIMIT 1;
--
-- Similar to the previous test case, but this time it's a backwards scan
-- using a < RowCompare. Must use the <= strategy (and not the < strategy).
--
explain (costs off)
SELECT proname, proargtypes, pronamespace
FROM pg_proc
WHERE (proname, pronamespace) < ('abs', 1_000_000)
ORDER BY proname DESC, proargtypes DESC, pronamespace DESC LIMIT 1;
SELECT proname, proargtypes, pronamespace
FROM pg_proc
WHERE (proname, pronamespace) < ('abs', 1_000_000)
ORDER BY proname DESC, proargtypes DESC, pronamespace DESC LIMIT 1;
--
-- Add coverage for RowCompare quals whose rhs row has a NULL that ends scan
--
explain (costs off)
SELECT proname, proargtypes, pronamespace
FROM pg_proc
WHERE proname = 'abs' AND (proname, proargtypes) < ('abs', NULL)
ORDER BY proname, proargtypes, pronamespace;
SELECT proname, proargtypes, pronamespace
FROM pg_proc
WHERE proname = 'abs' AND (proname, proargtypes) < ('abs', NULL)
ORDER BY proname, proargtypes, pronamespace;
--
-- Add coverage for backwards scan RowCompare quals whose rhs row has a NULL
-- that ends scan
--
explain (costs off)
SELECT proname, proargtypes, pronamespace
FROM pg_proc
WHERE proname = 'abs' AND (proname, proargtypes) > ('abs', NULL)
ORDER BY proname DESC, proargtypes DESC, pronamespace DESC;
SELECT proname, proargtypes, pronamespace
FROM pg_proc
WHERE proname = 'abs' AND (proname, proargtypes) > ('abs', NULL)
ORDER BY proname DESC, proargtypes DESC, pronamespace DESC;
--
-- Add coverage for recheck of > key following array advancement on previous
-- (left sibling) page that used a high key whose attribute value corresponding
-- to the > key was -inf (due to being truncated when the high key was created).
--
-- XXX This relies on the assumption that tenk1_thous_tenthous has a truncated
-- high key "(183, -inf)" on the first page that we'll scan. The test will only
-- provide useful coverage when the default 8K BLCKSZ is in use.
--
explain (costs off)
SELECT thousand, tenthous
FROM tenk1
WHERE thousand IN (182, 183) AND tenthous > 7550;
SELECT thousand, tenthous
FROM tenk1
WHERE thousand IN (182, 183) AND tenthous > 7550;
--
-- Add coverage for optimization of backwards scan index descents
--

View File

@@ -931,6 +931,11 @@ SELECT unique1 FROM tenk1 WHERE unique1 IN (1, 42, 7) and unique1 < (-1)::bigint
SELECT unique1 FROM tenk1 WHERE unique1 IN (1, 42, 7) and unique1 < (-1)::bigint;
explain (costs off)
SELECT unique1 FROM tenk1 WHERE (thousand, tenthous) > (NULL, 5);
SELECT unique1 FROM tenk1 WHERE (thousand, tenthous) > (NULL, 5);
--
-- Check elimination of constant-NULL subexpressions
--