-- The test of a predicate on a dictionary leaf (text, or a numeric of any shape stored as images) is made once per segment and predicate: the -- units of a segment share its dictionary, so a LUT over all of it per unit costs the scan its units times the dictionary. CREATE EXTENSION pg_sift; CREATE EXTENSION pg_sift_test; SET client_min_messages = warning; SET max_parallel_maintenance_workers = 0; CREATE TABLE dt (id int, k text, n numeric); INSERT INTO dt SELECT i, 'key-' || lpad(i::text, 6, '0'), i::numeric / 7 FROM generate_series(1, 330000) i; CREATE INDEX dt_idx ON dt USING sift_col (k, n); SELECT segments, units > 9 AS several_units FROM sift._test_col_counters('dt_idx', '', 0); segments | several_units ----------+--------------- 1 | t (1 row) -- leaf 0 is k, leaf 1 the head of n (its second lane follows) SELECT rows, tests_made FROM sift._test_col_counters('dt_idx', '0:ge:key-165000', 0); rows | tests_made --------+------------ 165001 | 1 (1 row) SELECT rows, tests_made FROM sift._test_col_counters('dt_idx', '1:gt:4000;1:le:20000', 0); rows | tests_made --------+------------ 112000 | 2 (1 row) SELECT rows, tests_made FROM sift._test_col_counters('dt_idx', '0:in:key-000001|key-250000|key-329999;1:ne:1', 0); rows | tests_made ------+------------ 3 | 2 (1 row) SELECT count(*) FROM dt WHERE k >= 'key-165000'; count -------- 165001 (1 row) SELECT count(*) FROM dt WHERE n > 4000 AND n <= 20000; count -------- 112000 (1 row) SELECT count(*) FROM dt WHERE k IN ('key-000001', 'key-250000', 'key-329999') AND n <> 1; count ------- 3 (1 row) -- a second segment: its dictionary is its own, so it has its tests too INSERT INTO dt SELECT i, 'key-' || lpad(i::text, 6, '0'), i::numeric / 7 FROM generate_series(330001, 500000) i; SELECT sift.col_promote('dt_idx') > 0 AS promoted; promoted ---------- t (1 row) SELECT segments, units > 14 AS several_units FROM sift._test_col_counters('dt_idx', '', 0); segments | several_units ----------+--------------- 3 | t (1 row) SELECT rows, tests_made FROM sift._test_col_counters('dt_idx', '0:ge:key-165000;1:le:60000', 0); rows | tests_made --------+------------ 255001 | 6 (1 row) SELECT count(*) FROM dt WHERE k >= 'key-165000' AND n <= 60000; count -------- 255001 (1 row) -- more predicates than the source keeps tests for still gives the rows of the heap SELECT rows FROM sift._test_col_counters('dt_idx', (SELECT string_agg('0:ne:key-' || lpad((i * 1000)::text, 6, '0'), ';') FROM generate_series(1, 24) i), 0); rows -------- 499976 (1 row) SELECT count(*) FROM dt WHERE k NOT IN (SELECT 'key-' || lpad((i * 1000)::text, 6, '0') FROM generate_series(1, 24) i); count -------- 499976 (1 row) DROP TABLE dt; DROP EXTENSION pg_sift_test; DROP EXTENSION pg_sift;