mirror of
https://github.com/timescale/timescaledb.git
synced 2025-05-17 02:53:51 +08:00
Vectorize filters with external parameters
For example, comparison to a query parameter in a parameterized prepared query.
This commit is contained in:
parent
662fcc1b1b
commit
1cd77b3a24
@ -373,15 +373,24 @@ is_not_runtime_constant_walker(Node *node, void *context)
|
||||
{
|
||||
case T_Var:
|
||||
case T_PlaceHolderVar:
|
||||
case T_Param:
|
||||
/*
|
||||
* We might want to support these nodes to have vectorizable
|
||||
* join clauses (T_Var), join clauses referencing a variable that is
|
||||
* above outer join (T_PlaceHolderVar) or initplan parameters and
|
||||
* prepared statement parameters (T_Param). We don't support them at
|
||||
* the moment.
|
||||
* We might want to support these nodes to have vectorizable join
|
||||
* clauses (T_Var) or join clauses referencing a variable that is
|
||||
* above outer join (T_PlaceHolderVar). We don't suppor them at the
|
||||
* moment.
|
||||
*/
|
||||
return true;
|
||||
case T_Param:
|
||||
/*
|
||||
* We support external query parameters (e.g. from parameterized
|
||||
* prepared statements), because they are constant for the duration
|
||||
* of the query.
|
||||
*
|
||||
* Join and initplan parameters are passed as PARAM_EXEC and require
|
||||
* support in the Rescan functions of the custom scan node. We don't
|
||||
* support them at the moment.
|
||||
*/
|
||||
return castNode(Param, node)->paramkind != PARAM_EXTERN;
|
||||
default:
|
||||
if (check_functions_in_node(node,
|
||||
contains_volatile_functions_checker,
|
||||
|
@ -132,7 +132,55 @@ select tag from vectorqual where metric2 > 0;
|
||||
tag5
|
||||
(5 rows)
|
||||
|
||||
-- Can't vectorize parameterized join clauses for now.
|
||||
set timescaledb.debug_require_vector_qual to 'forbid';
|
||||
set enable_hashjoin to off;
|
||||
set enable_mergejoin to off;
|
||||
with values(x) as materialized(select distinct metric2 from vectorqual)
|
||||
select x, (select metric2 from vectorqual where metric2 = x) from values order by 1;
|
||||
x | metric2
|
||||
----+---------
|
||||
12 | 12
|
||||
22 | 22
|
||||
32 | 32
|
||||
42 | 42
|
||||
52 | 52
|
||||
(5 rows)
|
||||
|
||||
reset enable_hashjoin;
|
||||
reset enable_mergejoin;
|
||||
-- Can't vectorize initplan parameters either.
|
||||
select count(*) from vectorqual where metric2
|
||||
= (select metric2 from vectorqual order by 1 limit 1);
|
||||
count
|
||||
-------
|
||||
1
|
||||
(1 row)
|
||||
|
||||
-- Can vectorize clauses with query parameters.
|
||||
set timescaledb.debug_require_vector_qual to 'only';
|
||||
set plan_cache_mode to 'force_generic_plan';
|
||||
prepare p as select count(*) from vectorqual where metric3 = $1;
|
||||
execute p(33);
|
||||
count
|
||||
-------
|
||||
1
|
||||
(1 row)
|
||||
|
||||
deallocate p;
|
||||
-- Also try query parameter in combination with a stable function.
|
||||
create function stable_identity(x anyelement) returns anyelement as $$ select x $$ language sql stable;
|
||||
prepare p(int4) as select count(*) from vectorqual where metric3 = stable_identity($1);
|
||||
execute p(33);
|
||||
count
|
||||
-------
|
||||
1
|
||||
(1 row)
|
||||
|
||||
deallocate p;
|
||||
reset plan_cache_mode;
|
||||
-- Queries without aggregation.
|
||||
set timescaledb.debug_require_vector_qual to 'only';
|
||||
select * from vectorqual where ts > '2021-01-01 00:00:00' order by vectorqual;
|
||||
ts | metric2 | device | metric3 | metric4 | tag
|
||||
--------------------------+---------+--------+---------+---------+------
|
||||
|
@ -2124,17 +2124,17 @@ QUERY PLAN
|
||||
Custom Scan (ChunkAppend) on metrics_compressed (actual rows=5 loops=1)
|
||||
Chunks excluded during runtime: 2
|
||||
-> Custom Scan (DecompressChunk) on _hyper_X_X_chunk (actual rows=5 loops=1)
|
||||
Filter: ("time" = $1)
|
||||
Vectorized Filter: ("time" = $1)
|
||||
Rows Removed by Filter: 4995
|
||||
-> Seq Scan on compress_hyper_X_X_chunk (actual rows=5 loops=1)
|
||||
Filter: ((_ts_meta_min_1 <= $1) AND (_ts_meta_max_1 >= $1))
|
||||
Rows Removed by Filter: 15
|
||||
-> Custom Scan (DecompressChunk) on _hyper_X_X_chunk (never executed)
|
||||
Filter: ("time" = $1)
|
||||
Vectorized Filter: ("time" = $1)
|
||||
-> Seq Scan on compress_hyper_X_X_chunk (never executed)
|
||||
Filter: ((_ts_meta_min_1 <= $1) AND (_ts_meta_max_1 >= $1))
|
||||
-> Custom Scan (DecompressChunk) on _hyper_X_X_chunk (never executed)
|
||||
Filter: ("time" = $1)
|
||||
Vectorized Filter: ("time" = $1)
|
||||
-> Seq Scan on compress_hyper_X_X_chunk (never executed)
|
||||
Filter: ((_ts_meta_min_1 <= $1) AND (_ts_meta_max_1 >= $1))
|
||||
(16 rows)
|
||||
@ -2144,17 +2144,17 @@ QUERY PLAN
|
||||
Custom Scan (ChunkAppend) on metrics_compressed (actual rows=5 loops=1)
|
||||
Chunks excluded during runtime: 2
|
||||
-> Custom Scan (DecompressChunk) on _hyper_X_X_chunk (never executed)
|
||||
Filter: ("time" = $1)
|
||||
Vectorized Filter: ("time" = $1)
|
||||
-> Seq Scan on compress_hyper_X_X_chunk (never executed)
|
||||
Filter: ((_ts_meta_min_1 <= $1) AND (_ts_meta_max_1 >= $1))
|
||||
-> Custom Scan (DecompressChunk) on _hyper_X_X_chunk (actual rows=5 loops=1)
|
||||
Filter: ("time" = $1)
|
||||
Vectorized Filter: ("time" = $1)
|
||||
Rows Removed by Filter: 4995
|
||||
-> Seq Scan on compress_hyper_X_X_chunk (actual rows=5 loops=1)
|
||||
Filter: ((_ts_meta_min_1 <= $1) AND (_ts_meta_max_1 >= $1))
|
||||
Rows Removed by Filter: 25
|
||||
-> Custom Scan (DecompressChunk) on _hyper_X_X_chunk (never executed)
|
||||
Filter: ("time" = $1)
|
||||
Vectorized Filter: ("time" = $1)
|
||||
-> Seq Scan on compress_hyper_X_X_chunk (never executed)
|
||||
Filter: ((_ts_meta_min_1 <= $1) AND (_ts_meta_max_1 >= $1))
|
||||
(16 rows)
|
||||
@ -2164,15 +2164,15 @@ QUERY PLAN
|
||||
Custom Scan (ChunkAppend) on metrics_compressed (actual rows=0 loops=1)
|
||||
Chunks excluded during runtime: 3
|
||||
-> Custom Scan (DecompressChunk) on _hyper_X_X_chunk (never executed)
|
||||
Filter: ("time" = $1)
|
||||
Vectorized Filter: ("time" = $1)
|
||||
-> Seq Scan on compress_hyper_X_X_chunk (never executed)
|
||||
Filter: ((_ts_meta_min_1 <= $1) AND (_ts_meta_max_1 >= $1))
|
||||
-> Custom Scan (DecompressChunk) on _hyper_X_X_chunk (never executed)
|
||||
Filter: ("time" = $1)
|
||||
Vectorized Filter: ("time" = $1)
|
||||
-> Seq Scan on compress_hyper_X_X_chunk (never executed)
|
||||
Filter: ((_ts_meta_min_1 <= $1) AND (_ts_meta_max_1 >= $1))
|
||||
-> Custom Scan (DecompressChunk) on _hyper_X_X_chunk (never executed)
|
||||
Filter: ("time" = $1)
|
||||
Vectorized Filter: ("time" = $1)
|
||||
-> Seq Scan on compress_hyper_X_X_chunk (never executed)
|
||||
Filter: ((_ts_meta_min_1 <= $1) AND (_ts_meta_max_1 >= $1))
|
||||
(14 rows)
|
||||
@ -3407,45 +3407,45 @@ QUERY PLAN
|
||||
Custom Scan (ChunkAppend) on metrics_space_compressed (actual rows=5 loops=1)
|
||||
Chunks excluded during runtime: 6
|
||||
-> Custom Scan (DecompressChunk) on _hyper_X_X_chunk (actual rows=1 loops=1)
|
||||
Filter: ("time" = $1)
|
||||
Vectorized Filter: ("time" = $1)
|
||||
Rows Removed by Filter: 999
|
||||
-> Seq Scan on compress_hyper_X_X_chunk (actual rows=1 loops=1)
|
||||
Filter: ((_ts_meta_min_1 <= $1) AND (_ts_meta_max_1 >= $1))
|
||||
Rows Removed by Filter: 3
|
||||
-> Custom Scan (DecompressChunk) on _hyper_X_X_chunk (actual rows=3 loops=1)
|
||||
Filter: ("time" = $1)
|
||||
Vectorized Filter: ("time" = $1)
|
||||
Rows Removed by Filter: 2997
|
||||
-> Seq Scan on compress_hyper_X_X_chunk (actual rows=3 loops=1)
|
||||
Filter: ((_ts_meta_min_1 <= $1) AND (_ts_meta_max_1 >= $1))
|
||||
Rows Removed by Filter: 9
|
||||
-> Custom Scan (DecompressChunk) on _hyper_X_X_chunk (actual rows=1 loops=1)
|
||||
Filter: ("time" = $1)
|
||||
Vectorized Filter: ("time" = $1)
|
||||
Rows Removed by Filter: 999
|
||||
-> Seq Scan on compress_hyper_X_X_chunk (actual rows=1 loops=1)
|
||||
Filter: ((_ts_meta_min_1 <= $1) AND (_ts_meta_max_1 >= $1))
|
||||
Rows Removed by Filter: 3
|
||||
-> Custom Scan (DecompressChunk) on _hyper_X_X_chunk (never executed)
|
||||
Filter: ("time" = $1)
|
||||
Vectorized Filter: ("time" = $1)
|
||||
-> Seq Scan on compress_hyper_X_X_chunk (never executed)
|
||||
Filter: ((_ts_meta_min_1 <= $1) AND (_ts_meta_max_1 >= $1))
|
||||
-> Custom Scan (DecompressChunk) on _hyper_X_X_chunk (never executed)
|
||||
Filter: ("time" = $1)
|
||||
Vectorized Filter: ("time" = $1)
|
||||
-> Seq Scan on compress_hyper_X_X_chunk (never executed)
|
||||
Filter: ((_ts_meta_min_1 <= $1) AND (_ts_meta_max_1 >= $1))
|
||||
-> Custom Scan (DecompressChunk) on _hyper_X_X_chunk (never executed)
|
||||
Filter: ("time" = $1)
|
||||
Vectorized Filter: ("time" = $1)
|
||||
-> Seq Scan on compress_hyper_X_X_chunk (never executed)
|
||||
Filter: ((_ts_meta_min_1 <= $1) AND (_ts_meta_max_1 >= $1))
|
||||
-> Custom Scan (DecompressChunk) on _hyper_X_X_chunk (never executed)
|
||||
Filter: ("time" = $1)
|
||||
Vectorized Filter: ("time" = $1)
|
||||
-> Seq Scan on compress_hyper_X_X_chunk (never executed)
|
||||
Filter: ((_ts_meta_min_1 <= $1) AND (_ts_meta_max_1 >= $1))
|
||||
-> Custom Scan (DecompressChunk) on _hyper_X_X_chunk (never executed)
|
||||
Filter: ("time" = $1)
|
||||
Vectorized Filter: ("time" = $1)
|
||||
-> Seq Scan on compress_hyper_X_X_chunk (never executed)
|
||||
Filter: ((_ts_meta_min_1 <= $1) AND (_ts_meta_max_1 >= $1))
|
||||
-> Custom Scan (DecompressChunk) on _hyper_X_X_chunk (never executed)
|
||||
Filter: ("time" = $1)
|
||||
Vectorized Filter: ("time" = $1)
|
||||
-> Seq Scan on compress_hyper_X_X_chunk (never executed)
|
||||
Filter: ((_ts_meta_min_1 <= $1) AND (_ts_meta_max_1 >= $1))
|
||||
(44 rows)
|
||||
@ -3455,45 +3455,45 @@ QUERY PLAN
|
||||
Custom Scan (ChunkAppend) on metrics_space_compressed (actual rows=5 loops=1)
|
||||
Chunks excluded during runtime: 6
|
||||
-> Custom Scan (DecompressChunk) on _hyper_X_X_chunk (never executed)
|
||||
Filter: ("time" = $1)
|
||||
Vectorized Filter: ("time" = $1)
|
||||
-> Seq Scan on compress_hyper_X_X_chunk (never executed)
|
||||
Filter: ((_ts_meta_min_1 <= $1) AND (_ts_meta_max_1 >= $1))
|
||||
-> Custom Scan (DecompressChunk) on _hyper_X_X_chunk (never executed)
|
||||
Filter: ("time" = $1)
|
||||
Vectorized Filter: ("time" = $1)
|
||||
-> Seq Scan on compress_hyper_X_X_chunk (never executed)
|
||||
Filter: ((_ts_meta_min_1 <= $1) AND (_ts_meta_max_1 >= $1))
|
||||
-> Custom Scan (DecompressChunk) on _hyper_X_X_chunk (never executed)
|
||||
Filter: ("time" = $1)
|
||||
Vectorized Filter: ("time" = $1)
|
||||
-> Seq Scan on compress_hyper_X_X_chunk (never executed)
|
||||
Filter: ((_ts_meta_min_1 <= $1) AND (_ts_meta_max_1 >= $1))
|
||||
-> Custom Scan (DecompressChunk) on _hyper_X_X_chunk (actual rows=1 loops=1)
|
||||
Filter: ("time" = $1)
|
||||
Vectorized Filter: ("time" = $1)
|
||||
Rows Removed by Filter: 999
|
||||
-> Seq Scan on compress_hyper_X_X_chunk (actual rows=1 loops=1)
|
||||
Filter: ((_ts_meta_min_1 <= $1) AND (_ts_meta_max_1 >= $1))
|
||||
Rows Removed by Filter: 5
|
||||
-> Custom Scan (DecompressChunk) on _hyper_X_X_chunk (actual rows=3 loops=1)
|
||||
Filter: ("time" = $1)
|
||||
Vectorized Filter: ("time" = $1)
|
||||
Rows Removed by Filter: 2997
|
||||
-> Seq Scan on compress_hyper_X_X_chunk (actual rows=3 loops=1)
|
||||
Filter: ((_ts_meta_min_1 <= $1) AND (_ts_meta_max_1 >= $1))
|
||||
Rows Removed by Filter: 15
|
||||
-> Custom Scan (DecompressChunk) on _hyper_X_X_chunk (actual rows=1 loops=1)
|
||||
Filter: ("time" = $1)
|
||||
Vectorized Filter: ("time" = $1)
|
||||
Rows Removed by Filter: 999
|
||||
-> Seq Scan on compress_hyper_X_X_chunk (actual rows=1 loops=1)
|
||||
Filter: ((_ts_meta_min_1 <= $1) AND (_ts_meta_max_1 >= $1))
|
||||
Rows Removed by Filter: 5
|
||||
-> Custom Scan (DecompressChunk) on _hyper_X_X_chunk (never executed)
|
||||
Filter: ("time" = $1)
|
||||
Vectorized Filter: ("time" = $1)
|
||||
-> Seq Scan on compress_hyper_X_X_chunk (never executed)
|
||||
Filter: ((_ts_meta_min_1 <= $1) AND (_ts_meta_max_1 >= $1))
|
||||
-> Custom Scan (DecompressChunk) on _hyper_X_X_chunk (never executed)
|
||||
Filter: ("time" = $1)
|
||||
Vectorized Filter: ("time" = $1)
|
||||
-> Seq Scan on compress_hyper_X_X_chunk (never executed)
|
||||
Filter: ((_ts_meta_min_1 <= $1) AND (_ts_meta_max_1 >= $1))
|
||||
-> Custom Scan (DecompressChunk) on _hyper_X_X_chunk (never executed)
|
||||
Filter: ("time" = $1)
|
||||
Vectorized Filter: ("time" = $1)
|
||||
-> Seq Scan on compress_hyper_X_X_chunk (never executed)
|
||||
Filter: ((_ts_meta_min_1 <= $1) AND (_ts_meta_max_1 >= $1))
|
||||
(44 rows)
|
||||
@ -3503,39 +3503,39 @@ QUERY PLAN
|
||||
Custom Scan (ChunkAppend) on metrics_space_compressed (actual rows=0 loops=1)
|
||||
Chunks excluded during runtime: 9
|
||||
-> Custom Scan (DecompressChunk) on _hyper_X_X_chunk (never executed)
|
||||
Filter: ("time" = $1)
|
||||
Vectorized Filter: ("time" = $1)
|
||||
-> Seq Scan on compress_hyper_X_X_chunk (never executed)
|
||||
Filter: ((_ts_meta_min_1 <= $1) AND (_ts_meta_max_1 >= $1))
|
||||
-> Custom Scan (DecompressChunk) on _hyper_X_X_chunk (never executed)
|
||||
Filter: ("time" = $1)
|
||||
Vectorized Filter: ("time" = $1)
|
||||
-> Seq Scan on compress_hyper_X_X_chunk (never executed)
|
||||
Filter: ((_ts_meta_min_1 <= $1) AND (_ts_meta_max_1 >= $1))
|
||||
-> Custom Scan (DecompressChunk) on _hyper_X_X_chunk (never executed)
|
||||
Filter: ("time" = $1)
|
||||
Vectorized Filter: ("time" = $1)
|
||||
-> Seq Scan on compress_hyper_X_X_chunk (never executed)
|
||||
Filter: ((_ts_meta_min_1 <= $1) AND (_ts_meta_max_1 >= $1))
|
||||
-> Custom Scan (DecompressChunk) on _hyper_X_X_chunk (never executed)
|
||||
Filter: ("time" = $1)
|
||||
Vectorized Filter: ("time" = $1)
|
||||
-> Seq Scan on compress_hyper_X_X_chunk (never executed)
|
||||
Filter: ((_ts_meta_min_1 <= $1) AND (_ts_meta_max_1 >= $1))
|
||||
-> Custom Scan (DecompressChunk) on _hyper_X_X_chunk (never executed)
|
||||
Filter: ("time" = $1)
|
||||
Vectorized Filter: ("time" = $1)
|
||||
-> Seq Scan on compress_hyper_X_X_chunk (never executed)
|
||||
Filter: ((_ts_meta_min_1 <= $1) AND (_ts_meta_max_1 >= $1))
|
||||
-> Custom Scan (DecompressChunk) on _hyper_X_X_chunk (never executed)
|
||||
Filter: ("time" = $1)
|
||||
Vectorized Filter: ("time" = $1)
|
||||
-> Seq Scan on compress_hyper_X_X_chunk (never executed)
|
||||
Filter: ((_ts_meta_min_1 <= $1) AND (_ts_meta_max_1 >= $1))
|
||||
-> Custom Scan (DecompressChunk) on _hyper_X_X_chunk (never executed)
|
||||
Filter: ("time" = $1)
|
||||
Vectorized Filter: ("time" = $1)
|
||||
-> Seq Scan on compress_hyper_X_X_chunk (never executed)
|
||||
Filter: ((_ts_meta_min_1 <= $1) AND (_ts_meta_max_1 >= $1))
|
||||
-> Custom Scan (DecompressChunk) on _hyper_X_X_chunk (never executed)
|
||||
Filter: ("time" = $1)
|
||||
Vectorized Filter: ("time" = $1)
|
||||
-> Seq Scan on compress_hyper_X_X_chunk (never executed)
|
||||
Filter: ((_ts_meta_min_1 <= $1) AND (_ts_meta_max_1 >= $1))
|
||||
-> Custom Scan (DecompressChunk) on _hyper_X_X_chunk (never executed)
|
||||
Filter: ("time" = $1)
|
||||
Vectorized Filter: ("time" = $1)
|
||||
-> Seq Scan on compress_hyper_X_X_chunk (never executed)
|
||||
Filter: ((_ts_meta_min_1 <= $1) AND (_ts_meta_max_1 >= $1))
|
||||
(38 rows)
|
||||
|
@ -47,7 +47,38 @@ set timescaledb.debug_require_vector_qual to 'only';
|
||||
select tag from vectorqual where metric2 > 0;
|
||||
|
||||
|
||||
-- Can't vectorize parameterized join clauses for now.
|
||||
set timescaledb.debug_require_vector_qual to 'forbid';
|
||||
set enable_hashjoin to off;
|
||||
set enable_mergejoin to off;
|
||||
with values(x) as materialized(select distinct metric2 from vectorqual)
|
||||
select x, (select metric2 from vectorqual where metric2 = x) from values order by 1;
|
||||
reset enable_hashjoin;
|
||||
reset enable_mergejoin;
|
||||
|
||||
-- Can't vectorize initplan parameters either.
|
||||
select count(*) from vectorqual where metric2
|
||||
= (select metric2 from vectorqual order by 1 limit 1);
|
||||
|
||||
-- Can vectorize clauses with query parameters.
|
||||
set timescaledb.debug_require_vector_qual to 'only';
|
||||
set plan_cache_mode to 'force_generic_plan';
|
||||
|
||||
prepare p as select count(*) from vectorqual where metric3 = $1;
|
||||
execute p(33);
|
||||
deallocate p;
|
||||
|
||||
-- Also try query parameter in combination with a stable function.
|
||||
create function stable_identity(x anyelement) returns anyelement as $$ select x $$ language sql stable;
|
||||
prepare p(int4) as select count(*) from vectorqual where metric3 = stable_identity($1);
|
||||
execute p(33);
|
||||
deallocate p;
|
||||
|
||||
reset plan_cache_mode;
|
||||
|
||||
|
||||
-- Queries without aggregation.
|
||||
set timescaledb.debug_require_vector_qual to 'only';
|
||||
select * from vectorqual where ts > '2021-01-01 00:00:00' order by vectorqual;
|
||||
select * from vectorqual where metric4 >= 0 order by vectorqual;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user