CREATE SCHEMA am_columnar_join; SET search_path TO am_columnar_join; CREATE TABLE users (id int, name text) USING columnar; INSERT INTO users SELECT a, 'name' || a FROM generate_series(0,30-1) AS a; CREATE TABLE things (id int, user_id int, name text) USING columnar; INSERT INTO things SELECT a, a % 30, 'thing' || a FROM generate_series(1,300) AS a; -- force the nested loop to rescan the table SET enable_material TO off; SET enable_hashjoin TO off; SET enable_mergejoin TO off; SELECT count(*) FROM users JOIN things ON (users.id = things.user_id) WHERE things.id > 290; count --------------------------------------------------------------------- 10 (1 row) -- verify the join uses a nested loop to trigger the rescan behaviour EXPLAIN (COSTS OFF) SELECT count(*) FROM users JOIN things ON (users.id = things.user_id) WHERE things.id > 299990; QUERY PLAN --------------------------------------------------------------------- Aggregate -> Nested Loop Join Filter: (users.id = things.user_id) -> Custom Scan (ColumnarScan) on things Filter: (id > 299990) Columnar Projected Columns: id, user_id Columnar Chunk Group Filters: (id > 299990) -> Custom Scan (ColumnarScan) on users Columnar Projected Columns: id (9 rows) EXPLAIN (COSTS OFF) SELECT u1.id, u2.id, COUNT(u2.*) FROM users u1 JOIN users u2 ON (u1.id::text = u2.name) WHERE u2.id > 299990 GROUP BY u1.id, u2.id; QUERY PLAN --------------------------------------------------------------------- HashAggregate Group Key: u1.id, u2.id -> Nested Loop Join Filter: ((u1.id)::text = u2.name) -> Custom Scan (ColumnarScan) on users u2 Filter: (id > 299990) Columnar Projected Columns: id, name Columnar Chunk Group Filters: (id > 299990) -> Custom Scan (ColumnarScan) on users u1 Columnar Projected Columns: id (10 rows) SET client_min_messages TO warning; DROP SCHEMA am_columnar_join CASCADE;