Allow BitmapHeapScans on non-parameterized paths

Planner can decide to use BitmapHeapScans exclusively when
scanning compressed chunks. Since we filter out such scans
due to previously reported issues, this can lead to no
query plan devised when querying compressed chunks. This
change allows Bitmap scans on compressed chunks only when
it is not parameterized.

Fixes #5090
This commit is contained in:
Ante Kresic 2022-12-14 18:53:00 +01:00 committed by Ante Kresic
parent 3b3846b0ff
commit 3f9e3379a9
3 changed files with 70 additions and 3 deletions

View File

@ -426,14 +426,14 @@ ts_decompress_chunk_generate_paths(PlannerInfo *root, RelOptInfo *chunk_rel, Hyp
DecompressChunkPath *path; DecompressChunkPath *path;
/* /*
* We skip any BitmapScan paths here as supporting those * We skip any BitmapScan parameterized paths here as supporting
* would require fixing up the internal scan. Since we * those would require fixing up the internal scan. Since we
* currently do not do this BitmapScans would be generated * currently do not do this BitmapScans would be generated
* when we have a parameterized path on a compressed column * when we have a parameterized path on a compressed column
* that would have invalid references due to our * that would have invalid references due to our
* EquivalenceClasses. * EquivalenceClasses.
*/ */
if (IsA(child_path, BitmapHeapPath)) if (IsA(child_path, BitmapHeapPath) && child_path->param_info)
continue; continue;
/* /*
@ -568,6 +568,9 @@ ts_decompress_chunk_generate_paths(PlannerInfo *root, RelOptInfo *chunk_rel, Hyp
} }
/* set reloptkind to RELOPT_DEADREL to prevent postgresql from replanning this relation */ /* set reloptkind to RELOPT_DEADREL to prevent postgresql from replanning this relation */
compressed_rel->reloptkind = RELOPT_DEADREL; compressed_rel->reloptkind = RELOPT_DEADREL;
/* We should never get in the situation with no viable paths. */
Assert(chunk_rel->pathlist != NIL);
} }
/* /*
@ -1204,6 +1207,18 @@ create_compressed_scan_paths(PlannerInfo *root, RelOptInfo *compressed_rel, int
add_partial_path(compressed_rel, compressed_path); add_partial_path(compressed_rel, compressed_path);
} }
/*
* We set enable_bitmapscan to false here to ensure any pathes with bitmapscan do not
* displace other pathes. Note that setting the postgres GUC will not actually disable
* the bitmapscan path creation but will instead create them with very high cost.
* If bitmapscan were the dominant path after postgres planning we could end up
* in a situation where we have no valid plan for this relation because we remove
* bitmapscan pathes from the pathlist.
*/
bool old_bitmapscan = enable_bitmapscan;
enable_bitmapscan = false;
if (sort_info->can_pushdown_sort) if (sort_info->can_pushdown_sort)
{ {
/* /*
@ -1223,6 +1238,8 @@ create_compressed_scan_paths(PlannerInfo *root, RelOptInfo *compressed_rel, int
check_index_predicates(root, compressed_rel); check_index_predicates(root, compressed_rel);
create_index_paths(root, compressed_rel); create_index_paths(root, compressed_rel);
} }
enable_bitmapscan = old_bitmapscan;
} }
/* /*

View File

@ -590,3 +590,34 @@ SELECT 'test7' AS "HYPERTABLE_NAME" \gset
(1 row) (1 row)
DROP TABLE test7; DROP TABLE test7;
--#5090
CREATE TABLE test8(time TIMESTAMPTZ NOT NULL, value DOUBLE PRECISION NOT NULL, series_id BIGINT NOT NULL);
SELECT create_hypertable('test8', 'time', chunk_time_interval => INTERVAL '1 h');
create_hypertable
---------------------
(15,public,test8,t)
(1 row)
ALTER TABLE test8 set (timescaledb.compress,
timescaledb.compress_segmentby = 'series_id',
timescaledb.compress_orderby = 'time',
timescaledb.compress_chunk_time_interval = '1 day');
INSERT INTO test8 (time, series_id, value) SELECT t, s, 1 FROM generate_series(NOW(), NOW()+INTERVAL'4h', INTERVAL '30s') t CROSS JOIN generate_series(0, 100, 1) s;
SELECT compress_chunk(c, true) FROM show_chunks('test8') c LIMIT 4;
compress_chunk
-------------------------------------------
_timescaledb_internal._hyper_15_314_chunk
_timescaledb_internal._hyper_15_314_chunk
_timescaledb_internal._hyper_15_314_chunk
_timescaledb_internal._hyper_15_314_chunk
(4 rows)
SET enable_indexscan TO OFF;
SET enable_seqscan TO OFF;
SET enable_bitmapscan TO ON;
SELECT count(*) FROM test8 WHERE series_id = 1;
count
-------
481
(1 row)

View File

@ -205,3 +205,22 @@ SELECT 'test7' AS "HYPERTABLE_NAME" \gset
\ir include/compression_test_merge.sql \ir include/compression_test_merge.sql
DROP TABLE test7; DROP TABLE test7;
--#5090
CREATE TABLE test8(time TIMESTAMPTZ NOT NULL, value DOUBLE PRECISION NOT NULL, series_id BIGINT NOT NULL);
SELECT create_hypertable('test8', 'time', chunk_time_interval => INTERVAL '1 h');
ALTER TABLE test8 set (timescaledb.compress,
timescaledb.compress_segmentby = 'series_id',
timescaledb.compress_orderby = 'time',
timescaledb.compress_chunk_time_interval = '1 day');
INSERT INTO test8 (time, series_id, value) SELECT t, s, 1 FROM generate_series(NOW(), NOW()+INTERVAL'4h', INTERVAL '30s') t CROSS JOIN generate_series(0, 100, 1) s;
SELECT compress_chunk(c, true) FROM show_chunks('test8') c LIMIT 4;
SET enable_indexscan TO OFF;
SET enable_seqscan TO OFF;
SET enable_bitmapscan TO ON;
SELECT count(*) FROM test8 WHERE series_id = 1;