mirror of
https://github.com/timescale/timescaledb.git
synced 2025-05-17 02:53:51 +08:00
Skip runtime exclusion when Param is not partitioning column
When the column a Param references is not a partitioning column the constraint is not useful for excluding chunks so we skip enabling runtime exclusion for those cases.
This commit is contained in:
parent
6f936ea2e3
commit
8c2acecbf4
@ -9,9 +9,11 @@
|
||||
#include <optimizer/pathnode.h>
|
||||
#include <optimizer/paths.h>
|
||||
#include <optimizer/tlist.h>
|
||||
#include <optimizer/var.h>
|
||||
#include <utils/builtins.h>
|
||||
#include <utils/typcache.h>
|
||||
|
||||
#include "hypertable.h"
|
||||
#include "chunk_append/chunk_append.h"
|
||||
#include "chunk_append/planner.h"
|
||||
#include "compat.h"
|
||||
@ -70,7 +72,30 @@ ts_chunk_append_path_create(PlannerInfo *root, RelOptInfo *rel, Hypertable *ht,
|
||||
path->startup_exclusion = true;
|
||||
|
||||
if (ts_guc_enable_runtime_exclusion && contain_param_exec((Node *) rinfo->clause))
|
||||
path->runtime_exclusion = true;
|
||||
{
|
||||
ListCell *lc_var;
|
||||
|
||||
/*
|
||||
* check the param references a partitioning column of the hypertable
|
||||
* otherwise we skip runtime exclusion
|
||||
*/
|
||||
foreach (lc_var, pull_var_clause((Node *) rinfo->clause, 0))
|
||||
{
|
||||
Var *var = lfirst(lc_var);
|
||||
/*
|
||||
* varattno 0 is whole row and varattno less than zero are
|
||||
* system columns so we skip those even though
|
||||
* ts_is_partitioning_column would return the correct
|
||||
* answer for those as well
|
||||
*/
|
||||
if (var->varno == rel->relid && var->varattno > 0 &&
|
||||
ts_is_partitioning_column(ht, var->varattno))
|
||||
{
|
||||
path->runtime_exclusion = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1872,3 +1872,16 @@ ts_hypertable_get_all_by_name(Name schema_name, Name table_name, MemoryContext m
|
||||
|
||||
return data.ht_oids;
|
||||
}
|
||||
|
||||
bool
|
||||
ts_is_partitioning_column(Hypertable *ht, Index column_attno)
|
||||
{
|
||||
uint16 i;
|
||||
|
||||
for (i = 0; i < ht->space->num_dimensions; i++)
|
||||
{
|
||||
if (column_attno == ht->space->dimensions[i].column_attno)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@ -106,6 +106,7 @@ extern Tablespace *ts_hypertable_get_tablespace_at_offset_from(int32 hypertable_
|
||||
extern bool ts_hypertable_has_tuples(Oid table_relid, LOCKMODE lockmode);
|
||||
extern void ts_hypertables_rename_schema_name(const char *old_name, const char *new_name);
|
||||
extern List *ts_hypertable_get_all_by_name(Name schema_name, Name table_name, MemoryContext mctx);
|
||||
extern bool ts_is_partitioning_column(Hypertable *ht, Index column_attno);
|
||||
|
||||
#define hypertable_scan(schema, table, tuple_found, data, lockmode, tuplock) \
|
||||
ts_hypertable_scan_with_memory_context(schema, \
|
||||
|
@ -1044,6 +1044,31 @@ ORDER BY time DESC;
|
||||
Heap Fetches: 129
|
||||
(31 rows)
|
||||
|
||||
-- test runtime exclusion does not activate for constraints on non-partitioning columns
|
||||
-- should not use runtime exclusion
|
||||
:PREFIX SELECT * FROM append_test a LEFT JOIN LATERAL(SELECT * FROM join_test j WHERE a.colorid = j.colorid ORDER BY time DESC LIMIT 1) j ON true ORDER BY a.time LIMIT 1;
|
||||
QUERY PLAN
|
||||
-----------------------------------------------------------------------------------------------------------------------------------
|
||||
Limit (actual rows=1 loops=1)
|
||||
-> Nested Loop Left Join (actual rows=1 loops=1)
|
||||
-> Custom Scan (ChunkAppend) on append_test a (actual rows=1 loops=1)
|
||||
Order: a."time"
|
||||
-> Index Scan Backward using _hyper_1_1_chunk_append_test_time_idx on _hyper_1_1_chunk a_1 (actual rows=1 loops=1)
|
||||
-> Index Scan Backward using _hyper_1_2_chunk_append_test_time_idx on _hyper_1_2_chunk a_2 (never executed)
|
||||
-> Index Scan Backward using _hyper_1_3_chunk_append_test_time_idx on _hyper_1_3_chunk a_3 (never executed)
|
||||
-> Limit (actual rows=1 loops=1)
|
||||
-> Custom Scan (ChunkAppend) on join_test j (actual rows=1 loops=1)
|
||||
Order: j."time" DESC
|
||||
-> Index Scan using _hyper_2_6_chunk_join_test_time_idx on _hyper_2_6_chunk j_1 (actual rows=0 loops=1)
|
||||
Filter: (a.colorid = colorid)
|
||||
Rows Removed by Filter: 1
|
||||
-> Index Scan using _hyper_2_5_chunk_join_test_time_idx on _hyper_2_5_chunk j_2 (actual rows=0 loops=1)
|
||||
Filter: (a.colorid = colorid)
|
||||
Rows Removed by Filter: 1
|
||||
-> Index Scan using _hyper_2_4_chunk_join_test_time_idx on _hyper_2_4_chunk j_3 (actual rows=1 loops=1)
|
||||
Filter: (a.colorid = colorid)
|
||||
(18 rows)
|
||||
|
||||
-- test runtime exclusion with LATERAL and generate_series
|
||||
:PREFIX SELECT g.time FROM generate_series('2000-01-01'::timestamptz, '2000-02-01'::timestamptz, '1d'::interval) g(time) LEFT JOIN LATERAL(SELECT time FROM metrics_timestamptz m WHERE m.time=g.time LIMIT 1) m ON true;
|
||||
QUERY PLAN
|
||||
@ -1117,6 +1142,33 @@ ORDER BY time DESC;
|
||||
Heap Fetches: 6
|
||||
(19 rows)
|
||||
|
||||
:PREFIX SELECT * FROM generate_series('2000-01-01'::timestamptz,'2000-02-01'::timestamptz,'1d'::interval) AS g(time) INNER JOIN LATERAL (SELECT time FROM metrics_timestamptz m WHERE time>g.time + '1 day' ORDER BY time LIMIT 1) m ON true;
|
||||
QUERY PLAN
|
||||
--------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
Nested Loop (actual rows=30 loops=1)
|
||||
-> Function Scan on generate_series g (actual rows=32 loops=1)
|
||||
-> Limit (actual rows=1 loops=32)
|
||||
-> Custom Scan (ChunkAppend) on metrics_timestamptz m (actual rows=1 loops=32)
|
||||
Order: m."time"
|
||||
Chunks excluded during startup: 0
|
||||
Chunks excluded during runtime: 2
|
||||
-> Index Only Scan Backward using _hyper_5_17_chunk_metrics_timestamptz_time_idx on _hyper_5_17_chunk m_1 (actual rows=1 loops=4)
|
||||
Index Cond: ("time" > (g."time" + '@ 1 day'::interval))
|
||||
Heap Fetches: 4
|
||||
-> Index Only Scan Backward using _hyper_5_18_chunk_metrics_timestamptz_time_idx on _hyper_5_18_chunk m_2 (actual rows=1 loops=7)
|
||||
Index Cond: ("time" > (g."time" + '@ 1 day'::interval))
|
||||
Heap Fetches: 7
|
||||
-> Index Only Scan Backward using _hyper_5_19_chunk_metrics_timestamptz_time_idx on _hyper_5_19_chunk m_3 (actual rows=1 loops=7)
|
||||
Index Cond: ("time" > (g."time" + '@ 1 day'::interval))
|
||||
Heap Fetches: 7
|
||||
-> Index Only Scan Backward using _hyper_5_20_chunk_metrics_timestamptz_time_idx on _hyper_5_20_chunk m_4 (actual rows=1 loops=7)
|
||||
Index Cond: ("time" > (g."time" + '@ 1 day'::interval))
|
||||
Heap Fetches: 7
|
||||
-> Index Only Scan Backward using _hyper_5_21_chunk_metrics_timestamptz_time_idx on _hyper_5_21_chunk m_5 (actual rows=1 loops=7)
|
||||
Index Cond: ("time" > (g."time" + '@ 1 day'::interval))
|
||||
Heap Fetches: 5
|
||||
(22 rows)
|
||||
|
||||
-- test runtime exclusion with subquery
|
||||
:PREFIX SELECT m1.time FROM metrics_timestamptz m1 WHERE m1.time=(SELECT max(time) FROM metrics_timestamptz);
|
||||
QUERY PLAN
|
||||
|
@ -1044,6 +1044,31 @@ ORDER BY time DESC;
|
||||
Heap Fetches: 129
|
||||
(31 rows)
|
||||
|
||||
-- test runtime exclusion does not activate for constraints on non-partitioning columns
|
||||
-- should not use runtime exclusion
|
||||
:PREFIX SELECT * FROM append_test a LEFT JOIN LATERAL(SELECT * FROM join_test j WHERE a.colorid = j.colorid ORDER BY time DESC LIMIT 1) j ON true ORDER BY a.time LIMIT 1;
|
||||
QUERY PLAN
|
||||
-----------------------------------------------------------------------------------------------------------------------------------
|
||||
Limit (actual rows=1 loops=1)
|
||||
-> Nested Loop Left Join (actual rows=1 loops=1)
|
||||
-> Custom Scan (ChunkAppend) on append_test a (actual rows=1 loops=1)
|
||||
Order: a."time"
|
||||
-> Index Scan Backward using _hyper_1_1_chunk_append_test_time_idx on _hyper_1_1_chunk a_1 (actual rows=1 loops=1)
|
||||
-> Index Scan Backward using _hyper_1_2_chunk_append_test_time_idx on _hyper_1_2_chunk a_2 (never executed)
|
||||
-> Index Scan Backward using _hyper_1_3_chunk_append_test_time_idx on _hyper_1_3_chunk a_3 (never executed)
|
||||
-> Limit (actual rows=1 loops=1)
|
||||
-> Custom Scan (ChunkAppend) on join_test j (actual rows=1 loops=1)
|
||||
Order: j."time" DESC
|
||||
-> Index Scan using _hyper_2_6_chunk_join_test_time_idx on _hyper_2_6_chunk j_1 (actual rows=0 loops=1)
|
||||
Filter: (a.colorid = colorid)
|
||||
Rows Removed by Filter: 1
|
||||
-> Index Scan using _hyper_2_5_chunk_join_test_time_idx on _hyper_2_5_chunk j_2 (actual rows=0 loops=1)
|
||||
Filter: (a.colorid = colorid)
|
||||
Rows Removed by Filter: 1
|
||||
-> Index Scan using _hyper_2_4_chunk_join_test_time_idx on _hyper_2_4_chunk j_3 (actual rows=1 loops=1)
|
||||
Filter: (a.colorid = colorid)
|
||||
(18 rows)
|
||||
|
||||
-- test runtime exclusion with LATERAL and generate_series
|
||||
:PREFIX SELECT g.time FROM generate_series('2000-01-01'::timestamptz, '2000-02-01'::timestamptz, '1d'::interval) g(time) LEFT JOIN LATERAL(SELECT time FROM metrics_timestamptz m WHERE m.time=g.time LIMIT 1) m ON true;
|
||||
QUERY PLAN
|
||||
@ -1117,6 +1142,33 @@ ORDER BY time DESC;
|
||||
Heap Fetches: 6
|
||||
(19 rows)
|
||||
|
||||
:PREFIX SELECT * FROM generate_series('2000-01-01'::timestamptz,'2000-02-01'::timestamptz,'1d'::interval) AS g(time) INNER JOIN LATERAL (SELECT time FROM metrics_timestamptz m WHERE time>g.time + '1 day' ORDER BY time LIMIT 1) m ON true;
|
||||
QUERY PLAN
|
||||
--------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
Nested Loop (actual rows=30 loops=1)
|
||||
-> Function Scan on generate_series g (actual rows=32 loops=1)
|
||||
-> Limit (actual rows=1 loops=32)
|
||||
-> Custom Scan (ChunkAppend) on metrics_timestamptz m (actual rows=1 loops=32)
|
||||
Order: m."time"
|
||||
Chunks excluded during startup: 0
|
||||
Chunks excluded during runtime: 2
|
||||
-> Index Only Scan Backward using _hyper_5_17_chunk_metrics_timestamptz_time_idx on _hyper_5_17_chunk m_1 (actual rows=1 loops=4)
|
||||
Index Cond: ("time" > (g."time" + '@ 1 day'::interval))
|
||||
Heap Fetches: 4
|
||||
-> Index Only Scan Backward using _hyper_5_18_chunk_metrics_timestamptz_time_idx on _hyper_5_18_chunk m_2 (actual rows=1 loops=7)
|
||||
Index Cond: ("time" > (g."time" + '@ 1 day'::interval))
|
||||
Heap Fetches: 7
|
||||
-> Index Only Scan Backward using _hyper_5_19_chunk_metrics_timestamptz_time_idx on _hyper_5_19_chunk m_3 (actual rows=1 loops=7)
|
||||
Index Cond: ("time" > (g."time" + '@ 1 day'::interval))
|
||||
Heap Fetches: 7
|
||||
-> Index Only Scan Backward using _hyper_5_20_chunk_metrics_timestamptz_time_idx on _hyper_5_20_chunk m_4 (actual rows=1 loops=7)
|
||||
Index Cond: ("time" > (g."time" + '@ 1 day'::interval))
|
||||
Heap Fetches: 7
|
||||
-> Index Only Scan Backward using _hyper_5_21_chunk_metrics_timestamptz_time_idx on _hyper_5_21_chunk m_5 (actual rows=1 loops=7)
|
||||
Index Cond: ("time" > (g."time" + '@ 1 day'::interval))
|
||||
Heap Fetches: 5
|
||||
(22 rows)
|
||||
|
||||
-- test runtime exclusion with subquery
|
||||
:PREFIX SELECT m1.time FROM metrics_timestamptz m1 WHERE m1.time=(SELECT max(time) FROM metrics_timestamptz);
|
||||
QUERY PLAN
|
||||
|
@ -936,6 +936,29 @@ ORDER BY time DESC;
|
||||
Index Cond: ("time" = m1."time")
|
||||
(20 rows)
|
||||
|
||||
-- test runtime exclusion does not activate for constraints on non-partitioning columns
|
||||
-- should not use runtime exclusion
|
||||
:PREFIX SELECT * FROM append_test a LEFT JOIN LATERAL(SELECT * FROM join_test j WHERE a.colorid = j.colorid ORDER BY time DESC LIMIT 1) j ON true ORDER BY a.time LIMIT 1;
|
||||
QUERY PLAN
|
||||
-----------------------------------------------------------------------------------------------------------
|
||||
Limit
|
||||
-> Nested Loop Left Join
|
||||
-> Custom Scan (ChunkAppend) on append_test a
|
||||
Order: a."time"
|
||||
-> Index Scan Backward using _hyper_1_1_chunk_append_test_time_idx on _hyper_1_1_chunk a_1
|
||||
-> Index Scan Backward using _hyper_1_2_chunk_append_test_time_idx on _hyper_1_2_chunk a_2
|
||||
-> Index Scan Backward using _hyper_1_3_chunk_append_test_time_idx on _hyper_1_3_chunk a_3
|
||||
-> Limit
|
||||
-> Custom Scan (ChunkAppend) on join_test j
|
||||
Order: j."time" DESC
|
||||
-> Index Scan using _hyper_2_6_chunk_join_test_time_idx on _hyper_2_6_chunk j_1
|
||||
Filter: (a.colorid = colorid)
|
||||
-> Index Scan using _hyper_2_5_chunk_join_test_time_idx on _hyper_2_5_chunk j_2
|
||||
Filter: (a.colorid = colorid)
|
||||
-> Index Scan using _hyper_2_4_chunk_join_test_time_idx on _hyper_2_4_chunk j_3
|
||||
Filter: (a.colorid = colorid)
|
||||
(16 rows)
|
||||
|
||||
-- test runtime exclusion with LATERAL and generate_series
|
||||
:PREFIX SELECT g.time FROM generate_series('2000-01-01'::timestamptz, '2000-02-01'::timestamptz, '1d'::interval) g(time) LEFT JOIN LATERAL(SELECT time FROM metrics_timestamptz m WHERE m.time=g.time LIMIT 1) m ON true;
|
||||
QUERY PLAN
|
||||
@ -991,6 +1014,27 @@ ORDER BY time DESC;
|
||||
Index Cond: ("time" = g."time")
|
||||
(13 rows)
|
||||
|
||||
:PREFIX SELECT * FROM generate_series('2000-01-01'::timestamptz,'2000-02-01'::timestamptz,'1d'::interval) AS g(time) INNER JOIN LATERAL (SELECT time FROM metrics_timestamptz m WHERE time>g.time + '1 day' ORDER BY time LIMIT 1) m ON true;
|
||||
QUERY PLAN
|
||||
--------------------------------------------------------------------------------------------------------------------------
|
||||
Nested Loop
|
||||
-> Function Scan on generate_series g
|
||||
-> Limit
|
||||
-> Custom Scan (ChunkAppend) on metrics_timestamptz m
|
||||
Order: m."time"
|
||||
Chunks excluded during startup: 0
|
||||
-> Index Only Scan Backward using _hyper_5_17_chunk_metrics_timestamptz_time_idx on _hyper_5_17_chunk m_1
|
||||
Index Cond: ("time" > (g."time" + '@ 1 day'::interval))
|
||||
-> Index Only Scan Backward using _hyper_5_18_chunk_metrics_timestamptz_time_idx on _hyper_5_18_chunk m_2
|
||||
Index Cond: ("time" > (g."time" + '@ 1 day'::interval))
|
||||
-> Index Only Scan Backward using _hyper_5_19_chunk_metrics_timestamptz_time_idx on _hyper_5_19_chunk m_3
|
||||
Index Cond: ("time" > (g."time" + '@ 1 day'::interval))
|
||||
-> Index Only Scan Backward using _hyper_5_20_chunk_metrics_timestamptz_time_idx on _hyper_5_20_chunk m_4
|
||||
Index Cond: ("time" > (g."time" + '@ 1 day'::interval))
|
||||
-> Index Only Scan Backward using _hyper_5_21_chunk_metrics_timestamptz_time_idx on _hyper_5_21_chunk m_5
|
||||
Index Cond: ("time" > (g."time" + '@ 1 day'::interval))
|
||||
(16 rows)
|
||||
|
||||
-- test runtime exclusion with subquery
|
||||
:PREFIX SELECT m1.time FROM metrics_timestamptz m1 WHERE m1.time=(SELECT max(time) FROM metrics_timestamptz);
|
||||
QUERY PLAN
|
||||
|
@ -218,10 +218,15 @@ ORDER BY time DESC;
|
||||
-- test runtime exclusion with LATERAL and 2 hypertables
|
||||
:PREFIX SELECT m1.time, m2.time FROM metrics_timestamptz m1 LEFT JOIN LATERAL(SELECT time FROM metrics_timestamptz m2 WHERE m1.time = m2.time LIMIT 1) m2 ON true ORDER BY m1.time;
|
||||
|
||||
-- test runtime exclusion does not activate for constraints on non-partitioning columns
|
||||
-- should not use runtime exclusion
|
||||
:PREFIX SELECT * FROM append_test a LEFT JOIN LATERAL(SELECT * FROM join_test j WHERE a.colorid = j.colorid ORDER BY time DESC LIMIT 1) j ON true ORDER BY a.time LIMIT 1;
|
||||
|
||||
-- test runtime exclusion with LATERAL and generate_series
|
||||
:PREFIX SELECT g.time FROM generate_series('2000-01-01'::timestamptz, '2000-02-01'::timestamptz, '1d'::interval) g(time) LEFT JOIN LATERAL(SELECT time FROM metrics_timestamptz m WHERE m.time=g.time LIMIT 1) m ON true;
|
||||
:PREFIX SELECT * FROM generate_series('2000-01-01'::timestamptz,'2000-02-01'::timestamptz,'1d'::interval) AS g(time) INNER JOIN LATERAL (SELECT time FROM metrics_timestamptz m WHERE time=g.time) m ON true;
|
||||
:PREFIX SELECT * FROM generate_series('2000-01-01'::timestamptz,'2000-02-01'::timestamptz,'1d'::interval) AS g(time) INNER JOIN LATERAL (SELECT time FROM metrics_timestamptz m WHERE time=g.time ORDER BY time) m ON true;
|
||||
:PREFIX SELECT * FROM generate_series('2000-01-01'::timestamptz,'2000-02-01'::timestamptz,'1d'::interval) AS g(time) INNER JOIN LATERAL (SELECT time FROM metrics_timestamptz m WHERE time>g.time + '1 day' ORDER BY time LIMIT 1) m ON true;
|
||||
|
||||
-- test runtime exclusion with subquery
|
||||
:PREFIX SELECT m1.time FROM metrics_timestamptz m1 WHERE m1.time=(SELECT max(time) FROM metrics_timestamptz);
|
||||
|
Loading…
x
Reference in New Issue
Block a user