Add time_bucket support to chunk exclusion

This patch adds support for chunk exclusion for time_bucket
expressions in the WHERE clause. The following transformation
is done when building RestrictInfo:

Transform time_bucket calls of the following form in WHERE clause:

time_bucket(width, column) OP value

Since time_bucket always returns the lower bound of the bucket
for lower bound comparisons the width is not relevant and the
following transformation can be applied:

time_bucket(width, column) > value
column > value

Example with values:

time_bucket(10, column) > 109
column > 109

For upper bound comparisons width needs to be taken into account
and we need to extend the upper bound by width to capture all
possible values.

time_bucket(width, column) < value
column < value + width

Example with values:

time_bucket(10, column) < 100
column < 100 + 10

This allows chunk exclusions to work for views with aggregations.
This commit is contained in:
Sven Klemm 2019-04-09 10:50:21 +02:00 committed by Sven Klemm
parent 0c346f17ab
commit 1813848cb7
9 changed files with 1069 additions and 47 deletions

View File

@ -96,53 +96,6 @@ can_exclude_chunk(PlannerInfo *root, Scan *scan, EState *estate, Index rt_index,
excluded_by_constraint(root, rte, rt_index, restrictinfos);
}
/*
* get_operator
*
* finds an operator given an exact specification (name, namespace,
* left and right type IDs).
*/
static Oid
get_operator(const char *name, Oid namespace, Oid left, Oid right)
{
HeapTuple tup;
Oid opoid = InvalidOid;
tup = SearchSysCache4(OPERNAMENSP,
PointerGetDatum(name),
ObjectIdGetDatum(left),
ObjectIdGetDatum(right),
ObjectIdGetDatum(namespace));
if (HeapTupleIsValid(tup))
{
opoid = HeapTupleGetOid(tup);
ReleaseSysCache(tup);
}
return opoid;
}
/*
* lookup cast func oid in pg_cast
*/
static Oid
get_cast_func(Oid source, Oid target)
{
Oid result = InvalidOid;
HeapTuple casttup;
casttup = SearchSysCache2(CASTSOURCETARGET, ObjectIdGetDatum(source), ObjectIdGetDatum(target));
if (HeapTupleIsValid(casttup))
{
Form_pg_cast castform = (Form_pg_cast) GETSTRUCT(casttup);
result = castform->castfunc;
ReleaseSysCache(casttup);
}
return result;
}
#define DATATYPE_PAIR(left, right, type1, type2) \
((left == type1 && right == type2) || (left == type2 && right == type1))

View File

@ -6,6 +6,7 @@
#include <postgres.h>
#include <nodes/relation.h>
#include <parser/parsetree.h>
#include <optimizer/clauses.h>
#include <optimizer/var.h>
#include <optimizer/restrictinfo.h>
#include <nodes/plannodes.h>
@ -15,6 +16,7 @@
#include <catalog/pg_constraint.h>
#include <catalog/pg_inherits.h>
#include <catalog/pg_namespace.h>
#include "compat.h"
#if PG96 || PG10 /* PG11 consolidates pg_foo_fn.h -> pg_foo.h */
#include <catalog/pg_constraint_fn.h>
@ -70,6 +72,188 @@ is_chunk_exclusion_func(Expr *node)
return false;
}
static bool
is_time_bucket_function(Expr *node)
{
if (IsA(node, FuncExpr) &&
strncmp(get_func_name(castNode(FuncExpr, node)->funcid), "time_bucket", NAMEDATALEN) == 0)
return true;
return false;
}
/*
* Transform time_bucket calls of the following form in WHERE clause:
*
* time_bucket(width, column) OP value
*
* Since time_bucket always returns the lower bound of the bucket
* for lower bound comparisons the width is not relevant and the
* following transformation can be applied:
*
* time_bucket(width, column) > value
* column > value
*
* Example with values:
*
* time_bucket(10, column) > 109
* column > 109
*
* For upper bound comparisons width needs to be taken into account
* and we need to extend the upper bound by width to capture all
* possible values.
*
* time_bucket(width, column) < value
* column < value + width
*
* Example with values:
*
* time_bucket(10, column) < 100
* column < 100 + 10
*
* Expressions with value on the left side will be switched around
* when building the expression for RestrictInfo.
*
* Caller must ensure that only 2 argument time_bucket versions
* are used.
*/
static OpExpr *
transform_time_bucket_comparison(PlannerInfo *root, OpExpr *op)
{
Expr *left = linitial(op->args);
Expr *right = lsecond(op->args);
FuncExpr *time_bucket = castNode(FuncExpr, (IsA(left, FuncExpr) ? left : right));
Expr *value = IsA(right, Const) ? right : left;
Const *width = linitial(time_bucket->args);
Oid opno = op->opno;
TypeCacheEntry *tce;
int strategy;
/* caller must ensure time_bucket only has 2 arguments */
Assert(list_length(time_bucket->args) == 2);
/*
* if time_bucket call is on wrong side we switch operator
*/
if (IsA(right, FuncExpr))
{
opno = get_commutator(op->opno);
if (!OidIsValid(opno))
return op;
}
tce = lookup_type_cache(exprType((Node *) time_bucket), TYPECACHE_BTREE_OPFAMILY);
strategy = get_op_opfamily_strategy(opno, tce->btree_opf);
if (strategy == BTGreaterStrategyNumber || strategy == BTGreaterEqualStrategyNumber)
{
/* column > value */
op = copyObject(op);
op->args = list_make2(lsecond(time_bucket->args), value);
/*
* if we switched operator we need to adjust OpExpr as well
*/
if (IsA(right, FuncExpr))
{
op->opno = opno;
op->opfuncid = InvalidOid;
}
return op;
}
else if (strategy == BTLessStrategyNumber || strategy == BTLessEqualStrategyNumber)
{
/* column < value + width */
Expr *subst;
Oid resulttype;
Oid subst_opno = get_operator("+",
PG_CATALOG_NAMESPACE,
exprType((Node *) value),
exprType((Node *) width));
if (!OidIsValid(subst_opno))
return op;
if (tce->type_id == TIMESTAMPTZOID && width->consttype == INTERVALOID &&
DatumGetIntervalP(width)->month == 0 && DatumGetIntervalP(width)->day != 0)
{
/*
* If width interval has day component we merge it with
* time component because estimating the day component
* depends on the session timezone and that would be
* unsafe during planning time.
* But since time_bucket calculation always is relative
* to UTC it is safe to do this transformation and assume
* day to always be 24 hours.
*/
Interval *interval;
width = copyObject(width);
interval = DatumGetIntervalP(width->constvalue);
interval->time += interval->day * USECS_PER_DAY;
interval->day = 0;
}
resulttype = get_op_rettype(subst_opno);
subst = make_opclause(subst_opno,
tce->type_id,
false,
value,
(Expr *) width,
InvalidOid,
InvalidOid);
/*
* check if resulttype of operation returns correct datatype
*
* date OP interval returns timestamp so we need to insert
* a cast to keep toplevel expr intact when datatypes don't match
*/
if (tce->type_id != resulttype)
{
Oid cast_func = get_cast_func(resulttype, tce->type_id);
if (!OidIsValid(cast_func))
return op;
subst = (Expr *)
makeFuncExpr(cast_func, tce->type_id, list_make1(subst), InvalidOid, InvalidOid, 0);
}
if (tce->type_id == TIMESTAMPTZOID && width->consttype == INTERVALOID)
{
/*
* TIMESTAMPTZ OP INTERVAL is marked stable and unsafe
* to evaluate at plan time unless it only has a time
* component
*/
Interval *interval = DatumGetIntervalP(width->constvalue);
if (interval->day == 0 && interval->month == 0)
subst = (Expr *) estimate_expression_value(root, (Node *) subst);
}
op = copyObject(op);
/*
* if we switched operator we need to adjust OpExpr as well
*/
if (IsA(right, FuncExpr))
{
op->opno = opno;
op->opfuncid = InvalidOid;
}
op->args = list_make2(lsecond(time_bucket->args), subst);
}
return op;
}
/* Since baserestrictinfo is not yet set by the planner, we have to derive
* it ourselves. It's safe for us to miss some restrict info clauses (this
* will just result in more chunks being included) so this does not need
@ -118,6 +302,23 @@ process_quals(Node *quals, CollectQualCtx *ctx)
return quals;
}
if (IsA(qual, OpExpr) && list_length(castNode(OpExpr, qual)->args) == 2)
{
OpExpr *op = castNode(OpExpr, qual);
Expr *left = linitial(op->args);
Expr *right = lsecond(op->args);
if ((IsA(left, FuncExpr) && IsA(right, Const) &&
list_length(castNode(FuncExpr, left)->args) == 2 &&
is_time_bucket_function(left)) ||
(IsA(left, Const) && IsA(right, FuncExpr) &&
list_length(castNode(FuncExpr, right)->args) == 2 &&
is_time_bucket_function(right)))
{
qual = (Expr *) transform_time_bucket_comparison(ctx->root, op);
}
}
#if PG96
restrictinfo = make_restrictinfo(qual, true, false, false, relids, NULL, NULL);
#else

View File

@ -469,3 +469,52 @@ get_function_oid(char *name, char *schema_name, int nargs, Oid arg_types[])
}
elog(ERROR, "failed to find function %s in schema %s with %d args", name, schema_name, nargs);
}
/*
* get_operator
*
* finds an operator given an exact specification (name, namespace,
* left and right type IDs).
*/
Oid
get_operator(const char *name, Oid namespace, Oid left, Oid right)
{
HeapTuple tup;
Oid opoid = InvalidOid;
tup = SearchSysCache4(OPERNAMENSP,
PointerGetDatum(name),
ObjectIdGetDatum(left),
ObjectIdGetDatum(right),
ObjectIdGetDatum(namespace));
if (HeapTupleIsValid(tup))
{
opoid = HeapTupleGetOid(tup);
ReleaseSysCache(tup);
}
return opoid;
}
/*
* get_cast_func
*
* returns Oid of functions that implements cast from source to target
*/
Oid
get_cast_func(Oid source, Oid target)
{
Oid result = InvalidOid;
HeapTuple casttup;
casttup = SearchSysCache2(CASTSOURCETARGET, ObjectIdGetDatum(source), ObjectIdGetDatum(target));
if (HeapTupleIsValid(casttup))
{
Form_pg_cast castform = (Form_pg_cast) GETSTRUCT(casttup);
result = castform->castfunc;
ReleaseSysCache(casttup);
}
return result;
}

View File

@ -61,6 +61,10 @@ extern bool ts_function_types_equal(Oid left[], Oid right[], int nargs);
extern Oid get_function_oid(char *name, char *schema_name, int nargs, Oid arg_types[]);
extern Oid get_operator(const char *name, Oid namespace, Oid left, Oid right);
extern Oid get_cast_func(Oid source, Oid target);
extern void *ts_create_struct_from_tuple(HeapTuple tuple, MemoryContext mctx, size_t alloc_size,
size_t copy_size);

View File

@ -68,6 +68,33 @@ psql:include/plan_expand_hypertable_load.sql:57: WARNING: unexpected interval:
(1 row)
INSERT INTO hyper_timefunc (time, device_id, value) SELECT g, 'dev' || g, g FROM generate_series(0,30) g;
CREATE TABLE metrics_timestamp(time timestamp);
SELECT create_hypertable('metrics_timestamp','time');
psql:include/plan_expand_hypertable_load.sql:62: NOTICE: adding not-null constraint to column "time"
create_hypertable
--------------------------------
(5,public,metrics_timestamp,t)
(1 row)
INSERT INTO metrics_timestamp SELECT generate_series('2000-01-01'::timestamp,'2000-02-01'::timestamp,'1d'::interval);
CREATE TABLE metrics_timestamptz(time timestamptz);
SELECT create_hypertable('metrics_timestamptz','time');
psql:include/plan_expand_hypertable_load.sql:66: NOTICE: adding not-null constraint to column "time"
create_hypertable
----------------------------------
(6,public,metrics_timestamptz,t)
(1 row)
INSERT INTO metrics_timestamptz SELECT generate_series('2000-01-01'::timestamptz,'2000-02-01'::timestamptz,'1d'::interval);
CREATE TABLE metrics_date(time date);
SELECT create_hypertable('metrics_date','time');
psql:include/plan_expand_hypertable_load.sql:70: NOTICE: adding not-null constraint to column "time"
create_hypertable
---------------------------
(7,public,metrics_date,t)
(1 row)
INSERT INTO metrics_date SELECT generate_series('2000-01-01'::date,'2000-02-01'::date,'1d'::interval);
ANALYZE hyper;
ANALYZE hyper_w_space;
ANALYZE tag;
@ -883,6 +910,237 @@ SELECT * FROM cte ORDER BY value;
Filter: (name = 'tag1'::text)
(9 rows)
-- time_bucket exclusion
:PREFIX SELECT * FROM hyper WHERE time_bucket(10, time) < 10::bigint ORDER BY time;
QUERY PLAN
--------------------------------------------------------------------------
Sort
Sort Key: _hyper_1_1_chunk."time"
-> Append
-> Seq Scan on _hyper_1_1_chunk
Filter: (time_bucket('10'::bigint, "time") < '10'::bigint)
-> Seq Scan on _hyper_1_2_chunk
Filter: (time_bucket('10'::bigint, "time") < '10'::bigint)
(7 rows)
:PREFIX SELECT * FROM hyper WHERE time_bucket(10, time) < 11::bigint ORDER BY time;
QUERY PLAN
--------------------------------------------------------------------------
Sort
Sort Key: _hyper_1_1_chunk."time"
-> Append
-> Seq Scan on _hyper_1_1_chunk
Filter: (time_bucket('10'::bigint, "time") < '11'::bigint)
-> Seq Scan on _hyper_1_2_chunk
Filter: (time_bucket('10'::bigint, "time") < '11'::bigint)
-> Seq Scan on _hyper_1_3_chunk
Filter: (time_bucket('10'::bigint, "time") < '11'::bigint)
(9 rows)
:PREFIX SELECT * FROM hyper WHERE time_bucket(10, time) <= 10::bigint ORDER BY time;
QUERY PLAN
---------------------------------------------------------------------------
Sort
Sort Key: _hyper_1_1_chunk."time"
-> Append
-> Seq Scan on _hyper_1_1_chunk
Filter: (time_bucket('10'::bigint, "time") <= '10'::bigint)
-> Seq Scan on _hyper_1_2_chunk
Filter: (time_bucket('10'::bigint, "time") <= '10'::bigint)
-> Seq Scan on _hyper_1_3_chunk
Filter: (time_bucket('10'::bigint, "time") <= '10'::bigint)
(9 rows)
:PREFIX SELECT * FROM hyper WHERE 10::bigint > time_bucket(10, time) ORDER BY time;
QUERY PLAN
--------------------------------------------------------------------------
Sort
Sort Key: _hyper_1_1_chunk."time"
-> Append
-> Seq Scan on _hyper_1_1_chunk
Filter: ('10'::bigint > time_bucket('10'::bigint, "time"))
-> Seq Scan on _hyper_1_2_chunk
Filter: ('10'::bigint > time_bucket('10'::bigint, "time"))
(7 rows)
:PREFIX SELECT * FROM hyper WHERE 11::bigint > time_bucket(10, time) ORDER BY time;
QUERY PLAN
--------------------------------------------------------------------------
Sort
Sort Key: _hyper_1_1_chunk."time"
-> Append
-> Seq Scan on _hyper_1_1_chunk
Filter: ('11'::bigint > time_bucket('10'::bigint, "time"))
-> Seq Scan on _hyper_1_2_chunk
Filter: ('11'::bigint > time_bucket('10'::bigint, "time"))
-> Seq Scan on _hyper_1_3_chunk
Filter: ('11'::bigint > time_bucket('10'::bigint, "time"))
(9 rows)
:PREFIX SELECT * FROM hyper WHERE time_bucket(10, time) > 10 AND time_bucket(10, time) < 100 ORDER BY time;
QUERY PLAN
----------------------------------------------------------------------------------------------------------------
Sort
Sort Key: _hyper_1_8_chunk."time"
-> Append
-> Seq Scan on _hyper_1_8_chunk
Filter: ((time_bucket('10'::bigint, "time") > 10) AND (time_bucket('10'::bigint, "time") < 100))
-> Seq Scan on _hyper_1_10_chunk
Filter: ((time_bucket('10'::bigint, "time") > 10) AND (time_bucket('10'::bigint, "time") < 100))
-> Seq Scan on _hyper_1_11_chunk
Filter: ((time_bucket('10'::bigint, "time") > 10) AND (time_bucket('10'::bigint, "time") < 100))
-> Seq Scan on _hyper_1_4_chunk
Filter: ((time_bucket('10'::bigint, "time") > 10) AND (time_bucket('10'::bigint, "time") < 100))
-> Seq Scan on _hyper_1_6_chunk
Filter: ((time_bucket('10'::bigint, "time") > 10) AND (time_bucket('10'::bigint, "time") < 100))
-> Seq Scan on _hyper_1_2_chunk
Filter: ((time_bucket('10'::bigint, "time") > 10) AND (time_bucket('10'::bigint, "time") < 100))
-> Seq Scan on _hyper_1_3_chunk
Filter: ((time_bucket('10'::bigint, "time") > 10) AND (time_bucket('10'::bigint, "time") < 100))
-> Seq Scan on _hyper_1_5_chunk
Filter: ((time_bucket('10'::bigint, "time") > 10) AND (time_bucket('10'::bigint, "time") < 100))
-> Seq Scan on _hyper_1_9_chunk
Filter: ((time_bucket('10'::bigint, "time") > 10) AND (time_bucket('10'::bigint, "time") < 100))
-> Seq Scan on _hyper_1_7_chunk
Filter: ((time_bucket('10'::bigint, "time") > 10) AND (time_bucket('10'::bigint, "time") < 100))
(23 rows)
:PREFIX SELECT * FROM hyper WHERE time_bucket(10, time) > 10 AND time_bucket(10, time) < 20 ORDER BY time;
QUERY PLAN
---------------------------------------------------------------------------------------------------------------
Sort
Sort Key: _hyper_1_2_chunk."time"
-> Append
-> Seq Scan on _hyper_1_2_chunk
Filter: ((time_bucket('10'::bigint, "time") > 10) AND (time_bucket('10'::bigint, "time") < 20))
-> Seq Scan on _hyper_1_3_chunk
Filter: ((time_bucket('10'::bigint, "time") > 10) AND (time_bucket('10'::bigint, "time") < 20))
(7 rows)
:PREFIX SELECT * FROM hyper WHERE time_bucket(1, time) > 11 AND time_bucket(1, time) < 19 ORDER BY time;
QUERY PLAN
-------------------------------------------------------------------------------------------------------------
Sort
Sort Key: _hyper_1_2_chunk."time"
-> Append
-> Seq Scan on _hyper_1_2_chunk
Filter: ((time_bucket('1'::bigint, "time") > 11) AND (time_bucket('1'::bigint, "time") < 19))
(5 rows)
:PREFIX SELECT * FROM hyper WHERE 10 < time_bucket(10, time) AND 20 > time_bucket(10,time) ORDER BY time;
QUERY PLAN
---------------------------------------------------------------------------------------------------------------
Sort
Sort Key: _hyper_1_2_chunk."time"
-> Append
-> Seq Scan on _hyper_1_2_chunk
Filter: ((10 < time_bucket('10'::bigint, "time")) AND (20 > time_bucket('10'::bigint, "time")))
-> Seq Scan on _hyper_1_3_chunk
Filter: ((10 < time_bucket('10'::bigint, "time")) AND (20 > time_bucket('10'::bigint, "time")))
(7 rows)
-- time_bucket exclusion with date
:PREFIX SELECT * FROM metrics_date WHERE time_bucket('1d',time) < '2000-01-03' ORDER BY time;
QUERY PLAN
-----------------------------------------------------------------------------------------------------
Merge Append
Sort Key: _hyper_7_165_chunk."time"
-> Index Only Scan Backward using _hyper_7_165_chunk_metrics_date_time_idx on _hyper_7_165_chunk
Filter: (time_bucket('@ 1 day'::interval, "time") < '01-03-2000'::date)
(4 rows)
:PREFIX SELECT * FROM metrics_date WHERE time_bucket('1d',time) >= '2000-01-03' AND time_bucket('1d',time) <= '2000-01-10' ORDER BY time;
QUERY PLAN
---------------------------------------------------------------------------------------------------------------------------------------------------------------
Sort
Sort Key: _hyper_7_166_chunk."time"
-> Append
-> Seq Scan on _hyper_7_166_chunk
Filter: ((time_bucket('@ 1 day'::interval, "time") >= '01-03-2000'::date) AND (time_bucket('@ 1 day'::interval, "time") <= '01-10-2000'::date))
-> Seq Scan on _hyper_7_165_chunk
Filter: ((time_bucket('@ 1 day'::interval, "time") >= '01-03-2000'::date) AND (time_bucket('@ 1 day'::interval, "time") <= '01-10-2000'::date))
(7 rows)
-- time_bucket exclusion with timestamp
:PREFIX SELECT * FROM metrics_timestamp WHERE time_bucket('1d',time) < '2000-01-03' ORDER BY time;
QUERY PLAN
----------------------------------------------------------------------------------------------------------------------
Merge Append
Sort Key: _hyper_5_155_chunk."time"
-> Index Only Scan Backward using _hyper_5_155_chunk_metrics_timestamp_time_idx on _hyper_5_155_chunk
Filter: (time_bucket('@ 1 day'::interval, "time") < 'Mon Jan 03 00:00:00 2000'::timestamp without time zone)
(4 rows)
:PREFIX SELECT * FROM metrics_timestamp WHERE time_bucket('1d',time) >= '2000-01-03' AND time_bucket('1d',time) <= '2000-01-10' ORDER BY time;
QUERY PLAN
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Sort
Sort Key: _hyper_5_156_chunk."time"
-> Append
-> Seq Scan on _hyper_5_156_chunk
Filter: ((time_bucket('@ 1 day'::interval, "time") >= 'Mon Jan 03 00:00:00 2000'::timestamp without time zone) AND (time_bucket('@ 1 day'::interval, "time") <= 'Mon Jan 10 00:00:00 2000'::timestamp without time zone))
-> Seq Scan on _hyper_5_155_chunk
Filter: ((time_bucket('@ 1 day'::interval, "time") >= 'Mon Jan 03 00:00:00 2000'::timestamp without time zone) AND (time_bucket('@ 1 day'::interval, "time") <= 'Mon Jan 10 00:00:00 2000'::timestamp without time zone))
(7 rows)
-- time_bucket exclusion with timestamptz
:PREFIX SELECT * FROM metrics_timestamptz WHERE time_bucket('6h',time) < '2000-01-03' ORDER BY time;
QUERY PLAN
-------------------------------------------------------------------------------------------------------------------------
Merge Append
Sort Key: _hyper_6_160_chunk."time"
-> Index Only Scan Backward using _hyper_6_160_chunk_metrics_timestamptz_time_idx on _hyper_6_160_chunk
Filter: (time_bucket('@ 6 hours'::interval, "time") < 'Mon Jan 03 00:00:00 2000 PST'::timestamp with time zone)
(4 rows)
:PREFIX SELECT * FROM metrics_timestamptz WHERE time_bucket('6h',time) >= '2000-01-03' AND time_bucket('6h',time) <= '2000-01-10' ORDER BY time;
QUERY PLAN
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Sort
Sort Key: _hyper_6_160_chunk."time"
-> Append
-> Seq Scan on _hyper_6_160_chunk
Filter: ((time_bucket('@ 6 hours'::interval, "time") >= 'Mon Jan 03 00:00:00 2000 PST'::timestamp with time zone) AND (time_bucket('@ 6 hours'::interval, "time") <= 'Mon Jan 10 00:00:00 2000 PST'::timestamp with time zone))
-> Seq Scan on _hyper_6_161_chunk
Filter: ((time_bucket('@ 6 hours'::interval, "time") >= 'Mon Jan 03 00:00:00 2000 PST'::timestamp with time zone) AND (time_bucket('@ 6 hours'::interval, "time") <= 'Mon Jan 10 00:00:00 2000 PST'::timestamp with time zone))
(7 rows)
-- time_bucket exclusion with timestamptz and day interval
:PREFIX SELECT * FROM metrics_timestamptz WHERE time_bucket('1d',time) < '2000-01-03' ORDER BY time;
QUERY PLAN
-----------------------------------------------------------------------------------------------------------------------
Merge Append
Sort Key: _hyper_6_160_chunk."time"
-> Index Only Scan Backward using _hyper_6_160_chunk_metrics_timestamptz_time_idx on _hyper_6_160_chunk
Filter: (time_bucket('@ 1 day'::interval, "time") < 'Mon Jan 03 00:00:00 2000 PST'::timestamp with time zone)
(4 rows)
:PREFIX SELECT * FROM metrics_timestamptz WHERE time_bucket('1d',time) >= '2000-01-03' AND time_bucket('1d',time) <= '2000-01-10' ORDER BY time;
QUERY PLAN
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Sort
Sort Key: _hyper_6_160_chunk."time"
-> Append
-> Seq Scan on _hyper_6_160_chunk
Filter: ((time_bucket('@ 1 day'::interval, "time") >= 'Mon Jan 03 00:00:00 2000 PST'::timestamp with time zone) AND (time_bucket('@ 1 day'::interval, "time") <= 'Mon Jan 10 00:00:00 2000 PST'::timestamp with time zone))
-> Seq Scan on _hyper_6_161_chunk
Filter: ((time_bucket('@ 1 day'::interval, "time") >= 'Mon Jan 03 00:00:00 2000 PST'::timestamp with time zone) AND (time_bucket('@ 1 day'::interval, "time") <= 'Mon Jan 10 00:00:00 2000 PST'::timestamp with time zone))
(7 rows)
:PREFIX SELECT * FROM metrics_timestamptz WHERE time_bucket('1d',time) >= '2000-01-03' AND time_bucket('7d',time) <= '2000-01-10' ORDER BY time;
QUERY PLAN
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Sort
Sort Key: _hyper_6_162_chunk."time"
-> Append
-> Seq Scan on _hyper_6_162_chunk
Filter: ((time_bucket('@ 1 day'::interval, "time") >= 'Mon Jan 03 00:00:00 2000 PST'::timestamp with time zone) AND (time_bucket('@ 7 days'::interval, "time") <= 'Mon Jan 10 00:00:00 2000 PST'::timestamp with time zone))
-> Seq Scan on _hyper_6_160_chunk
Filter: ((time_bucket('@ 1 day'::interval, "time") >= 'Mon Jan 03 00:00:00 2000 PST'::timestamp with time zone) AND (time_bucket('@ 7 days'::interval, "time") <= 'Mon Jan 10 00:00:00 2000 PST'::timestamp with time zone))
-> Seq Scan on _hyper_6_161_chunk
Filter: ((time_bucket('@ 1 day'::interval, "time") >= 'Mon Jan 03 00:00:00 2000 PST'::timestamp with time zone) AND (time_bucket('@ 7 days'::interval, "time") <= 'Mon Jan 10 00:00:00 2000 PST'::timestamp with time zone))
(9 rows)
--exclude chunks based on time column with partitioning function. This
--transparently applies the time partitioning function on the time
--value to be able to exclude chunks (similar to a closed dimension).

View File

@ -68,6 +68,33 @@ psql:include/plan_expand_hypertable_load.sql:57: WARNING: unexpected interval:
(1 row)
INSERT INTO hyper_timefunc (time, device_id, value) SELECT g, 'dev' || g, g FROM generate_series(0,30) g;
CREATE TABLE metrics_timestamp(time timestamp);
SELECT create_hypertable('metrics_timestamp','time');
psql:include/plan_expand_hypertable_load.sql:62: NOTICE: adding not-null constraint to column "time"
create_hypertable
--------------------------------
(5,public,metrics_timestamp,t)
(1 row)
INSERT INTO metrics_timestamp SELECT generate_series('2000-01-01'::timestamp,'2000-02-01'::timestamp,'1d'::interval);
CREATE TABLE metrics_timestamptz(time timestamptz);
SELECT create_hypertable('metrics_timestamptz','time');
psql:include/plan_expand_hypertable_load.sql:66: NOTICE: adding not-null constraint to column "time"
create_hypertable
----------------------------------
(6,public,metrics_timestamptz,t)
(1 row)
INSERT INTO metrics_timestamptz SELECT generate_series('2000-01-01'::timestamptz,'2000-02-01'::timestamptz,'1d'::interval);
CREATE TABLE metrics_date(time date);
SELECT create_hypertable('metrics_date','time');
psql:include/plan_expand_hypertable_load.sql:70: NOTICE: adding not-null constraint to column "time"
create_hypertable
---------------------------
(7,public,metrics_date,t)
(1 row)
INSERT INTO metrics_date SELECT generate_series('2000-01-01'::date,'2000-02-01'::date,'1d'::interval);
ANALYZE hyper;
ANALYZE hyper_w_space;
ANALYZE tag;
@ -884,6 +911,237 @@ SELECT * FROM cte ORDER BY value;
Filter: (name = 'tag1'::text)
(9 rows)
-- time_bucket exclusion
:PREFIX SELECT * FROM hyper WHERE time_bucket(10, time) < 10::bigint ORDER BY time;
QUERY PLAN
--------------------------------------------------------------------------
Sort
Sort Key: _hyper_1_1_chunk."time"
-> Append
-> Seq Scan on _hyper_1_1_chunk
Filter: (time_bucket('10'::bigint, "time") < '10'::bigint)
-> Seq Scan on _hyper_1_2_chunk
Filter: (time_bucket('10'::bigint, "time") < '10'::bigint)
(7 rows)
:PREFIX SELECT * FROM hyper WHERE time_bucket(10, time) < 11::bigint ORDER BY time;
QUERY PLAN
--------------------------------------------------------------------------
Sort
Sort Key: _hyper_1_1_chunk."time"
-> Append
-> Seq Scan on _hyper_1_1_chunk
Filter: (time_bucket('10'::bigint, "time") < '11'::bigint)
-> Seq Scan on _hyper_1_2_chunk
Filter: (time_bucket('10'::bigint, "time") < '11'::bigint)
-> Seq Scan on _hyper_1_3_chunk
Filter: (time_bucket('10'::bigint, "time") < '11'::bigint)
(9 rows)
:PREFIX SELECT * FROM hyper WHERE time_bucket(10, time) <= 10::bigint ORDER BY time;
QUERY PLAN
---------------------------------------------------------------------------
Sort
Sort Key: _hyper_1_1_chunk."time"
-> Append
-> Seq Scan on _hyper_1_1_chunk
Filter: (time_bucket('10'::bigint, "time") <= '10'::bigint)
-> Seq Scan on _hyper_1_2_chunk
Filter: (time_bucket('10'::bigint, "time") <= '10'::bigint)
-> Seq Scan on _hyper_1_3_chunk
Filter: (time_bucket('10'::bigint, "time") <= '10'::bigint)
(9 rows)
:PREFIX SELECT * FROM hyper WHERE 10::bigint > time_bucket(10, time) ORDER BY time;
QUERY PLAN
--------------------------------------------------------------------------
Sort
Sort Key: _hyper_1_1_chunk."time"
-> Append
-> Seq Scan on _hyper_1_1_chunk
Filter: ('10'::bigint > time_bucket('10'::bigint, "time"))
-> Seq Scan on _hyper_1_2_chunk
Filter: ('10'::bigint > time_bucket('10'::bigint, "time"))
(7 rows)
:PREFIX SELECT * FROM hyper WHERE 11::bigint > time_bucket(10, time) ORDER BY time;
QUERY PLAN
--------------------------------------------------------------------------
Sort
Sort Key: _hyper_1_1_chunk."time"
-> Append
-> Seq Scan on _hyper_1_1_chunk
Filter: ('11'::bigint > time_bucket('10'::bigint, "time"))
-> Seq Scan on _hyper_1_2_chunk
Filter: ('11'::bigint > time_bucket('10'::bigint, "time"))
-> Seq Scan on _hyper_1_3_chunk
Filter: ('11'::bigint > time_bucket('10'::bigint, "time"))
(9 rows)
:PREFIX SELECT * FROM hyper WHERE time_bucket(10, time) > 10 AND time_bucket(10, time) < 100 ORDER BY time;
QUERY PLAN
----------------------------------------------------------------------------------------------------------------
Sort
Sort Key: _hyper_1_8_chunk."time"
-> Append
-> Seq Scan on _hyper_1_8_chunk
Filter: ((time_bucket('10'::bigint, "time") > 10) AND (time_bucket('10'::bigint, "time") < 100))
-> Seq Scan on _hyper_1_10_chunk
Filter: ((time_bucket('10'::bigint, "time") > 10) AND (time_bucket('10'::bigint, "time") < 100))
-> Seq Scan on _hyper_1_11_chunk
Filter: ((time_bucket('10'::bigint, "time") > 10) AND (time_bucket('10'::bigint, "time") < 100))
-> Seq Scan on _hyper_1_4_chunk
Filter: ((time_bucket('10'::bigint, "time") > 10) AND (time_bucket('10'::bigint, "time") < 100))
-> Seq Scan on _hyper_1_6_chunk
Filter: ((time_bucket('10'::bigint, "time") > 10) AND (time_bucket('10'::bigint, "time") < 100))
-> Seq Scan on _hyper_1_2_chunk
Filter: ((time_bucket('10'::bigint, "time") > 10) AND (time_bucket('10'::bigint, "time") < 100))
-> Seq Scan on _hyper_1_3_chunk
Filter: ((time_bucket('10'::bigint, "time") > 10) AND (time_bucket('10'::bigint, "time") < 100))
-> Seq Scan on _hyper_1_5_chunk
Filter: ((time_bucket('10'::bigint, "time") > 10) AND (time_bucket('10'::bigint, "time") < 100))
-> Seq Scan on _hyper_1_9_chunk
Filter: ((time_bucket('10'::bigint, "time") > 10) AND (time_bucket('10'::bigint, "time") < 100))
-> Seq Scan on _hyper_1_7_chunk
Filter: ((time_bucket('10'::bigint, "time") > 10) AND (time_bucket('10'::bigint, "time") < 100))
(23 rows)
:PREFIX SELECT * FROM hyper WHERE time_bucket(10, time) > 10 AND time_bucket(10, time) < 20 ORDER BY time;
QUERY PLAN
---------------------------------------------------------------------------------------------------------------
Sort
Sort Key: _hyper_1_2_chunk."time"
-> Append
-> Seq Scan on _hyper_1_2_chunk
Filter: ((time_bucket('10'::bigint, "time") > 10) AND (time_bucket('10'::bigint, "time") < 20))
-> Seq Scan on _hyper_1_3_chunk
Filter: ((time_bucket('10'::bigint, "time") > 10) AND (time_bucket('10'::bigint, "time") < 20))
(7 rows)
:PREFIX SELECT * FROM hyper WHERE time_bucket(1, time) > 11 AND time_bucket(1, time) < 19 ORDER BY time;
QUERY PLAN
-------------------------------------------------------------------------------------------------------------
Sort
Sort Key: _hyper_1_2_chunk."time"
-> Append
-> Seq Scan on _hyper_1_2_chunk
Filter: ((time_bucket('1'::bigint, "time") > 11) AND (time_bucket('1'::bigint, "time") < 19))
(5 rows)
:PREFIX SELECT * FROM hyper WHERE 10 < time_bucket(10, time) AND 20 > time_bucket(10,time) ORDER BY time;
QUERY PLAN
---------------------------------------------------------------------------------------------------------------
Sort
Sort Key: _hyper_1_2_chunk."time"
-> Append
-> Seq Scan on _hyper_1_2_chunk
Filter: ((10 < time_bucket('10'::bigint, "time")) AND (20 > time_bucket('10'::bigint, "time")))
-> Seq Scan on _hyper_1_3_chunk
Filter: ((10 < time_bucket('10'::bigint, "time")) AND (20 > time_bucket('10'::bigint, "time")))
(7 rows)
-- time_bucket exclusion with date
:PREFIX SELECT * FROM metrics_date WHERE time_bucket('1d',time) < '2000-01-03' ORDER BY time;
QUERY PLAN
-----------------------------------------------------------------------------------------------------
Merge Append
Sort Key: _hyper_7_165_chunk."time"
-> Index Only Scan Backward using _hyper_7_165_chunk_metrics_date_time_idx on _hyper_7_165_chunk
Filter: (time_bucket('@ 1 day'::interval, "time") < '01-03-2000'::date)
(4 rows)
:PREFIX SELECT * FROM metrics_date WHERE time_bucket('1d',time) >= '2000-01-03' AND time_bucket('1d',time) <= '2000-01-10' ORDER BY time;
QUERY PLAN
---------------------------------------------------------------------------------------------------------------------------------------------------------------
Sort
Sort Key: _hyper_7_166_chunk."time"
-> Append
-> Seq Scan on _hyper_7_166_chunk
Filter: ((time_bucket('@ 1 day'::interval, "time") >= '01-03-2000'::date) AND (time_bucket('@ 1 day'::interval, "time") <= '01-10-2000'::date))
-> Seq Scan on _hyper_7_165_chunk
Filter: ((time_bucket('@ 1 day'::interval, "time") >= '01-03-2000'::date) AND (time_bucket('@ 1 day'::interval, "time") <= '01-10-2000'::date))
(7 rows)
-- time_bucket exclusion with timestamp
:PREFIX SELECT * FROM metrics_timestamp WHERE time_bucket('1d',time) < '2000-01-03' ORDER BY time;
QUERY PLAN
----------------------------------------------------------------------------------------------------------------------
Merge Append
Sort Key: _hyper_5_155_chunk."time"
-> Index Only Scan Backward using _hyper_5_155_chunk_metrics_timestamp_time_idx on _hyper_5_155_chunk
Filter: (time_bucket('@ 1 day'::interval, "time") < 'Mon Jan 03 00:00:00 2000'::timestamp without time zone)
(4 rows)
:PREFIX SELECT * FROM metrics_timestamp WHERE time_bucket('1d',time) >= '2000-01-03' AND time_bucket('1d',time) <= '2000-01-10' ORDER BY time;
QUERY PLAN
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Sort
Sort Key: _hyper_5_156_chunk."time"
-> Append
-> Seq Scan on _hyper_5_156_chunk
Filter: ((time_bucket('@ 1 day'::interval, "time") >= 'Mon Jan 03 00:00:00 2000'::timestamp without time zone) AND (time_bucket('@ 1 day'::interval, "time") <= 'Mon Jan 10 00:00:00 2000'::timestamp without time zone))
-> Seq Scan on _hyper_5_155_chunk
Filter: ((time_bucket('@ 1 day'::interval, "time") >= 'Mon Jan 03 00:00:00 2000'::timestamp without time zone) AND (time_bucket('@ 1 day'::interval, "time") <= 'Mon Jan 10 00:00:00 2000'::timestamp without time zone))
(7 rows)
-- time_bucket exclusion with timestamptz
:PREFIX SELECT * FROM metrics_timestamptz WHERE time_bucket('6h',time) < '2000-01-03' ORDER BY time;
QUERY PLAN
-------------------------------------------------------------------------------------------------------------------------
Merge Append
Sort Key: _hyper_6_160_chunk."time"
-> Index Only Scan Backward using _hyper_6_160_chunk_metrics_timestamptz_time_idx on _hyper_6_160_chunk
Filter: (time_bucket('@ 6 hours'::interval, "time") < 'Mon Jan 03 00:00:00 2000 PST'::timestamp with time zone)
(4 rows)
:PREFIX SELECT * FROM metrics_timestamptz WHERE time_bucket('6h',time) >= '2000-01-03' AND time_bucket('6h',time) <= '2000-01-10' ORDER BY time;
QUERY PLAN
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Sort
Sort Key: _hyper_6_160_chunk."time"
-> Append
-> Seq Scan on _hyper_6_160_chunk
Filter: ((time_bucket('@ 6 hours'::interval, "time") >= 'Mon Jan 03 00:00:00 2000 PST'::timestamp with time zone) AND (time_bucket('@ 6 hours'::interval, "time") <= 'Mon Jan 10 00:00:00 2000 PST'::timestamp with time zone))
-> Seq Scan on _hyper_6_161_chunk
Filter: ((time_bucket('@ 6 hours'::interval, "time") >= 'Mon Jan 03 00:00:00 2000 PST'::timestamp with time zone) AND (time_bucket('@ 6 hours'::interval, "time") <= 'Mon Jan 10 00:00:00 2000 PST'::timestamp with time zone))
(7 rows)
-- time_bucket exclusion with timestamptz and day interval
:PREFIX SELECT * FROM metrics_timestamptz WHERE time_bucket('1d',time) < '2000-01-03' ORDER BY time;
QUERY PLAN
-----------------------------------------------------------------------------------------------------------------------
Merge Append
Sort Key: _hyper_6_160_chunk."time"
-> Index Only Scan Backward using _hyper_6_160_chunk_metrics_timestamptz_time_idx on _hyper_6_160_chunk
Filter: (time_bucket('@ 1 day'::interval, "time") < 'Mon Jan 03 00:00:00 2000 PST'::timestamp with time zone)
(4 rows)
:PREFIX SELECT * FROM metrics_timestamptz WHERE time_bucket('1d',time) >= '2000-01-03' AND time_bucket('1d',time) <= '2000-01-10' ORDER BY time;
QUERY PLAN
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Sort
Sort Key: _hyper_6_160_chunk."time"
-> Append
-> Seq Scan on _hyper_6_160_chunk
Filter: ((time_bucket('@ 1 day'::interval, "time") >= 'Mon Jan 03 00:00:00 2000 PST'::timestamp with time zone) AND (time_bucket('@ 1 day'::interval, "time") <= 'Mon Jan 10 00:00:00 2000 PST'::timestamp with time zone))
-> Seq Scan on _hyper_6_161_chunk
Filter: ((time_bucket('@ 1 day'::interval, "time") >= 'Mon Jan 03 00:00:00 2000 PST'::timestamp with time zone) AND (time_bucket('@ 1 day'::interval, "time") <= 'Mon Jan 10 00:00:00 2000 PST'::timestamp with time zone))
(7 rows)
:PREFIX SELECT * FROM metrics_timestamptz WHERE time_bucket('1d',time) >= '2000-01-03' AND time_bucket('7d',time) <= '2000-01-10' ORDER BY time;
QUERY PLAN
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Sort
Sort Key: _hyper_6_162_chunk."time"
-> Append
-> Seq Scan on _hyper_6_162_chunk
Filter: ((time_bucket('@ 1 day'::interval, "time") >= 'Mon Jan 03 00:00:00 2000 PST'::timestamp with time zone) AND (time_bucket('@ 7 days'::interval, "time") <= 'Mon Jan 10 00:00:00 2000 PST'::timestamp with time zone))
-> Seq Scan on _hyper_6_160_chunk
Filter: ((time_bucket('@ 1 day'::interval, "time") >= 'Mon Jan 03 00:00:00 2000 PST'::timestamp with time zone) AND (time_bucket('@ 7 days'::interval, "time") <= 'Mon Jan 10 00:00:00 2000 PST'::timestamp with time zone))
-> Seq Scan on _hyper_6_161_chunk
Filter: ((time_bucket('@ 1 day'::interval, "time") >= 'Mon Jan 03 00:00:00 2000 PST'::timestamp with time zone) AND (time_bucket('@ 7 days'::interval, "time") <= 'Mon Jan 10 00:00:00 2000 PST'::timestamp with time zone))
(9 rows)
--exclude chunks based on time column with partitioning function. This
--transparently applies the time partitioning function on the time
--value to be able to exclude chunks (similar to a closed dimension).

View File

@ -68,6 +68,33 @@ psql:include/plan_expand_hypertable_load.sql:57: WARNING: unexpected interval:
(1 row)
INSERT INTO hyper_timefunc (time, device_id, value) SELECT g, 'dev' || g, g FROM generate_series(0,30) g;
CREATE TABLE metrics_timestamp(time timestamp);
SELECT create_hypertable('metrics_timestamp','time');
psql:include/plan_expand_hypertable_load.sql:62: NOTICE: adding not-null constraint to column "time"
create_hypertable
--------------------------------
(5,public,metrics_timestamp,t)
(1 row)
INSERT INTO metrics_timestamp SELECT generate_series('2000-01-01'::timestamp,'2000-02-01'::timestamp,'1d'::interval);
CREATE TABLE metrics_timestamptz(time timestamptz);
SELECT create_hypertable('metrics_timestamptz','time');
psql:include/plan_expand_hypertable_load.sql:66: NOTICE: adding not-null constraint to column "time"
create_hypertable
----------------------------------
(6,public,metrics_timestamptz,t)
(1 row)
INSERT INTO metrics_timestamptz SELECT generate_series('2000-01-01'::timestamptz,'2000-02-01'::timestamptz,'1d'::interval);
CREATE TABLE metrics_date(time date);
SELECT create_hypertable('metrics_date','time');
psql:include/plan_expand_hypertable_load.sql:70: NOTICE: adding not-null constraint to column "time"
create_hypertable
---------------------------
(7,public,metrics_date,t)
(1 row)
INSERT INTO metrics_date SELECT generate_series('2000-01-01'::date,'2000-02-01'::date,'1d'::interval);
ANALYZE hyper;
ANALYZE hyper_w_space;
ANALYZE tag;
@ -883,6 +910,237 @@ SELECT * FROM cte ORDER BY value;
Filter: (name = 'tag1'::text)
(9 rows)
-- time_bucket exclusion
:PREFIX SELECT * FROM hyper WHERE time_bucket(10, time) < 10::bigint ORDER BY time;
QUERY PLAN
--------------------------------------------------------------------------
Sort
Sort Key: _hyper_1_1_chunk."time"
-> Append
-> Seq Scan on _hyper_1_1_chunk
Filter: (time_bucket('10'::bigint, "time") < '10'::bigint)
-> Seq Scan on _hyper_1_2_chunk
Filter: (time_bucket('10'::bigint, "time") < '10'::bigint)
(7 rows)
:PREFIX SELECT * FROM hyper WHERE time_bucket(10, time) < 11::bigint ORDER BY time;
QUERY PLAN
--------------------------------------------------------------------------
Sort
Sort Key: _hyper_1_1_chunk."time"
-> Append
-> Seq Scan on _hyper_1_1_chunk
Filter: (time_bucket('10'::bigint, "time") < '11'::bigint)
-> Seq Scan on _hyper_1_2_chunk
Filter: (time_bucket('10'::bigint, "time") < '11'::bigint)
-> Seq Scan on _hyper_1_3_chunk
Filter: (time_bucket('10'::bigint, "time") < '11'::bigint)
(9 rows)
:PREFIX SELECT * FROM hyper WHERE time_bucket(10, time) <= 10::bigint ORDER BY time;
QUERY PLAN
---------------------------------------------------------------------------
Sort
Sort Key: _hyper_1_1_chunk."time"
-> Append
-> Seq Scan on _hyper_1_1_chunk
Filter: (time_bucket('10'::bigint, "time") <= '10'::bigint)
-> Seq Scan on _hyper_1_2_chunk
Filter: (time_bucket('10'::bigint, "time") <= '10'::bigint)
-> Seq Scan on _hyper_1_3_chunk
Filter: (time_bucket('10'::bigint, "time") <= '10'::bigint)
(9 rows)
:PREFIX SELECT * FROM hyper WHERE 10::bigint > time_bucket(10, time) ORDER BY time;
QUERY PLAN
--------------------------------------------------------------------------
Sort
Sort Key: _hyper_1_1_chunk."time"
-> Append
-> Seq Scan on _hyper_1_1_chunk
Filter: ('10'::bigint > time_bucket('10'::bigint, "time"))
-> Seq Scan on _hyper_1_2_chunk
Filter: ('10'::bigint > time_bucket('10'::bigint, "time"))
(7 rows)
:PREFIX SELECT * FROM hyper WHERE 11::bigint > time_bucket(10, time) ORDER BY time;
QUERY PLAN
--------------------------------------------------------------------------
Sort
Sort Key: _hyper_1_1_chunk."time"
-> Append
-> Seq Scan on _hyper_1_1_chunk
Filter: ('11'::bigint > time_bucket('10'::bigint, "time"))
-> Seq Scan on _hyper_1_2_chunk
Filter: ('11'::bigint > time_bucket('10'::bigint, "time"))
-> Seq Scan on _hyper_1_3_chunk
Filter: ('11'::bigint > time_bucket('10'::bigint, "time"))
(9 rows)
:PREFIX SELECT * FROM hyper WHERE time_bucket(10, time) > 10 AND time_bucket(10, time) < 100 ORDER BY time;
QUERY PLAN
----------------------------------------------------------------------------------------------------------------
Sort
Sort Key: _hyper_1_8_chunk."time"
-> Append
-> Seq Scan on _hyper_1_8_chunk
Filter: ((time_bucket('10'::bigint, "time") > 10) AND (time_bucket('10'::bigint, "time") < 100))
-> Seq Scan on _hyper_1_10_chunk
Filter: ((time_bucket('10'::bigint, "time") > 10) AND (time_bucket('10'::bigint, "time") < 100))
-> Seq Scan on _hyper_1_11_chunk
Filter: ((time_bucket('10'::bigint, "time") > 10) AND (time_bucket('10'::bigint, "time") < 100))
-> Seq Scan on _hyper_1_4_chunk
Filter: ((time_bucket('10'::bigint, "time") > 10) AND (time_bucket('10'::bigint, "time") < 100))
-> Seq Scan on _hyper_1_6_chunk
Filter: ((time_bucket('10'::bigint, "time") > 10) AND (time_bucket('10'::bigint, "time") < 100))
-> Seq Scan on _hyper_1_2_chunk
Filter: ((time_bucket('10'::bigint, "time") > 10) AND (time_bucket('10'::bigint, "time") < 100))
-> Seq Scan on _hyper_1_3_chunk
Filter: ((time_bucket('10'::bigint, "time") > 10) AND (time_bucket('10'::bigint, "time") < 100))
-> Seq Scan on _hyper_1_5_chunk
Filter: ((time_bucket('10'::bigint, "time") > 10) AND (time_bucket('10'::bigint, "time") < 100))
-> Seq Scan on _hyper_1_9_chunk
Filter: ((time_bucket('10'::bigint, "time") > 10) AND (time_bucket('10'::bigint, "time") < 100))
-> Seq Scan on _hyper_1_7_chunk
Filter: ((time_bucket('10'::bigint, "time") > 10) AND (time_bucket('10'::bigint, "time") < 100))
(23 rows)
:PREFIX SELECT * FROM hyper WHERE time_bucket(10, time) > 10 AND time_bucket(10, time) < 20 ORDER BY time;
QUERY PLAN
---------------------------------------------------------------------------------------------------------------
Sort
Sort Key: _hyper_1_2_chunk."time"
-> Append
-> Seq Scan on _hyper_1_2_chunk
Filter: ((time_bucket('10'::bigint, "time") > 10) AND (time_bucket('10'::bigint, "time") < 20))
-> Seq Scan on _hyper_1_3_chunk
Filter: ((time_bucket('10'::bigint, "time") > 10) AND (time_bucket('10'::bigint, "time") < 20))
(7 rows)
:PREFIX SELECT * FROM hyper WHERE time_bucket(1, time) > 11 AND time_bucket(1, time) < 19 ORDER BY time;
QUERY PLAN
-------------------------------------------------------------------------------------------------------------
Sort
Sort Key: _hyper_1_2_chunk."time"
-> Append
-> Seq Scan on _hyper_1_2_chunk
Filter: ((time_bucket('1'::bigint, "time") > 11) AND (time_bucket('1'::bigint, "time") < 19))
(5 rows)
:PREFIX SELECT * FROM hyper WHERE 10 < time_bucket(10, time) AND 20 > time_bucket(10,time) ORDER BY time;
QUERY PLAN
---------------------------------------------------------------------------------------------------------------
Sort
Sort Key: _hyper_1_2_chunk."time"
-> Append
-> Seq Scan on _hyper_1_2_chunk
Filter: ((10 < time_bucket('10'::bigint, "time")) AND (20 > time_bucket('10'::bigint, "time")))
-> Seq Scan on _hyper_1_3_chunk
Filter: ((10 < time_bucket('10'::bigint, "time")) AND (20 > time_bucket('10'::bigint, "time")))
(7 rows)
-- time_bucket exclusion with date
:PREFIX SELECT * FROM metrics_date WHERE time_bucket('1d',time) < '2000-01-03' ORDER BY time;
QUERY PLAN
-----------------------------------------------------------------------------------------------------
Merge Append
Sort Key: _hyper_7_165_chunk."time"
-> Index Only Scan Backward using _hyper_7_165_chunk_metrics_date_time_idx on _hyper_7_165_chunk
Filter: (time_bucket('@ 1 day'::interval, "time") < '01-03-2000'::date)
(4 rows)
:PREFIX SELECT * FROM metrics_date WHERE time_bucket('1d',time) >= '2000-01-03' AND time_bucket('1d',time) <= '2000-01-10' ORDER BY time;
QUERY PLAN
---------------------------------------------------------------------------------------------------------------------------------------------------------------
Sort
Sort Key: _hyper_7_166_chunk."time"
-> Append
-> Seq Scan on _hyper_7_166_chunk
Filter: ((time_bucket('@ 1 day'::interval, "time") >= '01-03-2000'::date) AND (time_bucket('@ 1 day'::interval, "time") <= '01-10-2000'::date))
-> Seq Scan on _hyper_7_165_chunk
Filter: ((time_bucket('@ 1 day'::interval, "time") >= '01-03-2000'::date) AND (time_bucket('@ 1 day'::interval, "time") <= '01-10-2000'::date))
(7 rows)
-- time_bucket exclusion with timestamp
:PREFIX SELECT * FROM metrics_timestamp WHERE time_bucket('1d',time) < '2000-01-03' ORDER BY time;
QUERY PLAN
----------------------------------------------------------------------------------------------------------------------
Merge Append
Sort Key: _hyper_5_155_chunk."time"
-> Index Only Scan Backward using _hyper_5_155_chunk_metrics_timestamp_time_idx on _hyper_5_155_chunk
Filter: (time_bucket('@ 1 day'::interval, "time") < 'Mon Jan 03 00:00:00 2000'::timestamp without time zone)
(4 rows)
:PREFIX SELECT * FROM metrics_timestamp WHERE time_bucket('1d',time) >= '2000-01-03' AND time_bucket('1d',time) <= '2000-01-10' ORDER BY time;
QUERY PLAN
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Sort
Sort Key: _hyper_5_156_chunk."time"
-> Append
-> Seq Scan on _hyper_5_156_chunk
Filter: ((time_bucket('@ 1 day'::interval, "time") >= 'Mon Jan 03 00:00:00 2000'::timestamp without time zone) AND (time_bucket('@ 1 day'::interval, "time") <= 'Mon Jan 10 00:00:00 2000'::timestamp without time zone))
-> Seq Scan on _hyper_5_155_chunk
Filter: ((time_bucket('@ 1 day'::interval, "time") >= 'Mon Jan 03 00:00:00 2000'::timestamp without time zone) AND (time_bucket('@ 1 day'::interval, "time") <= 'Mon Jan 10 00:00:00 2000'::timestamp without time zone))
(7 rows)
-- time_bucket exclusion with timestamptz
:PREFIX SELECT * FROM metrics_timestamptz WHERE time_bucket('6h',time) < '2000-01-03' ORDER BY time;
QUERY PLAN
-------------------------------------------------------------------------------------------------------------------------
Merge Append
Sort Key: _hyper_6_160_chunk."time"
-> Index Only Scan Backward using _hyper_6_160_chunk_metrics_timestamptz_time_idx on _hyper_6_160_chunk
Filter: (time_bucket('@ 6 hours'::interval, "time") < 'Mon Jan 03 00:00:00 2000 PST'::timestamp with time zone)
(4 rows)
:PREFIX SELECT * FROM metrics_timestamptz WHERE time_bucket('6h',time) >= '2000-01-03' AND time_bucket('6h',time) <= '2000-01-10' ORDER BY time;
QUERY PLAN
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Sort
Sort Key: _hyper_6_160_chunk."time"
-> Append
-> Seq Scan on _hyper_6_160_chunk
Filter: ((time_bucket('@ 6 hours'::interval, "time") >= 'Mon Jan 03 00:00:00 2000 PST'::timestamp with time zone) AND (time_bucket('@ 6 hours'::interval, "time") <= 'Mon Jan 10 00:00:00 2000 PST'::timestamp with time zone))
-> Seq Scan on _hyper_6_161_chunk
Filter: ((time_bucket('@ 6 hours'::interval, "time") >= 'Mon Jan 03 00:00:00 2000 PST'::timestamp with time zone) AND (time_bucket('@ 6 hours'::interval, "time") <= 'Mon Jan 10 00:00:00 2000 PST'::timestamp with time zone))
(7 rows)
-- time_bucket exclusion with timestamptz and day interval
:PREFIX SELECT * FROM metrics_timestamptz WHERE time_bucket('1d',time) < '2000-01-03' ORDER BY time;
QUERY PLAN
-----------------------------------------------------------------------------------------------------------------------
Merge Append
Sort Key: _hyper_6_160_chunk."time"
-> Index Only Scan Backward using _hyper_6_160_chunk_metrics_timestamptz_time_idx on _hyper_6_160_chunk
Filter: (time_bucket('@ 1 day'::interval, "time") < 'Mon Jan 03 00:00:00 2000 PST'::timestamp with time zone)
(4 rows)
:PREFIX SELECT * FROM metrics_timestamptz WHERE time_bucket('1d',time) >= '2000-01-03' AND time_bucket('1d',time) <= '2000-01-10' ORDER BY time;
QUERY PLAN
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Sort
Sort Key: _hyper_6_160_chunk."time"
-> Append
-> Seq Scan on _hyper_6_160_chunk
Filter: ((time_bucket('@ 1 day'::interval, "time") >= 'Mon Jan 03 00:00:00 2000 PST'::timestamp with time zone) AND (time_bucket('@ 1 day'::interval, "time") <= 'Mon Jan 10 00:00:00 2000 PST'::timestamp with time zone))
-> Seq Scan on _hyper_6_161_chunk
Filter: ((time_bucket('@ 1 day'::interval, "time") >= 'Mon Jan 03 00:00:00 2000 PST'::timestamp with time zone) AND (time_bucket('@ 1 day'::interval, "time") <= 'Mon Jan 10 00:00:00 2000 PST'::timestamp with time zone))
(7 rows)
:PREFIX SELECT * FROM metrics_timestamptz WHERE time_bucket('1d',time) >= '2000-01-03' AND time_bucket('7d',time) <= '2000-01-10' ORDER BY time;
QUERY PLAN
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Sort
Sort Key: _hyper_6_162_chunk."time"
-> Append
-> Seq Scan on _hyper_6_162_chunk
Filter: ((time_bucket('@ 1 day'::interval, "time") >= 'Mon Jan 03 00:00:00 2000 PST'::timestamp with time zone) AND (time_bucket('@ 7 days'::interval, "time") <= 'Mon Jan 10 00:00:00 2000 PST'::timestamp with time zone))
-> Seq Scan on _hyper_6_160_chunk
Filter: ((time_bucket('@ 1 day'::interval, "time") >= 'Mon Jan 03 00:00:00 2000 PST'::timestamp with time zone) AND (time_bucket('@ 7 days'::interval, "time") <= 'Mon Jan 10 00:00:00 2000 PST'::timestamp with time zone))
-> Seq Scan on _hyper_6_161_chunk
Filter: ((time_bucket('@ 1 day'::interval, "time") >= 'Mon Jan 03 00:00:00 2000 PST'::timestamp with time zone) AND (time_bucket('@ 7 days'::interval, "time") <= 'Mon Jan 10 00:00:00 2000 PST'::timestamp with time zone))
(9 rows)
--exclude chunks based on time column with partitioning function. This
--transparently applies the time partitioning function on the time
--value to be able to exclude chunks (similar to a closed dimension).

View File

@ -58,6 +58,18 @@ SELECT create_hypertable('hyper_timefunc', 'time', 'device_id', 4, chunk_time_in
INSERT INTO hyper_timefunc (time, device_id, value) SELECT g, 'dev' || g, g FROM generate_series(0,30) g;
CREATE TABLE metrics_timestamp(time timestamp);
SELECT create_hypertable('metrics_timestamp','time');
INSERT INTO metrics_timestamp SELECT generate_series('2000-01-01'::timestamp,'2000-02-01'::timestamp,'1d'::interval);
CREATE TABLE metrics_timestamptz(time timestamptz);
SELECT create_hypertable('metrics_timestamptz','time');
INSERT INTO metrics_timestamptz SELECT generate_series('2000-01-01'::timestamptz,'2000-02-01'::timestamptz,'1d'::interval);
CREATE TABLE metrics_date(time date);
SELECT create_hypertable('metrics_date','time');
INSERT INTO metrics_date SELECT generate_series('2000-01-01'::date,'2000-02-01'::date,'1d'::interval);
ANALYZE hyper;
ANALYZE hyper_w_space;
ANALYZE tag;

View File

@ -139,6 +139,35 @@ SELECT * FROM cte ORDER BY value;
:PREFIX SELECT * FROM hyper_ts JOIN tag on (hyper_ts.tag_id = tag.id ) WHERE time < to_timestamp(10) and device_id = 'dev1' ORDER BY value;
:PREFIX SELECT * FROM hyper_ts JOIN tag on (hyper_ts.tag_id = tag.id ) WHERE tag.name = 'tag1' and time < to_timestamp(10) and device_id = 'dev1' ORDER BY value;
-- time_bucket exclusion
:PREFIX SELECT * FROM hyper WHERE time_bucket(10, time) < 10::bigint ORDER BY time;
:PREFIX SELECT * FROM hyper WHERE time_bucket(10, time) < 11::bigint ORDER BY time;
:PREFIX SELECT * FROM hyper WHERE time_bucket(10, time) <= 10::bigint ORDER BY time;
:PREFIX SELECT * FROM hyper WHERE 10::bigint > time_bucket(10, time) ORDER BY time;
:PREFIX SELECT * FROM hyper WHERE 11::bigint > time_bucket(10, time) ORDER BY time;
:PREFIX SELECT * FROM hyper WHERE time_bucket(10, time) > 10 AND time_bucket(10, time) < 100 ORDER BY time;
:PREFIX SELECT * FROM hyper WHERE time_bucket(10, time) > 10 AND time_bucket(10, time) < 20 ORDER BY time;
:PREFIX SELECT * FROM hyper WHERE time_bucket(1, time) > 11 AND time_bucket(1, time) < 19 ORDER BY time;
:PREFIX SELECT * FROM hyper WHERE 10 < time_bucket(10, time) AND 20 > time_bucket(10,time) ORDER BY time;
-- time_bucket exclusion with date
:PREFIX SELECT * FROM metrics_date WHERE time_bucket('1d',time) < '2000-01-03' ORDER BY time;
:PREFIX SELECT * FROM metrics_date WHERE time_bucket('1d',time) >= '2000-01-03' AND time_bucket('1d',time) <= '2000-01-10' ORDER BY time;
-- time_bucket exclusion with timestamp
:PREFIX SELECT * FROM metrics_timestamp WHERE time_bucket('1d',time) < '2000-01-03' ORDER BY time;
:PREFIX SELECT * FROM metrics_timestamp WHERE time_bucket('1d',time) >= '2000-01-03' AND time_bucket('1d',time) <= '2000-01-10' ORDER BY time;
-- time_bucket exclusion with timestamptz
:PREFIX SELECT * FROM metrics_timestamptz WHERE time_bucket('6h',time) < '2000-01-03' ORDER BY time;
:PREFIX SELECT * FROM metrics_timestamptz WHERE time_bucket('6h',time) >= '2000-01-03' AND time_bucket('6h',time) <= '2000-01-10' ORDER BY time;
-- time_bucket exclusion with timestamptz and day interval
:PREFIX SELECT * FROM metrics_timestamptz WHERE time_bucket('1d',time) < '2000-01-03' ORDER BY time;
:PREFIX SELECT * FROM metrics_timestamptz WHERE time_bucket('1d',time) >= '2000-01-03' AND time_bucket('1d',time) <= '2000-01-10' ORDER BY time;
:PREFIX SELECT * FROM metrics_timestamptz WHERE time_bucket('1d',time) >= '2000-01-03' AND time_bucket('7d',time) <= '2000-01-10' ORDER BY time;
--exclude chunks based on time column with partitioning function. This
--transparently applies the time partitioning function on the time
--value to be able to exclude chunks (similar to a closed dimension).