Avoid string conversion in hash partitioning

Hash partitioning previously relied on coercing (casting) values to
strings before calculating a hash value, including creating CHECK
constraints with casts. This approach is fairly suboptimal from a
performance perspective and might have issues related to different
character encodings depending on system.

Hash partitioning now instead uses a partitioning function that takes
an anyelement type that calls type-dependent hash functions internal
to PostgreSQL. This should provide more efficient hashing both by
avoiding unnecessary string conversions and by using more optimal
type-specific hash functions.

Support for the previous hash partitioning function is preserved for
backwards compatibility. Hypertables created with the previous
function will continue to use to old hashing strategy, while new
tables will default to the updated hash partitioning.

For safety, this change also blocks changing types on hash-partitioned
columns, since it seems hard to guarantee the same hash result between
different types.
This commit is contained in:
Erik Nordström 2017-10-16 20:54:02 +02:00 committed by Erik Nordström
parent 2ba1a40a9f
commit cf009cc584
30 changed files with 1043 additions and 239 deletions

View File

@ -151,7 +151,7 @@ CREATE OR REPLACE FUNCTION _timescaledb_internal.add_dimension(
RETURNS _timescaledb_catalog.dimension LANGUAGE PLPGSQL VOLATILE AS
$BODY$
DECLARE
partitioning_func _timescaledb_catalog.dimension.partitioning_func%TYPE = 'get_partition_for_key';
partitioning_func _timescaledb_catalog.dimension.partitioning_func%TYPE = 'get_partition_hash';
partitioning_func_schema _timescaledb_catalog.dimension.partitioning_func_schema%TYPE = '_timescaledb_internal';
aligned BOOL;
column_type REGTYPE;

View File

@ -1,4 +1,8 @@
-- our default partitioning function.
-- returns a hash of val modulous the mod_factor
CREATE OR REPLACE FUNCTION _timescaledb_internal.get_partition_for_key(val text) RETURNS int
-- Deprecated partition hash function
CREATE OR REPLACE FUNCTION _timescaledb_internal.get_partition_for_key(val text)
RETURNS int
AS '$libdir/timescaledb', 'get_partition_for_key' LANGUAGE C IMMUTABLE STRICT;
CREATE OR REPLACE FUNCTION _timescaledb_internal.get_partition_hash(val anyelement)
RETURNS int
AS '$libdir/timescaledb', 'get_partition_hash' LANGUAGE C IMMUTABLE STRICT;

View File

@ -82,6 +82,8 @@ $BODY$
DECLARE
dimension_slice_row _timescaledb_catalog.dimension_slice;
dimension_row _timescaledb_catalog.dimension;
proargtype OID;
typecast TEXT = '';
BEGIN
SELECT * INTO STRICT dimension_slice_row
FROM _timescaledb_catalog.dimension_slice
@ -92,12 +94,28 @@ BEGIN
WHERE id = dimension_slice_row.dimension_id;
IF dimension_row.partitioning_func IS NOT NULL THEN
SELECT proargtypes[0] INTO STRICT proargtype
FROM pg_proc p, pg_namespace n
WHERE n.nspname = dimension_row.partitioning_func_schema
AND p.proname = dimension_row.partitioning_func
AND n.oid = p.pronamespace;
-- Check if we are using a legacy partitioning function
-- that only takes text input
IF proargtype = 'text'::regtype THEN
typecast := '::text';
END IF;
return format(
$$
%1$I.%2$s(%3$I::text) >= %4$L AND %1$I.%2$s(%3$I::text) < %5$L
%1$I.%2$s(%3$I%4$s) >= %5$L AND %1$I.%2$s(%3$I%4$s) < %6$L
$$,
dimension_row.partitioning_func_schema, dimension_row.partitioning_func,
dimension_row.column_name, dimension_slice_row.range_start, dimension_slice_row.range_end);
dimension_row.partitioning_func_schema,
dimension_row.partitioning_func,
dimension_row.column_name,
typecast,
dimension_slice_row.range_start,
dimension_slice_row.range_end);
ELSE
--TODO: only works with time for now
IF _timescaledb_internal.time_literal_sql(dimension_slice_row.range_start, dimension_row.column_type) =

View File

@ -1,6 +1,7 @@
#include <postgres.h>
#include <access/relscan.h>
#include <utils/lsyscache.h>
#include <utils/builtins.h>
#include <funcapi.h>
#include "catalog.h"
@ -37,6 +38,22 @@ hyperspace_get_dimension_by_id(Hyperspace *hs, int32 id)
sizeof(Dimension), cmp_dimension_id);
}
Dimension *
hyperspace_get_dimension_by_name(Hyperspace *hs, DimensionType type, const char *name)
{
int i;
for (i = 0; i < hs->num_dimensions; i++)
{
Dimension *dim = &hs->dimensions[i];
if (dim->type == type && namestrcmp(&dim->fd.column_name, name) == 0)
return dim;
}
return NULL;
}
Dimension *
hyperspace_get_dimension(Hyperspace *hs, DimensionType type, Index n)
{
@ -95,8 +112,7 @@ dimension_fill_in_from_tuple(Dimension *d, TupleInfo *ti, Oid main_table_relid)
DatumGetName(values[Anum_dimension_partitioning_func - 1]),
NAMEDATALEN);
d->partitioning = partitioning_info_create(d->fd.num_slices,
NameStr(d->fd.partitioning_func_schema),
d->partitioning = partitioning_info_create(NameStr(d->fd.partitioning_func_schema),
NameStr(d->fd.partitioning_func),
NameStr(d->fd.column_name),
main_table_relid);

View File

@ -67,6 +67,7 @@ extern DimensionSlice *dimension_calculate_default_slice(Dimension *dim, int64 v
extern Point *hyperspace_calculate_point(Hyperspace *h, HeapTuple tuple, TupleDesc tupdesc);
extern Dimension *hyperspace_get_dimension_by_id(Hyperspace *hs, int32 id);
extern Dimension *hyperspace_get_dimension(Hyperspace *hs, DimensionType type, Index n);
extern Dimension *hyperspace_get_dimension_by_name(Hyperspace *hs, DimensionType type, const char *name);
#define hyperspace_get_open_dimension(space, i) \
hyperspace_get_dimension(space, DIMENSION_TYPE_OPEN, i)

View File

@ -1,83 +1,157 @@
#include <postgres.h>
#include <utils/builtins.h>
#include <utils/lsyscache.h>
#include <utils/numeric.h>
#include <utils/timestamp.h>
#include <utils/inet.h>
#include <utils/cash.h>
#include <utils/date.h>
#include <utils/nabstime.h>
#include <utils/jsonb.h>
#include <utils/acl.h>
#include <utils/rangetypes.h>
#include <catalog/namespace.h>
#include <catalog/pg_type.h>
#include <access/hash.h>
#include <access/htup_details.h>
#include <parser/parse_coerce.h>
#include <nodes/makefuncs.h>
#include <nodes/pg_list.h>
#include "partitioning.h"
#include "catalog.h"
#include "utils.h"
/*
* Resolve the partitioning function set for a hypertable.
*/
static void
partitioning_func_set_func_fmgr(PartitioningFunc *pf)
{
FuncCandidateList funclist =
FuncnameGetCandidates(list_make2(makeString(pf->schema), makeString(pf->name)),
FuncnameGetCandidates(partitioning_func_qualified_name(pf),
1, NULL, false, false, false);
if (funclist == NULL || funclist->next)
elog(ERROR, "Could not resolve the partitioning function");
pf->paramtype = funclist->args[0];
if (!(funclist->nargs == 1 &&
(pf->paramtype == TEXTOID || pf->paramtype == ANYELEMENTOID)))
elog(ERROR, "Invalid partitioning function signature");
fmgr_info_cxt(funclist->oid, &pf->func_fmgr, CurrentMemoryContext);
}
static void
partitioning_info_set_textfunc_fmgr(PartitioningInfo *pi, Oid relid)
List *
partitioning_func_qualified_name(PartitioningFunc *pf)
{
Oid type_id,
func_id;
bool isVarlena;
CoercionPathType cpt;
return list_make2(makeString(pf->schema), makeString(pf->name));
}
pi->column_attnum = get_attnum(relid, pi->column);
type_id = get_atttype(relid, pi->column_attnum);
static Oid
find_text_coercion_func(Oid type)
{
Oid funcid;
bool is_varlena;
CoercionPathType cpt;
/*
* First look for an explicit cast type. Needed since the output of for
* example character(20) not the same as character(20)::text
*/
cpt = find_coercion_pathway(TEXTOID, type_id, COERCION_EXPLICIT, &func_id);
cpt = find_coercion_pathway(TEXTOID, type, COERCION_EXPLICIT, &funcid);
if (cpt != COERCION_PATH_FUNC)
{
getTypeOutputInfo(type_id, &func_id, &isVarlena);
}
fmgr_info_cxt(func_id, &pi->partfunc.textfunc_fmgr, CurrentMemoryContext);
getTypeOutputInfo(type, &funcid, &is_varlena);
return funcid;
}
#define TYPECACHE_HASH_FLAGS (TYPECACHE_HASH_PROC | TYPECACHE_HASH_PROC_FINFO)
PartitioningInfo *
partitioning_info_create(int num_partitions,
const char *schema,
partitioning_info_create(const char *schema,
const char *partfunc,
const char *partcol,
Oid relid)
{
PartitioningInfo *pi;
PartitioningInfo *pinfo;
Oid columntype,
varcollid,
funccollid = InvalidOid;
Var *var;
FuncExpr *expr;
pi = palloc0(sizeof(PartitioningInfo));
strncpy(pi->partfunc.name, partfunc, NAMEDATALEN);
strncpy(pi->column, partcol, NAMEDATALEN);
pinfo = palloc0(sizeof(PartitioningInfo));
strncpy(pinfo->partfunc.name, partfunc, NAMEDATALEN);
strncpy(pinfo->column, partcol, NAMEDATALEN);
pinfo->column_attnum = get_attnum(relid, pinfo->column);
if (schema != NULL)
strncpy(pi->partfunc.schema, schema, NAMEDATALEN);
strncpy(pinfo->partfunc.schema, schema, NAMEDATALEN);
partitioning_func_set_func_fmgr(&pi->partfunc);
partitioning_info_set_textfunc_fmgr(pi, relid);
/* Lookup the type cache entry to access the hash function for the type */
columntype = get_atttype(relid, pinfo->column_attnum);
pinfo->typcache_entry = lookup_type_cache(columntype, TYPECACHE_HASH_FLAGS);
return pi;
if (pinfo->typcache_entry->hash_proc == InvalidOid)
elog(ERROR, "No hash function for type %u", columntype);
partitioning_func_set_func_fmgr(&pinfo->partfunc);
/*
* Prepare a function expression for this function. The partition hash
* function needs this to be able to resolve the type of the value to be
* hashed.
*/
varcollid = get_typcollation(columntype);
var = makeVar(1,
pinfo->column_attnum,
columntype,
-1,
varcollid,
0);
expr = makeFuncExpr(pinfo->partfunc.func_fmgr.fn_oid, INT4OID, list_make1(var),
funccollid, varcollid, COERCE_EXPLICIT_CALL);
fmgr_info_set_expr((Node *) expr, &pinfo->partfunc.func_fmgr);
/*
* Set the type cache entry in fn_extra to avoid an extry lookup in the
* partition hash function
*/
pinfo->partfunc.func_fmgr.fn_extra = pinfo->typcache_entry;
return pinfo;
}
/*
* Apply the partitioning function of a hypertable to a value.
*
* We support both partitioning functions with the legacy signature int
* func(text) and the new signature int func(anyelement).
*/
int32
partitioning_func_apply(PartitioningInfo *pinfo, Datum value)
{
Datum text = FunctionCall1(&pinfo->partfunc.textfunc_fmgr, value);
char *partition_val = DatumGetCString(text);
Datum keyspace_datum = FunctionCall1(&pinfo->partfunc.func_fmgr,
CStringGetTextDatum(partition_val));
if (pinfo->partfunc.paramtype == TEXTOID)
{
/* Legacy function signature. We need to convert the datum to text. */
Oid funcid = find_text_coercion_func(pinfo->typcache_entry->type_id);
return DatumGetInt32(keyspace_datum);
if (!OidIsValid(funcid))
elog(ERROR, "Could not coerce type %u to text",
pinfo->typcache_entry->type_id);
value = OidFunctionCall1(funcid, value);
value = CStringGetTextDatum(DatumGetCString(value));
}
return DatumGetInt32(FunctionCall1(&pinfo->partfunc.func_fmgr, value));
}
int32
@ -99,15 +173,18 @@ PGDLLEXPORT Datum get_partition_for_key(PG_FUNCTION_ARGS);
PG_FUNCTION_INFO_V1(get_partition_for_key);
/*
* Deprecated function to calculate partition hash values.
*
* This function assumes text input only.
*/
Datum
get_partition_for_key(PG_FUNCTION_ARGS)
{
struct varlena *data;
struct varlena *data = PG_GETARG_VARLENA_PP(0);
uint32 hash_u;
int32 res;
data = PG_GETARG_VARLENA_PP(0);
hash_u = DatumGetUInt32(hash_any((unsigned char *) VARDATA_ANY(data),
VARSIZE_ANY_EXHDR(data)));
@ -116,3 +193,85 @@ get_partition_for_key(PG_FUNCTION_ARGS)
PG_FREE_IF_COPY(data, 0);
PG_RETURN_INT32(res);
}
/*
* Resolve the type of the argument passed to a function.
*
* The type is resolved from the function expression in the function call info.
*/
static Oid
resolve_function_argtype(FunctionCallInfo fcinfo)
{
FuncExpr *fe;
Node *node;
Oid argtype;
/* Get the function expression from the call info */
fe = (FuncExpr *) fcinfo->flinfo->fn_expr;
if (NULL == fe || !IsA(fe, FuncExpr))
elog(ERROR, "No function expression set when invoking partitioning function");
if (list_length(fe->args) != 1)
elog(ERROR, "Unexpected number of arguments in function expression");
node = linitial(fe->args);
switch (nodeTag(node))
{
case T_Var:
argtype = ((Var *) node)->vartype;
break;
case T_Const:
argtype = ((Const *) node)->consttype;
break;
case T_CoerceViaIO:
argtype = ((CoerceViaIO *) node)->resulttype;
break;
default:
elog(ERROR, "Unsupported expression argument node type %u", nodeTag(node));
}
return argtype;
}
PGDLLEXPORT Datum get_partition_hash(PG_FUNCTION_ARGS);
PG_FUNCTION_INFO_V1(get_partition_hash);
/*
* Compute a partition hash value for any input type.
*
* get_partition_hash() takes a single argument of anyelement type. We compute
* the hash based on the argument type information that we expect to find in the
* function expression in the function call context. If no such expression
* exists, or the type cannot be resolved from the expression, the function
* throws an error.
*/
Datum
get_partition_hash(PG_FUNCTION_ARGS)
{
Datum arg = PG_GETARG_DATUM(0);
TypeCacheEntry *tce = fcinfo->flinfo->fn_extra;
Oid argtype;
Datum hash;
int32 res;
if (PG_NARGS() != 1)
elog(ERROR, "Unexpected number of arguments to partitioning function");
argtype = resolve_function_argtype(fcinfo);
if (tce == NULL)
tce = lookup_type_cache(argtype, TYPECACHE_HASH_FLAGS);
if (tce->hash_proc == InvalidOid)
elog(ERROR, "No hash function for type %u", argtype);
hash = FunctionCall1(&tce->hash_proc_finfo, arg);
/* Only positive numbers */
res = (int32) (DatumGetUInt32(hash) & 0x7fffffff);
PG_RETURN_INT32(res);
}

View File

@ -5,7 +5,8 @@
#include <postgres.h>
#include <access/attnum.h>
#include <access/htup.h>
#include <access/htup_details.h>
#include <utils/typcache.h>
#include <fmgr.h>
#define OPEN_START_TIME -1
@ -16,17 +17,17 @@ typedef struct PartitioningFunc
char schema[NAMEDATALEN];
char name[NAMEDATALEN];
/*
* Function manager info to call the function to convert a row's
* partitioning column value to a text string
*/
FmgrInfo textfunc_fmgr;
/*
* Function manager info to call the partitioning function on the
* partitioning column's text representation
* partitioning column's text representation.
*/
FmgrInfo func_fmgr;
/*
* The type of the parameter that the partitioning function accepts. This
* can be either TEXTOID or ANYELEMENTOID.
*/
Oid paramtype;
} PartitioningFunc;
@ -34,16 +35,17 @@ typedef struct PartitioningInfo
{
char column[NAMEDATALEN];
AttrNumber column_attnum;
TypeCacheEntry *typcache_entry;
PartitioningFunc partfunc;
} PartitioningInfo;
extern PartitioningInfo *partitioning_info_create(int num_partitions,
const char *schema,
extern PartitioningInfo *partitioning_info_create(const char *schema,
const char *partfunc,
const char *partcol,
Oid relid);
extern List *partitioning_func_qualified_name(PartitioningFunc *pf);
extern int32 partitioning_func_apply(PartitioningInfo *pinfo, Datum value);
extern int32 partitioning_func_apply_tuple(PartitioningInfo *pinfo, HeapTuple tuple, TupleDesc desc);

View File

@ -110,36 +110,37 @@ hypertable_query_walker(Node *node, void *context)
/* Returns the partitioning info for a var if the var is a partitioning
* column. If the var is not a partitioning column return NULL */
static PartitioningInfo *
static inline PartitioningInfo *
get_partitioning_info_for_partition_column_var(Var *var_expr, AddPartFuncQualCtx *context)
{
Hypertable *ht = context->hentry;
RangeTblEntry *rte = rt_fetch(var_expr->varno, context->parse->rtable);
char *varname = get_rte_attribute_name(rte, var_expr->varattno);
char *varname;
Dimension *dim;
if (rte->relid == context->hentry->main_table_relid)
{
Dimension *closed_dim = hyperspace_get_closed_dimension(context->hentry->space, 0);
if (rte->relid != ht->main_table_relid)
return NULL;
varname = get_rte_attribute_name(rte, var_expr->varattno);
dim = hyperspace_get_dimension_by_name(ht->space, DIMENSION_TYPE_CLOSED, varname);
if (dim != NULL)
return dim->partitioning;
if (closed_dim != NULL &&
strncmp(closed_dim->fd.column_name.data, varname, NAMEDATALEN) == 0)
return closed_dim->partitioning;
}
return NULL;
}
/* Creates an expression for partioning_func(var_expr, partitioning_mod) =
* partioning_func(const_expr, partitioning_mod). This function makes a copy of
* partitioning_func(const_expr, partitioning_mod). This function makes a copy of
* all nodes given in input. */
static Expr *
create_partition_func_equals_const(Var *var_expr, Const *const_expr, char *partitioning_func_schema,
char *partitioning_func)
create_partition_func_equals_const(PartitioningInfo *pi, Var *var_expr, Const *const_expr)
{
Expr *op_expr;
List *func_name = list_make2(makeString(partitioning_func_schema), makeString(partitioning_func));
Var *var_for_fn_call;
Node *var_node_for_fn_call;
Const *const_for_fn_call;
Node *const_node_for_fn_call;
List *func_name = partitioning_func_qualified_name(&pi->partfunc);
Node *var_node;
Node *const_node;
List *args_func_var;
List *args_func_const;
FuncCall *fc_var;
@ -147,33 +148,35 @@ create_partition_func_equals_const(Var *var_expr, Const *const_expr, char *parti
Node *f_var;
Node *f_const;
const_for_fn_call = (Const *) palloc(sizeof(Const));
memcpy(const_for_fn_call, const_expr, sizeof(Const));
var_for_fn_call = (Var *) palloc(sizeof(Var));
memcpy(var_for_fn_call, var_expr, sizeof(Var));
if (var_for_fn_call->vartype == TEXTOID)
if (pi->partfunc.paramtype == TEXTOID)
{
var_node_for_fn_call = (Node *) var_for_fn_call;
const_node_for_fn_call = (Node *) const_for_fn_call;
/* Path for deprecated partitioning function taking text input */
if (var_expr->vartype == TEXTOID)
{
var_node = copyObject(var_expr);
const_node = copyObject(const_expr);
}
else
{
var_node_for_fn_call =
coerce_to_target_type(NULL, (Node *) var_for_fn_call,
var_for_fn_call->vartype,
var_node = coerce_to_target_type(NULL, (Node *) var_expr,
var_expr->vartype,
TEXTOID, -1, COERCION_EXPLICIT,
COERCE_EXPLICIT_CAST, -1);
const_node_for_fn_call =
coerce_to_target_type(NULL, (Node *) const_for_fn_call,
const_for_fn_call->consttype,
const_node = coerce_to_target_type(NULL, (Node *) const_expr,
const_expr->consttype,
TEXTOID, -1, COERCION_EXPLICIT,
COERCE_EXPLICIT_CAST, -1);
}
}
else
{
/* Path for partitioning func taking anyelement */
var_node = copyObject(var_expr);
const_node = copyObject(const_expr);
}
args_func_var = list_make1(var_node_for_fn_call);
args_func_const = list_make1(const_node_for_fn_call);
args_func_var = list_make1(var_node);
args_func_const = list_make1(const_node);
fc_var = makeFuncCall(func_name, args_func_var, -1);
fc_const = makeFuncCall(func_name, args_func_const, -1);
@ -248,8 +251,8 @@ add_partitioning_func_qual_mutator(Node *node, AddPartFuncQualCtx *context)
if (pi != NULL)
{
/* The var is a partitioning column */
Expr *partitioning_clause = create_partition_func_equals_const(var_expr, const_expr,
pi->partfunc.schema, pi->partfunc.name);
Expr *partitioning_clause =
create_partition_func_equals_const(pi, var_expr, const_expr);
return (Node *) make_andclause(list_make2(node, partitioning_clause));

View File

@ -1005,7 +1005,24 @@ typename_get_unqual_name(TypeName *tn)
}
static void
process_alter_column_type(Hypertable *ht, AlterTableCmd *cmd)
process_alter_column_type_start(Hypertable *ht, AlterTableCmd *cmd)
{
int i;
for (i = 0; i < ht->space->num_dimensions; i++)
{
Dimension *dim = &ht->space->dimensions[i];
if (IS_CLOSED_DIMENSION(dim) &&
strncmp(NameStr(dim->fd.column_name), cmd->name, NAMEDATALEN) == 0)
ereport(ERROR,
(errcode(ERRCODE_IO_OPERATION_NOT_SUPPORTED),
errmsg("Cannot change the type of a hash-partitioned column")));
}
}
static void
process_alter_column_type_end(Hypertable *ht, AlterTableCmd *cmd)
{
ColumnDef *coldef = (ColumnDef *) cmd->def;
Oid new_type = TypenameGetTypid(typename_get_unqual_name(coldef->typeName));
@ -1102,6 +1119,11 @@ process_altertable_start(Node *parsetree)
verify_constraint_plaintable(stmt->relation, (Constraint *) cmd->def);
else
verify_constraint_hypertable(ht, cmd->def);
break;
case AT_AlterColumnType:
Assert(IsA(cmd->def, ColumnDef));
process_alter_column_type_start(ht, cmd);
break;
default:
break;
}
@ -1163,7 +1185,7 @@ process_altertable_end_subcmd(Hypertable *ht, Node *parsetree, ObjectAddress *ob
break;
case AT_AlterColumnType:
Assert(IsA(cmd->def, ColumnDef));
process_alter_column_type(ht, cmd);
process_alter_column_type_end(ht, cmd);
break;
default:
break;

View File

@ -29,7 +29,7 @@ SELECT create_hypertable('chunk_test', 'time', 'tag', 2, chunk_time_interval =>
(1 row)
INSERT INTO chunk_test VALUES (4, 24.3, 3, 1);
INSERT INTO chunk_test VALUES (4, 24.3, 1, 1);
SELECT * FROM _timescaledb_catalog.dimension_slice;
id | dimension_id | range_start | range_end
----+--------------+-------------+------------
@ -37,8 +37,8 @@ SELECT * FROM _timescaledb_catalog.dimension_slice;
2 | 2 | 0 | 1073741823
(2 rows)
INSERT INTO chunk_test VALUES (4, 24.3, 1, 1);
INSERT INTO chunk_test VALUES (10, 24.3, 1, 1);
INSERT INTO chunk_test VALUES (4, 24.3, 2, 1);
INSERT INTO chunk_test VALUES (10, 24.3, 2, 1);
SELECT c.table_name AS chunk_name, d.id AS dimension_id, ds.id AS slice_id, range_start, range_end FROM _timescaledb_catalog.chunk c
LEFT JOIN _timescaledb_catalog.chunk_constraint cc ON (c.id = cc.chunk_id)
LEFT JOIN _timescaledb_catalog.dimension_slice ds ON (ds.id = cc.dimension_slice_id)
@ -65,7 +65,7 @@ SELECT set_chunk_time_interval('chunk_test', 1::bigint);
(1 row)
INSERT INTO chunk_test VALUES (8, 24.3, 79669, 1);
INSERT INTO chunk_test VALUES (8, 24.3, 11233, 1);
SELECT set_chunk_time_interval('chunk_test', 5::bigint);
set_chunk_time_interval
-------------------------
@ -74,15 +74,15 @@ SELECT set_chunk_time_interval('chunk_test', 5::bigint);
SELECT * FROM _timescaledb_catalog.dimension;
id | hypertable_id | column_name | column_type | aligned | num_slices | partitioning_func_schema | partitioning_func | interval_length
----+---------------+-------------+-------------+---------+------------+--------------------------+-----------------------+-----------------
2 | 1 | tag | integer | f | 3 | _timescaledb_internal | get_partition_for_key |
----+---------------+-------------+-------------+---------+------------+--------------------------+--------------------+-----------------
2 | 1 | tag | integer | f | 3 | _timescaledb_internal | get_partition_hash |
1 | 1 | time | integer | t | | | | 5
(2 rows)
INSERT INTO chunk_test VALUES (7, 24.3, 11233, 1);
INSERT INTO chunk_test VALUES (8, 24.3, 11233, 1);
INSERT INTO chunk_test VALUES (10, 24.3, 79669, 1);
INSERT INTO chunk_test VALUES (16, 24.3, 79669, 1);
INSERT INTO chunk_test VALUES (7, 24.3, 79669, 1);
INSERT INTO chunk_test VALUES (8, 24.3, 79669, 1);
INSERT INTO chunk_test VALUES (10, 24.3, 11233, 1);
INSERT INTO chunk_test VALUES (16, 24.3, 11233, 1);
SELECT c.table_name AS chunk_name, d.id AS dimension_id, ds.id AS slice_id, range_start, range_end FROM _timescaledb_catalog.chunk c
LEFT JOIN _timescaledb_catalog.chunk_constraint cc ON (c.id = cc.chunk_id)
LEFT JOIN _timescaledb_catalog.dimension_slice ds ON (ds.id = cc.dimension_slice_id)

View File

@ -41,10 +41,10 @@ select * from _timescaledb_catalog.hypertable where table_name = 'test_table';
select * from _timescaledb_catalog.dimension;
id | hypertable_id | column_name | column_type | aligned | num_slices | partitioning_func_schema | partitioning_func | interval_length
----+---------------+-------------+-------------+---------+------------+--------------------------+-----------------------+-----------------
----+---------------+-------------+-------------+---------+------------+--------------------------+--------------------+-----------------
1 | 1 | time | bigint | t | | | | 2592000000000
2 | 1 | device_id | text | f | 2 | _timescaledb_internal | get_partition_for_key |
3 | 1 | location | text | f | 2 | _timescaledb_internal | get_partition_for_key |
2 | 1 | device_id | text | f | 2 | _timescaledb_internal | get_partition_hash |
3 | 1 | location | text | f | 2 | _timescaledb_internal | get_partition_hash |
(3 rows)
\set ON_ERROR_STOP 0
@ -67,10 +67,10 @@ select * from _timescaledb_catalog.hypertable where table_name = 'test_table';
select * from _timescaledb_catalog.dimension;
id | hypertable_id | column_name | column_type | aligned | num_slices | partitioning_func_schema | partitioning_func | interval_length
----+---------------+-------------+-------------+---------+------------+--------------------------+-----------------------+-----------------
----+---------------+-------------+-------------+---------+------------+--------------------------+--------------------+-----------------
1 | 1 | time | bigint | t | | | | 2592000000000
2 | 1 | device_id | text | f | 2 | _timescaledb_internal | get_partition_for_key |
3 | 1 | location | text | f | 2 | _timescaledb_internal | get_partition_for_key |
2 | 1 | device_id | text | f | 2 | _timescaledb_internal | get_partition_hash |
3 | 1 | location | text | f | 2 | _timescaledb_internal | get_partition_hash |
4 | 1 | id | integer | t | | | | 1000
(4 rows)

View File

@ -351,7 +351,7 @@ Indexes:
"_hyper_1_1_chunk_ind_sensor_1" btree ("time", sensor_1)
Check constraints:
"constraint_1" CHECK ("time" >= '1257892416000000000'::bigint AND "time" < '1257895008000000000'::bigint)
"constraint_2" CHECK (_timescaledb_internal.get_partition_for_key("Device_id") >= 0 AND _timescaledb_internal.get_partition_for_key("Device_id") < 2147483647)
"constraint_2" CHECK (_timescaledb_internal.get_partition_hash("Device_id") >= 0 AND _timescaledb_internal.get_partition_hash("Device_id") < 2147483647)
Inherits: "Hypertable_1"
\ir include/ddl_ops_2.sql

View File

@ -36,7 +36,7 @@ Indexes:
"_hyper_1_1_chunk_alter_test_time_idx" btree ("time" DESC)
Check constraints:
"constraint_1" CHECK ("time" >= 'Thu Jan 19 02:00:00 2017 PST'::timestamp with time zone AND "time" < 'Sat Feb 18 12:00:00 2017 PST'::timestamp with time zone)
"constraint_2" CHECK (_timescaledb_internal.get_partition_for_key(color::text) >= 0 AND _timescaledb_internal.get_partition_for_key(color::text) < 1073741823)
"constraint_2" CHECK (_timescaledb_internal.get_partition_hash(color) >= 0 AND _timescaledb_internal.get_partition_hash(color) < 1073741823)
Inherits: alter_test
Index "_timescaledb_internal._hyper_1_1_chunk_alter_test_color_time_idx"
@ -63,7 +63,7 @@ Indexes:
"_hyper_1_2_chunk_alter_test_time_idx" btree ("time" DESC)
Check constraints:
"constraint_3" CHECK ("time" >= 'Thu Apr 20 09:00:00 2017 PDT'::timestamp with time zone AND "time" < 'Sat May 20 19:00:00 2017 PDT'::timestamp with time zone)
"constraint_4" CHECK (_timescaledb_internal.get_partition_for_key(color::text) >= 1073741823 AND _timescaledb_internal.get_partition_for_key(color::text) < 2147483647)
"constraint_4" CHECK (_timescaledb_internal.get_partition_hash(color) >= 1073741823 AND _timescaledb_internal.get_partition_hash(color) < 2147483647)
Inherits: alter_test
Index "_timescaledb_internal._hyper_1_2_chunk_alter_test_color_time_idx"
@ -89,7 +89,7 @@ Indexes:
"_hyper_1_3_chunk_alter_test_color_time_idx" btree (color, "time" DESC)
"_hyper_1_3_chunk_alter_test_time_idx" btree ("time" DESC)
Check constraints:
"constraint_2" CHECK (_timescaledb_internal.get_partition_for_key(color::text) >= 0 AND _timescaledb_internal.get_partition_for_key(color::text) < 1073741823)
"constraint_2" CHECK (_timescaledb_internal.get_partition_hash(color) >= 0 AND _timescaledb_internal.get_partition_hash(color) < 1073741823)
"constraint_3" CHECK ("time" >= 'Thu Apr 20 09:00:00 2017 PDT'::timestamp with time zone AND "time" < 'Sat May 20 19:00:00 2017 PDT'::timestamp with time zone)
Inherits: alter_test
@ -110,9 +110,9 @@ btree, for table "_timescaledb_internal._hyper_1_3_chunk"
-- metadata table
SELECT * FROM _timescaledb_catalog.dimension;
id | hypertable_id | column_name | column_type | aligned | num_slices | partitioning_func_schema | partitioning_func | interval_length
----+---------------+-------------+--------------------------+---------+------------+--------------------------+-----------------------+-----------------
----+---------------+-------------+--------------------------+---------+------------+--------------------------+--------------------+-----------------
1 | 1 | time | timestamp with time zone | t | | | | 2628000000000
2 | 1 | color | character varying | f | 2 | _timescaledb_internal | get_partition_for_key |
2 | 1 | color | character varying | f | 2 | _timescaledb_internal | get_partition_hash |
(2 rows)
EXPLAIN (costs off)
@ -136,14 +136,19 @@ SELECT * FROM alter_test WHERE time > '2017-05-20T10:00:01';
ALTER TABLE alter_test RENAME COLUMN time TO time_us;
ALTER TABLE alter_test ALTER COLUMN time_us TYPE timestamp;
ALTER TABLE alter_test RENAME COLUMN color TO colorname;
\set ON_ERROR_STOP 0
-- Changing types on hash-partitioned columns is not safe for some
-- types and is therefore blocked.
ALTER TABLE alter_test ALTER COLUMN colorname TYPE text;
ERROR: Cannot change the type of a hash-partitioned column
\set ON_ERROR_STOP 1
\d+ alter_test
Table "public.alter_test"
Column | Type | Modifiers | Storage | Stats target | Description
-----------+-----------------------------+-----------+----------+--------------+-------------
time_us | timestamp without time zone | | plain | |
temp | double precision | | plain | |
colorname | text | | extended | |
colorname | character varying(10) | | extended | |
Indexes:
"alter_test_color_time_idx" btree (colorname, time_us DESC)
"alter_test_time_idx" btree (time_us DESC)
@ -157,19 +162,19 @@ Child tables: _timescaledb_internal._hyper_1_1_chunk,
-----------+-----------------------------+-----------+----------+--------------+-------------
time_us | timestamp without time zone | | plain | |
temp | double precision | | plain | |
colorname | text | | extended | |
colorname | character varying(10) | | extended | |
Indexes:
"_hyper_1_1_chunk_alter_test_color_time_idx" btree (colorname, time_us DESC)
"_hyper_1_1_chunk_alter_test_time_idx" btree (time_us DESC)
Check constraints:
"constraint_1" CHECK (time_us >= 'Thu Jan 19 02:00:00 2017'::timestamp without time zone AND time_us < 'Sat Feb 18 12:00:00 2017'::timestamp without time zone)
"constraint_2" CHECK (_timescaledb_internal.get_partition_for_key(colorname) >= 0 AND _timescaledb_internal.get_partition_for_key(colorname) < 1073741823)
"constraint_2" CHECK (_timescaledb_internal.get_partition_hash(colorname) >= 0 AND _timescaledb_internal.get_partition_hash(colorname) < 1073741823)
Inherits: alter_test
Index "_timescaledb_internal._hyper_1_1_chunk_alter_test_color_time_idx"
Column | Type | Definition | Storage
-----------+-----------------------------+------------+----------
colorname | text | colorname | extended
---------+-----------------------------+------------+----------
color | character varying(10) | colorname | extended
time_us | timestamp without time zone | time_us | plain
btree, for table "_timescaledb_internal._hyper_1_1_chunk"
@ -184,19 +189,19 @@ btree, for table "_timescaledb_internal._hyper_1_1_chunk"
-----------+-----------------------------+-----------+----------+--------------+-------------
time_us | timestamp without time zone | | plain | |
temp | double precision | | plain | |
colorname | text | | extended | |
colorname | character varying(10) | | extended | |
Indexes:
"_hyper_1_2_chunk_alter_test_color_time_idx" btree (colorname, time_us DESC)
"_hyper_1_2_chunk_alter_test_time_idx" btree (time_us DESC)
Check constraints:
"constraint_3" CHECK (time_us >= 'Thu Apr 20 09:00:00 2017'::timestamp without time zone AND time_us < 'Sat May 20 19:00:00 2017'::timestamp without time zone)
"constraint_4" CHECK (_timescaledb_internal.get_partition_for_key(colorname) >= 1073741823 AND _timescaledb_internal.get_partition_for_key(colorname) < 2147483647)
"constraint_4" CHECK (_timescaledb_internal.get_partition_hash(colorname) >= 1073741823 AND _timescaledb_internal.get_partition_hash(colorname) < 2147483647)
Inherits: alter_test
Index "_timescaledb_internal._hyper_1_2_chunk_alter_test_color_time_idx"
Column | Type | Definition | Storage
-----------+-----------------------------+------------+----------
colorname | text | colorname | extended
---------+-----------------------------+------------+----------
color | character varying(10) | colorname | extended
time_us | timestamp without time zone | time_us | plain
btree, for table "_timescaledb_internal._hyper_1_2_chunk"
@ -211,19 +216,19 @@ btree, for table "_timescaledb_internal._hyper_1_2_chunk"
-----------+-----------------------------+-----------+----------+--------------+-------------
time_us | timestamp without time zone | | plain | |
temp | double precision | | plain | |
colorname | text | | extended | |
colorname | character varying(10) | | extended | |
Indexes:
"_hyper_1_3_chunk_alter_test_color_time_idx" btree (colorname, time_us DESC)
"_hyper_1_3_chunk_alter_test_time_idx" btree (time_us DESC)
Check constraints:
"constraint_2" CHECK (_timescaledb_internal.get_partition_for_key(colorname) >= 0 AND _timescaledb_internal.get_partition_for_key(colorname) < 1073741823)
"constraint_2" CHECK (_timescaledb_internal.get_partition_hash(colorname) >= 0 AND _timescaledb_internal.get_partition_hash(colorname) < 1073741823)
"constraint_3" CHECK (time_us >= 'Thu Apr 20 09:00:00 2017'::timestamp without time zone AND time_us < 'Sat May 20 19:00:00 2017'::timestamp without time zone)
Inherits: alter_test
Index "_timescaledb_internal._hyper_1_3_chunk_alter_test_color_time_idx"
Column | Type | Definition | Storage
-----------+-----------------------------+------------+----------
colorname | text | colorname | extended
---------+-----------------------------+------------+----------
color | character varying(10) | colorname | extended
time_us | timestamp without time zone | time_us | plain
btree, for table "_timescaledb_internal._hyper_1_3_chunk"
@ -236,9 +241,9 @@ btree, for table "_timescaledb_internal._hyper_1_3_chunk"
-- show that the metadata has been updated
SELECT * FROM _timescaledb_catalog.dimension;
id | hypertable_id | column_name | column_type | aligned | num_slices | partitioning_func_schema | partitioning_func | interval_length
----+---------------+-------------+-----------------------------+---------+------------+--------------------------+-----------------------+-----------------
----+---------------+-------------+-----------------------------+---------+------------+--------------------------+--------------------+-----------------
1 | 1 | time_us | timestamp without time zone | t | | | | 2628000000000
2 | 1 | colorname | text | f | 2 | _timescaledb_internal | get_partition_for_key |
2 | 1 | colorname | character varying | f | 2 | _timescaledb_internal | get_partition_hash |
(2 rows)
-- constraint exclusion should still work with updated column
@ -258,7 +263,7 @@ SELECT * FROM alter_test WHERE time_us > '2017-05-20T10:00:01';
\set ON_ERROR_STOP 0
-- verify that we cannot change the column type to something incompatible
ALTER TABLE alter_test ALTER COLUMN colorname TYPE varchar(3);
ERROR: value too long for type character varying(3)
ERROR: Cannot change the type of a hash-partitioned column
-- conversion that messes up partitioning fails
ALTER TABLE alter_test ALTER COLUMN time_us TYPE timestamptz USING time_us::timestamptz+INTERVAL '1 year';
ERROR: check constraint "constraint_1" is violated by some row

View File

@ -381,7 +381,7 @@ Indexes:
"_hyper_1_1_chunk_ind_humdity2" btree ("time", humidity)
Check constraints:
"constraint_1" CHECK ("time" >= '1257892416000000000'::bigint AND "time" < '1257895008000000000'::bigint)
"constraint_2" CHECK (_timescaledb_internal.get_partition_for_key("Device_id") >= 0 AND _timescaledb_internal.get_partition_for_key("Device_id") < 2147483647)
"constraint_2" CHECK (_timescaledb_internal.get_partition_hash("Device_id") >= 0 AND _timescaledb_internal.get_partition_hash("Device_id") < 2147483647)
Inherits: "Hypertable_1"
SELECT * FROM PUBLIC."Hypertable_1";

View File

@ -49,7 +49,7 @@ Indexes:
"_hyper_1_1_chunk_two_Partitions_timeCustom_series_bool_idx" btree ("timeCustom" DESC NULLS LAST, series_bool) WHERE series_bool IS NOT NULL
Check constraints:
"constraint_1" CHECK ("timeCustom" >= '1257892416000000000'::bigint AND "timeCustom" < '1257895008000000000'::bigint)
"constraint_2" CHECK (_timescaledb_internal.get_partition_for_key(device_id) >= 1073741823 AND _timescaledb_internal.get_partition_for_key(device_id) < 2147483647)
"constraint_2" CHECK (_timescaledb_internal.get_partition_hash(device_id) >= 1073741823 AND _timescaledb_internal.get_partition_hash(device_id) < 2147483647)
Inherits: "two_Partitions"
Index "_timescaledb_internal._hyper_1_1_chunk_two_Partitions_device_id_timeCustom_idx"
@ -118,7 +118,7 @@ Indexes:
"_hyper_1_2_chunk_two_Partitions_timeCustom_series_2_idx" btree ("timeCustom" DESC NULLS LAST, series_2) WHERE series_2 IS NOT NULL
"_hyper_1_2_chunk_two_Partitions_timeCustom_series_bool_idx" btree ("timeCustom" DESC NULLS LAST, series_bool) WHERE series_bool IS NOT NULL
Check constraints:
"constraint_2" CHECK (_timescaledb_internal.get_partition_for_key(device_id) >= 1073741823 AND _timescaledb_internal.get_partition_for_key(device_id) < 2147483647)
"constraint_2" CHECK (_timescaledb_internal.get_partition_hash(device_id) >= 1073741823 AND _timescaledb_internal.get_partition_hash(device_id) < 2147483647)
"constraint_3" CHECK ("timeCustom" >= '1257897600000000000'::bigint AND "timeCustom" < '1257900192000000000'::bigint)
Inherits: "two_Partitions"
@ -188,7 +188,7 @@ Indexes:
"_hyper_1_3_chunk_two_Partitions_timeCustom_series_2_idx" btree ("timeCustom" DESC NULLS LAST, series_2) WHERE series_2 IS NOT NULL
"_hyper_1_3_chunk_two_Partitions_timeCustom_series_bool_idx" btree ("timeCustom" DESC NULLS LAST, series_bool) WHERE series_bool IS NOT NULL
Check constraints:
"constraint_2" CHECK (_timescaledb_internal.get_partition_for_key(device_id) >= 1073741823 AND _timescaledb_internal.get_partition_for_key(device_id) < 2147483647)
"constraint_2" CHECK (_timescaledb_internal.get_partition_hash(device_id) >= 1073741823 AND _timescaledb_internal.get_partition_hash(device_id) < 2147483647)
"constraint_4" CHECK ("timeCustom" >= '1257985728000000000'::bigint AND "timeCustom" < '1257988320000000000'::bigint)
Inherits: "two_Partitions"
@ -259,7 +259,7 @@ Indexes:
"_hyper_1_4_chunk_two_Partitions_timeCustom_series_bool_idx" btree ("timeCustom" DESC NULLS LAST, series_bool) WHERE series_bool IS NOT NULL
Check constraints:
"constraint_1" CHECK ("timeCustom" >= '1257892416000000000'::bigint AND "timeCustom" < '1257895008000000000'::bigint)
"constraint_5" CHECK (_timescaledb_internal.get_partition_for_key(device_id) >= 0 AND _timescaledb_internal.get_partition_for_key(device_id) < 1073741823)
"constraint_5" CHECK (_timescaledb_internal.get_partition_hash(device_id) >= 0 AND _timescaledb_internal.get_partition_hash(device_id) < 1073741823)
Inherits: "two_Partitions"
Index "_timescaledb_internal._hyper_1_4_chunk_two_Partitions_device_id_timeCustom_idx"
@ -331,7 +331,7 @@ Indexes:
"_hyper_1_1_chunk_two_Partitions_timeCustom_series_bool_idx" btree ("timeCustom" DESC NULLS LAST, series_bool) WHERE series_bool IS NOT NULL
Check constraints:
"constraint_1" CHECK ("timeCustom" >= '1257892416000000000'::bigint AND "timeCustom" < '1257895008000000000'::bigint)
"constraint_2" CHECK (_timescaledb_internal.get_partition_for_key(device_id) >= 1073741823 AND _timescaledb_internal.get_partition_for_key(device_id) < 2147483647)
"constraint_2" CHECK (_timescaledb_internal.get_partition_hash(device_id) >= 1073741823 AND _timescaledb_internal.get_partition_hash(device_id) < 2147483647)
Inherits: "two_Partitions"
ALTER TABLE "two_Partitions" RENAME TO "newname";

View File

@ -177,11 +177,11 @@ SELECT *,
) sub1
) sub2;
chunk_id | chunk_table | partitioning_columns | partitioning_column_types | partitioning_hash_functions | ranges | table_bytes | index_bytes | toast_bytes | total_bytes
----------+--------------------------------------------+------------------------+---------------------------+----------------------------------------------------+-----------------------------------------------------------------------------+-------------+-------------+-------------+-------------
1 | "_timescaledb_internal"."_hyper_1_1_chunk" | {timeCustom,device_id} | {bigint,text} | {NULL,_timescaledb_internal.get_partition_for_key} | {"['1257892416000000000','1257895008000000000')","[1073741823,2147483647)"} | 8192 | 114688 | 8192 | 131072
2 | "_timescaledb_internal"."_hyper_1_2_chunk" | {timeCustom,device_id} | {bigint,text} | {NULL,_timescaledb_internal.get_partition_for_key} | {"['1257897600000000000','1257900192000000000')","[1073741823,2147483647)"} | 8192 | 106496 | 8192 | 122880
3 | "_timescaledb_internal"."_hyper_1_3_chunk" | {timeCustom,device_id} | {bigint,text} | {NULL,_timescaledb_internal.get_partition_for_key} | {"['1257985728000000000','1257988320000000000')","[1073741823,2147483647)"} | 8192 | 98304 | 8192 | 114688
4 | "_timescaledb_internal"."_hyper_1_4_chunk" | {timeCustom,device_id} | {bigint,text} | {NULL,_timescaledb_internal.get_partition_for_key} | {"['1257892416000000000','1257895008000000000')","[0,1073741823)"} | 8192 | 98304 | 8192 | 114688
----------+--------------------------------------------+------------------------+---------------------------+-------------------------------------------------+-----------------------------------------------------------------------------+-------------+-------------+-------------+-------------
1 | "_timescaledb_internal"."_hyper_1_1_chunk" | {timeCustom,device_id} | {bigint,text} | {NULL,_timescaledb_internal.get_partition_hash} | {"['1257892416000000000','1257895008000000000')","[1073741823,2147483647)"} | 8192 | 114688 | 8192 | 131072
2 | "_timescaledb_internal"."_hyper_1_2_chunk" | {timeCustom,device_id} | {bigint,text} | {NULL,_timescaledb_internal.get_partition_hash} | {"['1257897600000000000','1257900192000000000')","[1073741823,2147483647)"} | 8192 | 106496 | 8192 | 122880
3 | "_timescaledb_internal"."_hyper_1_3_chunk" | {timeCustom,device_id} | {bigint,text} | {NULL,_timescaledb_internal.get_partition_hash} | {"['1257985728000000000','1257988320000000000')","[1073741823,2147483647)"} | 8192 | 98304 | 8192 | 114688
4 | "_timescaledb_internal"."_hyper_1_4_chunk" | {timeCustom,device_id} | {bigint,text} | {NULL,_timescaledb_internal.get_partition_hash} | {"['1257892416000000000','1257895008000000000')","[0,1073741823)"} | 8192 | 98304 | 8192 | 114688
(4 rows)
\echo 'Hypertable index sizes'

252
test/expected/hash.out Normal file
View File

@ -0,0 +1,252 @@
-- Test hashing Const values. We should expect the same hash value for
-- all integer types when values are compatible
SELECT _timescaledb_internal.get_partition_hash(1::int);
get_partition_hash
--------------------
242423622
(1 row)
SELECT _timescaledb_internal.get_partition_hash(1::bigint);
get_partition_hash
--------------------
242423622
(1 row)
SELECT _timescaledb_internal.get_partition_hash(1::smallint);
get_partition_hash
--------------------
242423622
(1 row)
SELECT _timescaledb_internal.get_partition_hash(true);
get_partition_hash
--------------------
242423622
(1 row)
-- Floating point types should also hash the same for compatible values
SELECT _timescaledb_internal.get_partition_hash(1.0::real);
get_partition_hash
--------------------
376496956
(1 row)
SELECT _timescaledb_internal.get_partition_hash(1.0::double precision);
get_partition_hash
--------------------
376496956
(1 row)
-- Float aliases
SELECT _timescaledb_internal.get_partition_hash(1.0::float);
get_partition_hash
--------------------
376496956
(1 row)
SELECT _timescaledb_internal.get_partition_hash(1.0::float4);
get_partition_hash
--------------------
376496956
(1 row)
SELECT _timescaledb_internal.get_partition_hash(1.0::float8);
get_partition_hash
--------------------
376496956
(1 row)
SELECT _timescaledb_internal.get_partition_hash(1.0::numeric);
get_partition_hash
--------------------
1324868424
(1 row)
-- 'name' and '"char"' are internal PostgreSQL types, which are not
-- intended for use by the general user. They are included here only
-- for completeness
-- https://www.postgresql.org/docs/10/static/datatype-character.html#datatype-character-special-table
SELECT _timescaledb_internal.get_partition_hash('c'::name);
get_partition_hash
--------------------
1903644986
(1 row)
SELECT _timescaledb_internal.get_partition_hash('c'::"char");
get_partition_hash
--------------------
203891234
(1 row)
-- String and character hashes should also have the same output for
-- compatible values
SELECT _timescaledb_internal.get_partition_hash('c'::char);
get_partition_hash
--------------------
1903644986
(1 row)
SELECT _timescaledb_internal.get_partition_hash('c'::varchar(2));
get_partition_hash
--------------------
1903644986
(1 row)
SELECT _timescaledb_internal.get_partition_hash('c'::text);
get_partition_hash
--------------------
1903644986
(1 row)
-- 'c' is 0x63 in ASCII
SELECT _timescaledb_internal.get_partition_hash(E'\\x63'::bytea);
get_partition_hash
--------------------
1903644986
(1 row)
-- Time and date types
SELECT _timescaledb_internal.get_partition_hash(interval '1 day');
get_partition_hash
--------------------
93502988
(1 row)
SELECT _timescaledb_internal.get_partition_hash('2017-03-22T09:18:23'::timestamp);
get_partition_hash
--------------------
307315039
(1 row)
SELECT _timescaledb_internal.get_partition_hash('2017-03-22T09:18:23'::timestamptz);
get_partition_hash
--------------------
1195163597
(1 row)
SELECT _timescaledb_internal.get_partition_hash('2017-03-22'::date);
get_partition_hash
--------------------
693590295
(1 row)
SELECT _timescaledb_internal.get_partition_hash('10:00:00'::time);
get_partition_hash
--------------------
1380652790
(1 row)
SELECT _timescaledb_internal.get_partition_hash('10:00:00-1'::timetz);
get_partition_hash
--------------------
769387140
(1 row)
-- Other types
SELECT _timescaledb_internal.get_partition_hash(ARRAY[1,2,3]);
get_partition_hash
--------------------
1822090118
(1 row)
SELECT _timescaledb_internal.get_partition_hash('08002b:010203'::macaddr);
get_partition_hash
--------------------
294987870
(1 row)
SELECT _timescaledb_internal.get_partition_hash('192.168.100.128/25'::cidr);
get_partition_hash
--------------------
1612896565
(1 row)
SELECT _timescaledb_internal.get_partition_hash('192.168.100.128'::inet);
get_partition_hash
--------------------
1952516432
(1 row)
SELECT _timescaledb_internal.get_partition_hash('2001:4f8:3:ba:2e0:81ff:fe22:d1f1'::inet);
get_partition_hash
--------------------
933321588
(1 row)
SELECT _timescaledb_internal.get_partition_hash('2001:4f8:3:ba:2e0:81ff:fe22:d1f1/128'::cidr);
get_partition_hash
--------------------
933321588
(1 row)
SELECT _timescaledb_internal.get_partition_hash('{ "foo": "bar" }'::jsonb);
get_partition_hash
--------------------
208840587
(1 row)
SELECT _timescaledb_internal.get_partition_hash('4b6a5eec-b344-11e7-abc4-cec278b6b50a'::uuid);
get_partition_hash
--------------------
504202548
(1 row)
SELECT _timescaledb_internal.get_partition_hash(1::regclass);
get_partition_hash
--------------------
242423622
(1 row)
SELECT _timescaledb_internal.get_partition_hash(int4range(10, 20));
get_partition_hash
--------------------
1202375768
(1 row)
SELECT _timescaledb_internal.get_partition_hash(int8range(10, 20));
get_partition_hash
--------------------
1202375768
(1 row)
SELECT _timescaledb_internal.get_partition_hash(numrange(10, 20));
get_partition_hash
--------------------
1083987536
(1 row)
SELECT _timescaledb_internal.get_partition_hash(tsrange('2017-03-22T09:18:23', '2017-03-23T09:18:23'));
get_partition_hash
--------------------
2079608838
(1 row)
SELECT _timescaledb_internal.get_partition_hash(tstzrange('2017-03-22T09:18:23+01', '2017-03-23T09:18:23+00'));
get_partition_hash
--------------------
1255083771
(1 row)
-- Test hashing Var values
CREATE TABLE hash_test(id int, value text);
INSERT INTO hash_test VALUES (1, 'test');
-- Test Vars
SELECT _timescaledb_internal.get_partition_hash(id) FROM hash_test;
get_partition_hash
--------------------
242423622
(1 row)
SELECT _timescaledb_internal.get_partition_hash(value) FROM hash_test;
get_partition_hash
--------------------
1771415073
(1 row)
-- Test coerced value
SELECT _timescaledb_internal.get_partition_hash(id::text) FROM hash_test;
get_partition_hash
--------------------
1516350201
(1 row)

View File

@ -200,7 +200,7 @@ Indexes:
"_hyper_4_3_chunk_time_temp_idx" btree ("time", temp)
Check constraints:
"constraint_3" CHECK ("time" >= 'Sat Dec 24 16:00:00 2016 PST'::timestamp with time zone AND "time" < 'Mon Jan 23 16:00:00 2017 PST'::timestamp with time zone)
"constraint_4" CHECK (_timescaledb_internal.get_partition_for_key(device::text) >= 1073741823 AND _timescaledb_internal.get_partition_for_key(device::text) < 2147483647)
"constraint_4" CHECK (_timescaledb_internal.get_partition_hash(device) >= 0 AND _timescaledb_internal.get_partition_hash(device) < 1073741823)
Inherits: index_test
Table "_timescaledb_internal._hyper_4_4_chunk"
@ -215,7 +215,7 @@ Indexes:
"_hyper_4_4_chunk_index_test_time_idx" btree ("time" DESC)
"_hyper_4_4_chunk_index_test_time_temp_idx" btree ("time", temp)
Check constraints:
"constraint_4" CHECK (_timescaledb_internal.get_partition_for_key(device::text) >= 1073741823 AND _timescaledb_internal.get_partition_for_key(device::text) < 2147483647)
"constraint_4" CHECK (_timescaledb_internal.get_partition_hash(device) >= 0 AND _timescaledb_internal.get_partition_hash(device) < 1073741823)
"constraint_5" CHECK ("time" >= 'Fri Mar 24 17:00:00 2017 PDT'::timestamp with time zone AND "time" < 'Sun Apr 23 17:00:00 2017 PDT'::timestamp with time zone)
Inherits: index_test
@ -263,7 +263,7 @@ Indexes:
"_hyper_4_3_chunk_time_temp_idx" btree ("time", temp)
Check constraints:
"constraint_3" CHECK ("time" >= 'Sat Dec 24 16:00:00 2016 PST'::timestamp with time zone AND "time" < 'Mon Jan 23 16:00:00 2017 PST'::timestamp with time zone)
"constraint_4" CHECK (_timescaledb_internal.get_partition_for_key(device::text) >= 1073741823 AND _timescaledb_internal.get_partition_for_key(device::text) < 2147483647)
"constraint_4" CHECK (_timescaledb_internal.get_partition_hash(device) >= 0 AND _timescaledb_internal.get_partition_hash(device) < 1073741823)
Inherits: index_test
Table "_timescaledb_internal._hyper_4_4_chunk"
@ -278,7 +278,7 @@ Indexes:
"_hyper_4_4_chunk_index_test_time_idx2" btree ("time" DESC)
"_hyper_4_4_chunk_index_test_time_temp_idx" btree ("time", temp)
Check constraints:
"constraint_4" CHECK (_timescaledb_internal.get_partition_for_key(device::text) >= 1073741823 AND _timescaledb_internal.get_partition_for_key(device::text) < 2147483647)
"constraint_4" CHECK (_timescaledb_internal.get_partition_hash(device) >= 0 AND _timescaledb_internal.get_partition_hash(device) < 1073741823)
"constraint_5" CHECK ("time" >= 'Fri Mar 24 17:00:00 2017 PDT'::timestamp with time zone AND "time" < 'Sun Apr 23 17:00:00 2017 PDT'::timestamp with time zone)
Inherits: index_test
@ -323,7 +323,7 @@ Indexes:
"_hyper_4_3_chunk_time_temp_idx" btree ("time", temp)
Check constraints:
"constraint_3" CHECK ("time" >= 'Sat Dec 24 16:00:00 2016 PST'::timestamp with time zone AND "time" < 'Mon Jan 23 16:00:00 2017 PST'::timestamp with time zone)
"constraint_4" CHECK (_timescaledb_internal.get_partition_for_key(device::text) >= 1073741823 AND _timescaledb_internal.get_partition_for_key(device::text) < 2147483647)
"constraint_4" CHECK (_timescaledb_internal.get_partition_hash(device) >= 0 AND _timescaledb_internal.get_partition_hash(device) < 1073741823)
Inherits: index_test
Table "_timescaledb_internal._hyper_4_4_chunk"
@ -336,7 +336,7 @@ Indexes:
"_hyper_4_4_chunk_index_test_device_time_idx" btree (device, "time" DESC)
"_hyper_4_4_chunk_index_test_time_temp_idx" btree ("time", temp)
Check constraints:
"constraint_4" CHECK (_timescaledb_internal.get_partition_for_key(device::text) >= 1073741823 AND _timescaledb_internal.get_partition_for_key(device::text) < 2147483647)
"constraint_4" CHECK (_timescaledb_internal.get_partition_hash(device) >= 0 AND _timescaledb_internal.get_partition_hash(device) < 1073741823)
"constraint_5" CHECK ("time" >= 'Fri Mar 24 17:00:00 2017 PDT'::timestamp with time zone AND "time" < 'Sun Apr 23 17:00:00 2017 PDT'::timestamp with time zone)
Inherits: index_test
@ -381,7 +381,7 @@ Indexes:
"_hyper_4_3_chunk_time_temp_idx" btree ("time", temp)
Check constraints:
"constraint_3" CHECK ("time" >= 'Sat Dec 24 16:00:00 2016 PST'::timestamp with time zone AND "time" < 'Mon Jan 23 16:00:00 2017 PST'::timestamp with time zone)
"constraint_4" CHECK (_timescaledb_internal.get_partition_for_key(device::text) >= 1073741823 AND _timescaledb_internal.get_partition_for_key(device::text) < 2147483647)
"constraint_4" CHECK (_timescaledb_internal.get_partition_hash(device) >= 0 AND _timescaledb_internal.get_partition_hash(device) < 1073741823)
Inherits: index_test
Table "_timescaledb_internal._hyper_4_4_chunk"
@ -396,7 +396,7 @@ Indexes:
"_hyper_4_4_chunk_index_test_device_time_idx" btree (device, "time" DESC)
"_hyper_4_4_chunk_index_test_time_temp_idx" btree ("time", temp)
Check constraints:
"constraint_4" CHECK (_timescaledb_internal.get_partition_for_key(device::text) >= 1073741823 AND _timescaledb_internal.get_partition_for_key(device::text) < 2147483647)
"constraint_4" CHECK (_timescaledb_internal.get_partition_hash(device) >= 0 AND _timescaledb_internal.get_partition_hash(device) < 1073741823)
"constraint_5" CHECK ("time" >= 'Fri Mar 24 17:00:00 2017 PDT'::timestamp with time zone AND "time" < 'Sun Apr 23 17:00:00 2017 PDT'::timestamp with time zone)
Inherits: index_test
@ -444,7 +444,7 @@ Indexes:
"_hyper_4_3_chunk_time_temp_idx" btree ("time", temp)
Check constraints:
"constraint_3" CHECK ("time" >= 'Sat Dec 24 16:00:00 2016 PST'::timestamp with time zone AND "time" < 'Mon Jan 23 16:00:00 2017 PST'::timestamp with time zone)
"constraint_4" CHECK (_timescaledb_internal.get_partition_for_key(device::text) >= 1073741823 AND _timescaledb_internal.get_partition_for_key(device::text) < 2147483647)
"constraint_4" CHECK (_timescaledb_internal.get_partition_hash(device) >= 0 AND _timescaledb_internal.get_partition_hash(device) < 1073741823)
Inherits: index_test
Index "_timescaledb_internal._hyper_4_3_chunk_index_test_device_time_idx"
@ -479,7 +479,7 @@ Indexes:
"_hyper_4_4_chunk_index_test_time_idx" btree ("time"), tablespace "tablespace1"
"_hyper_4_4_chunk_index_test_time_temp_idx" btree ("time", temp)
Check constraints:
"constraint_4" CHECK (_timescaledb_internal.get_partition_for_key(device::text) >= 1073741823 AND _timescaledb_internal.get_partition_for_key(device::text) < 2147483647)
"constraint_4" CHECK (_timescaledb_internal.get_partition_hash(device) >= 0 AND _timescaledb_internal.get_partition_hash(device) < 1073741823)
"constraint_5" CHECK ("time" >= 'Fri Mar 24 17:00:00 2017 PDT'::timestamp with time zone AND "time" < 'Sun Apr 23 17:00:00 2017 PDT'::timestamp with time zone)
Inherits: index_test
@ -535,7 +535,7 @@ Indexes:
"_hyper_4_3_chunk_time_temp_idx" btree ("time", temp)
Check constraints:
"constraint_3" CHECK ("time" >= 'Sat Dec 24 16:00:00 2016 PST'::timestamp with time zone AND "time" < 'Mon Jan 23 16:00:00 2017 PST'::timestamp with time zone)
"constraint_4" CHECK (_timescaledb_internal.get_partition_for_key(device::text) >= 1073741823 AND _timescaledb_internal.get_partition_for_key(device::text) < 2147483647)
"constraint_4" CHECK (_timescaledb_internal.get_partition_hash(device) >= 0 AND _timescaledb_internal.get_partition_hash(device) < 1073741823)
Inherits: index_test
Table "_timescaledb_internal._hyper_4_4_chunk"
@ -549,7 +549,7 @@ Indexes:
"_hyper_4_4_chunk_index_test_time_idx" btree ("time"), tablespace "tablespace2"
"_hyper_4_4_chunk_index_test_time_temp_idx" btree ("time", temp)
Check constraints:
"constraint_4" CHECK (_timescaledb_internal.get_partition_for_key(device::text) >= 1073741823 AND _timescaledb_internal.get_partition_for_key(device::text) < 2147483647)
"constraint_4" CHECK (_timescaledb_internal.get_partition_hash(device) >= 0 AND _timescaledb_internal.get_partition_hash(device) < 1073741823)
"constraint_5" CHECK ("time" >= 'Fri Mar 24 17:00:00 2017 PDT'::timestamp with time zone AND "time" < 'Sun Apr 23 17:00:00 2017 PDT'::timestamp with time zone)
Inherits: index_test
@ -584,7 +584,7 @@ Indexes:
"_hyper_4_3_chunk_time_temp_idx" btree ("time", temp)
Check constraints:
"constraint_3" CHECK ("time" >= 'Sat Dec 24 16:00:00 2016 PST'::timestamp with time zone AND "time" < 'Mon Jan 23 16:00:00 2017 PST'::timestamp with time zone)
"constraint_4" CHECK (_timescaledb_internal.get_partition_for_key(device::text) >= 1073741823 AND _timescaledb_internal.get_partition_for_key(device::text) < 2147483647)
"constraint_4" CHECK (_timescaledb_internal.get_partition_hash(device) >= 0 AND _timescaledb_internal.get_partition_hash(device) < 1073741823)
Inherits: index_test
Table "_timescaledb_internal._hyper_4_4_chunk"
@ -599,7 +599,7 @@ Indexes:
"_hyper_4_4_chunk_index_test_time_idx" btree ("time"), tablespace "tablespace2"
"_hyper_4_4_chunk_index_test_time_temp_idx" btree ("time", temp)
Check constraints:
"constraint_4" CHECK (_timescaledb_internal.get_partition_for_key(device::text) >= 1073741823 AND _timescaledb_internal.get_partition_for_key(device::text) < 2147483647)
"constraint_4" CHECK (_timescaledb_internal.get_partition_hash(device) >= 0 AND _timescaledb_internal.get_partition_hash(device) < 1073741823)
"constraint_5" CHECK ("time" >= 'Fri Mar 24 17:00:00 2017 PDT'::timestamp with time zone AND "time" < 'Sun Apr 23 17:00:00 2017 PDT'::timestamp with time zone)
Inherits: index_test

View File

@ -57,7 +57,7 @@ Indexes:
"_hyper_1_1_chunk_two_Partitions_timeCustom_series_bool_idx" btree ("timeCustom" DESC NULLS LAST, series_bool) WHERE series_bool IS NOT NULL
Check constraints:
"constraint_1" CHECK ("timeCustom" >= '1257892416000000000'::bigint AND "timeCustom" < '1257895008000000000'::bigint)
"constraint_2" CHECK (_timescaledb_internal.get_partition_for_key(device_id) >= 1073741823 AND _timescaledb_internal.get_partition_for_key(device_id) < 2147483647)
"constraint_2" CHECK (_timescaledb_internal.get_partition_hash(device_id) >= 1073741823 AND _timescaledb_internal.get_partition_hash(device_id) < 2147483647)
Inherits: "two_Partitions"
Index "_timescaledb_internal._hyper_1_1_chunk_two_Partitions_device_id_timeCustom_idx"
@ -126,7 +126,7 @@ Indexes:
"_hyper_1_2_chunk_two_Partitions_timeCustom_series_2_idx" btree ("timeCustom" DESC NULLS LAST, series_2) WHERE series_2 IS NOT NULL
"_hyper_1_2_chunk_two_Partitions_timeCustom_series_bool_idx" btree ("timeCustom" DESC NULLS LAST, series_bool) WHERE series_bool IS NOT NULL
Check constraints:
"constraint_2" CHECK (_timescaledb_internal.get_partition_for_key(device_id) >= 1073741823 AND _timescaledb_internal.get_partition_for_key(device_id) < 2147483647)
"constraint_2" CHECK (_timescaledb_internal.get_partition_hash(device_id) >= 1073741823 AND _timescaledb_internal.get_partition_hash(device_id) < 2147483647)
"constraint_3" CHECK ("timeCustom" >= '1257897600000000000'::bigint AND "timeCustom" < '1257900192000000000'::bigint)
Inherits: "two_Partitions"
@ -196,7 +196,7 @@ Indexes:
"_hyper_1_3_chunk_two_Partitions_timeCustom_series_2_idx" btree ("timeCustom" DESC NULLS LAST, series_2) WHERE series_2 IS NOT NULL
"_hyper_1_3_chunk_two_Partitions_timeCustom_series_bool_idx" btree ("timeCustom" DESC NULLS LAST, series_bool) WHERE series_bool IS NOT NULL
Check constraints:
"constraint_2" CHECK (_timescaledb_internal.get_partition_for_key(device_id) >= 1073741823 AND _timescaledb_internal.get_partition_for_key(device_id) < 2147483647)
"constraint_2" CHECK (_timescaledb_internal.get_partition_hash(device_id) >= 1073741823 AND _timescaledb_internal.get_partition_hash(device_id) < 2147483647)
"constraint_4" CHECK ("timeCustom" >= '1257985728000000000'::bigint AND "timeCustom" < '1257988320000000000'::bigint)
Inherits: "two_Partitions"
@ -267,7 +267,7 @@ Indexes:
"_hyper_1_4_chunk_two_Partitions_timeCustom_series_bool_idx" btree ("timeCustom" DESC NULLS LAST, series_bool) WHERE series_bool IS NOT NULL
Check constraints:
"constraint_1" CHECK ("timeCustom" >= '1257892416000000000'::bigint AND "timeCustom" < '1257895008000000000'::bigint)
"constraint_5" CHECK (_timescaledb_internal.get_partition_for_key(device_id) >= 0 AND _timescaledb_internal.get_partition_for_key(device_id) < 1073741823)
"constraint_5" CHECK (_timescaledb_internal.get_partition_hash(device_id) >= 0 AND _timescaledb_internal.get_partition_hash(device_id) < 1073741823)
Inherits: "two_Partitions"
Index "_timescaledb_internal._hyper_1_4_chunk_two_Partitions_device_id_timeCustom_idx"

View File

@ -426,8 +426,8 @@ Indexes:
"_hyper_7_15_chunk_3dim_time_idx" btree ("time" DESC)
Check constraints:
"constraint_15" CHECK ("time" >= 'Sat Dec 24 16:00:00 2016'::timestamp without time zone AND "time" < 'Mon Jan 23 16:00:00 2017'::timestamp without time zone)
"constraint_16" CHECK (_timescaledb_internal.get_partition_for_key(device) >= 0 AND _timescaledb_internal.get_partition_for_key(device) < 1073741823)
"constraint_17" CHECK (_timescaledb_internal.get_partition_for_key(location) >= 1073741823 AND _timescaledb_internal.get_partition_for_key(location) < 2147483647)
"constraint_16" CHECK (_timescaledb_internal.get_partition_hash(device) >= 0 AND _timescaledb_internal.get_partition_hash(device) < 1073741823)
"constraint_17" CHECK (_timescaledb_internal.get_partition_hash(location) >= 1073741823 AND _timescaledb_internal.get_partition_hash(location) < 2147483647)
Inherits: "3dim"
--queries should work in three dimensions

View File

@ -0,0 +1,166 @@
CREATE TABLE part_legacy(time timestamptz, temp float, device int);
SELECT create_hypertable('part_legacy', 'time', 'device', 2);
create_hypertable
-------------------
(1 row)
SELECT * FROM _timescaledb_catalog.dimension;
id | hypertable_id | column_name | column_type | aligned | num_slices | partitioning_func_schema | partitioning_func | interval_length
----+---------------+-------------+--------------------------+---------+------------+--------------------------+--------------------+-----------------
1 | 1 | time | timestamp with time zone | t | | | | 2592000000000
2 | 1 | device | integer | f | 2 | _timescaledb_internal | get_partition_hash |
(2 rows)
\c single :ROLE_SUPERUSER
UPDATE _timescaledb_catalog.dimension SET partitioning_func = 'get_partition_for_key'
WHERE partitioning_func IS NOT NULL;
\c single :ROLE_DEFAULT_PERM_USER
-- Show updated partitioning function
SELECT * FROM _timescaledb_catalog.dimension;
id | hypertable_id | column_name | column_type | aligned | num_slices | partitioning_func_schema | partitioning_func | interval_length
----+---------------+-------------+--------------------------+---------+------------+--------------------------+-----------------------+-----------------
1 | 1 | time | timestamp with time zone | t | | | | 2592000000000
2 | 1 | device | integer | f | 2 | _timescaledb_internal | get_partition_for_key |
(2 rows)
INSERT INTO part_legacy VALUES ('2017-03-22T09:18:23', 23.4, 1);
INSERT INTO part_legacy VALUES ('2017-03-22T09:18:23', 23.4, 76);
VACUUM part_legacy;
-- Show two chunks and CHECK constraint with cast
\d+ _timescaledb_internal._hyper_1_*_chunk
Table "_timescaledb_internal._hyper_1_1_chunk"
Column | Type | Modifiers | Storage | Stats target | Description
--------+--------------------------+-----------+---------+--------------+-------------
time | timestamp with time zone | | plain | |
temp | double precision | | plain | |
device | integer | | plain | |
Indexes:
"_hyper_1_1_chunk_part_legacy_device_time_idx" btree (device, "time" DESC)
"_hyper_1_1_chunk_part_legacy_time_idx" btree ("time" DESC)
Check constraints:
"constraint_1" CHECK ("time" >= 'Wed Feb 22 16:00:00 2017 PST'::timestamp with time zone AND "time" < 'Fri Mar 24 17:00:00 2017 PDT'::timestamp with time zone)
"constraint_2" CHECK (_timescaledb_internal.get_partition_for_key(device::text) >= 1073741823 AND _timescaledb_internal.get_partition_for_key(device::text) < 2147483647)
Inherits: part_legacy
Table "_timescaledb_internal._hyper_1_2_chunk"
Column | Type | Modifiers | Storage | Stats target | Description
--------+--------------------------+-----------+---------+--------------+-------------
time | timestamp with time zone | | plain | |
temp | double precision | | plain | |
device | integer | | plain | |
Indexes:
"_hyper_1_2_chunk_part_legacy_device_time_idx" btree (device, "time" DESC)
"_hyper_1_2_chunk_part_legacy_time_idx" btree ("time" DESC)
Check constraints:
"constraint_1" CHECK ("time" >= 'Wed Feb 22 16:00:00 2017 PST'::timestamp with time zone AND "time" < 'Fri Mar 24 17:00:00 2017 PDT'::timestamp with time zone)
"constraint_3" CHECK (_timescaledb_internal.get_partition_for_key(device::text) >= 0 AND _timescaledb_internal.get_partition_for_key(device::text) < 1073741823)
Inherits: part_legacy
-- Make sure constraint exclusion works on device column
EXPLAIN (verbose, costs off)
SELECT * FROM part_legacy WHERE device = 1;
QUERY PLAN
-------------------------------------------------------------------------------------------------------------------------------------------------
Append
-> Seq Scan on public.part_legacy
Output: part_legacy."time", part_legacy.temp, part_legacy.device
Filter: ((part_legacy.device = 1) AND (_timescaledb_internal.get_partition_for_key((part_legacy.device)::text) = 1516350201))
-> Seq Scan on _timescaledb_internal._hyper_1_1_chunk
Output: _hyper_1_1_chunk."time", _hyper_1_1_chunk.temp, _hyper_1_1_chunk.device
Filter: ((_hyper_1_1_chunk.device = 1) AND (_timescaledb_internal.get_partition_for_key((_hyper_1_1_chunk.device)::text) = 1516350201))
(7 rows)
CREATE TABLE part_new(time timestamptz, temp float, device int);
SELECT create_hypertable('part_new', 'time', 'device', 2);
create_hypertable
-------------------
(1 row)
SELECT * FROM _timescaledb_catalog.dimension;
id | hypertable_id | column_name | column_type | aligned | num_slices | partitioning_func_schema | partitioning_func | interval_length
----+---------------+-------------+--------------------------+---------+------------+--------------------------+-----------------------+-----------------
1 | 1 | time | timestamp with time zone | t | | | | 2592000000000
2 | 1 | device | integer | f | 2 | _timescaledb_internal | get_partition_for_key |
3 | 2 | time | timestamp with time zone | t | | | | 2592000000000
4 | 2 | device | integer | f | 2 | _timescaledb_internal | get_partition_hash |
(4 rows)
INSERT INTO part_new VALUES ('2017-03-22T09:18:23', 23.4, 1);
INSERT INTO part_new VALUES ('2017-03-22T09:18:23', 23.4, 2);
VACUUM part_new;
-- Show two chunks and CHECK constraint without cast
\d+ _timescaledb_internal._hyper_2_*_chunk
Table "_timescaledb_internal._hyper_2_3_chunk"
Column | Type | Modifiers | Storage | Stats target | Description
--------+--------------------------+-----------+---------+--------------+-------------
time | timestamp with time zone | | plain | |
temp | double precision | | plain | |
device | integer | | plain | |
Indexes:
"_hyper_2_3_chunk_part_new_device_time_idx" btree (device, "time" DESC)
"_hyper_2_3_chunk_part_new_time_idx" btree ("time" DESC)
Check constraints:
"constraint_4" CHECK ("time" >= 'Wed Feb 22 16:00:00 2017 PST'::timestamp with time zone AND "time" < 'Fri Mar 24 17:00:00 2017 PDT'::timestamp with time zone)
"constraint_5" CHECK (_timescaledb_internal.get_partition_hash(device) >= 0 AND _timescaledb_internal.get_partition_hash(device) < 1073741823)
Inherits: part_new
Table "_timescaledb_internal._hyper_2_4_chunk"
Column | Type | Modifiers | Storage | Stats target | Description
--------+--------------------------+-----------+---------+--------------+-------------
time | timestamp with time zone | | plain | |
temp | double precision | | plain | |
device | integer | | plain | |
Indexes:
"_hyper_2_4_chunk_part_new_device_time_idx" btree (device, "time" DESC)
"_hyper_2_4_chunk_part_new_time_idx" btree ("time" DESC)
Check constraints:
"constraint_4" CHECK ("time" >= 'Wed Feb 22 16:00:00 2017 PST'::timestamp with time zone AND "time" < 'Fri Mar 24 17:00:00 2017 PDT'::timestamp with time zone)
"constraint_6" CHECK (_timescaledb_internal.get_partition_hash(device) >= 1073741823 AND _timescaledb_internal.get_partition_hash(device) < 2147483647)
Inherits: part_new
-- Make sure constraint exclusion works on device column
EXPLAIN (verbose, costs off)
SELECT * FROM part_new WHERE device = 1;
QUERY PLAN
-------------------------------------------------------------------------------------------------------------------------------------
Append
-> Seq Scan on public.part_new
Output: part_new."time", part_new.temp, part_new.device
Filter: ((part_new.device = 1) AND (_timescaledb_internal.get_partition_hash(part_new.device) = 242423622))
-> Seq Scan on _timescaledb_internal._hyper_2_3_chunk
Output: _hyper_2_3_chunk."time", _hyper_2_3_chunk.temp, _hyper_2_3_chunk.device
Filter: ((_hyper_2_3_chunk.device = 1) AND (_timescaledb_internal.get_partition_hash(_hyper_2_3_chunk.device) = 242423622))
(7 rows)
CREATE TABLE part_new_convert1(time timestamptz, temp float8, device int);
SELECT create_hypertable('part_new_convert1', 'time', 'temp', 2);
create_hypertable
-------------------
(1 row)
INSERT INTO part_new_convert1 VALUES ('2017-03-22T09:18:23', 1.0, 2);
\set ON_ERROR_STOP 0
-- Changing the type of a hash-partitioned column should be unsupported
ALTER TABLE part_new_convert1 ALTER COLUMN temp TYPE numeric;
ERROR: Cannot change the type of a hash-partitioned column
\set ON_ERROR_STOP 1
-- Should be able to change if not hash partitioned though
ALTER TABLE part_new_convert1 ALTER COLUMN time TYPE timestamp;
\d+ _timescaledb_internal._hyper_3_*_chunk
Table "_timescaledb_internal._hyper_3_5_chunk"
Column | Type | Modifiers | Storage | Stats target | Description
--------+-----------------------------+-----------+---------+--------------+-------------
time | timestamp without time zone | | plain | |
temp | double precision | | plain | |
device | integer | | plain | |
Indexes:
"_hyper_3_5_chunk_part_new_convert1_temp_time_idx" btree (temp, "time" DESC)
"_hyper_3_5_chunk_part_new_convert1_time_idx" btree ("time" DESC)
Check constraints:
"constraint_7" CHECK ("time" >= 'Wed Feb 22 16:00:00 2017'::timestamp without time zone AND "time" < 'Fri Mar 24 17:00:00 2017'::timestamp without time zone)
"constraint_8" CHECK (_timescaledb_internal.get_partition_hash(temp) >= 0 AND _timescaledb_internal.get_partition_hash(temp) < 1073741823)
Inherits: part_new_convert1

View File

@ -49,7 +49,7 @@ SELECT count(*)
AND refobjid = (SELECT oid FROM pg_extension WHERE extname = 'timescaledb');
count
-------
110
111
(1 row)
\d+ public."two_Partitions"
@ -99,7 +99,7 @@ Indexes:
"_hyper_1_1_chunk_two_Partitions_timeCustom_series_bool_idx" btree ("timeCustom" DESC NULLS LAST, series_bool) WHERE series_bool IS NOT NULL
Check constraints:
"constraint_1" CHECK ("timeCustom" >= '1257892416000000000'::bigint AND "timeCustom" < '1257895008000000000'::bigint)
"constraint_2" CHECK (_timescaledb_internal.get_partition_for_key(device_id) >= 1073741823 AND _timescaledb_internal.get_partition_for_key(device_id) < 2147483647)
"constraint_2" CHECK (_timescaledb_internal.get_partition_hash(device_id) >= 1073741823 AND _timescaledb_internal.get_partition_hash(device_id) < 2147483647)
Triggers:
restore_trigger BEFORE INSERT ON _timescaledb_internal._hyper_1_1_chunk FOR EACH ROW EXECUTE PROCEDURE test_trigger()
Inherits: "two_Partitions"
@ -213,7 +213,7 @@ SELECT count(*)
AND refobjid = (SELECT oid FROM pg_extension WHERE extname = 'timescaledb');
count
-------
110
111
(1 row)
--main table and chunk schemas should be the same
@ -264,7 +264,7 @@ Indexes:
"_hyper_1_1_chunk_two_Partitions_timeCustom_series_bool_idx" btree ("timeCustom" DESC NULLS LAST, series_bool) WHERE series_bool IS NOT NULL
Check constraints:
"constraint_1" CHECK ("timeCustom" >= '1257892416000000000'::bigint AND "timeCustom" < '1257895008000000000'::bigint)
"constraint_2" CHECK (_timescaledb_internal.get_partition_for_key(device_id) >= 1073741823 AND _timescaledb_internal.get_partition_for_key(device_id) < 2147483647)
"constraint_2" CHECK (_timescaledb_internal.get_partition_hash(device_id) >= 1073741823 AND _timescaledb_internal.get_partition_hash(device_id) < 2147483647)
Triggers:
restore_trigger BEFORE INSERT ON _timescaledb_internal._hyper_1_1_chunk FOR EACH ROW EXECUTE PROCEDURE test_trigger()
Inherits: "two_Partitions"

View File

@ -51,20 +51,20 @@ SELECT * FROM hypertable_relation_size_pretty('"public"."two_Partitions"');
SELECT * FROM chunk_relation_size('"public"."two_Partitions"');
chunk_id | chunk_table | partitioning_columns | partitioning_column_types | partitioning_hash_functions | ranges | table_bytes | index_bytes | toast_bytes | total_bytes
----------+--------------------------------------------+------------------------+---------------------------+----------------------------------------------------+-------------------------------------------------------------------------+-------------+-------------+-------------+-------------
1 | "_timescaledb_internal"."_hyper_1_1_chunk" | {timeCustom,device_id} | {bigint,text} | {NULL,_timescaledb_internal.get_partition_for_key} | {"[1257892416000000000,1257895008000000000)","[1073741823,2147483647)"} | 8192 | 114688 | 8192 | 131072
2 | "_timescaledb_internal"."_hyper_1_2_chunk" | {timeCustom,device_id} | {bigint,text} | {NULL,_timescaledb_internal.get_partition_for_key} | {"[1257897600000000000,1257900192000000000)","[1073741823,2147483647)"} | 8192 | 106496 | 8192 | 122880
3 | "_timescaledb_internal"."_hyper_1_3_chunk" | {timeCustom,device_id} | {bigint,text} | {NULL,_timescaledb_internal.get_partition_for_key} | {"[1257985728000000000,1257988320000000000)","[1073741823,2147483647)"} | 8192 | 98304 | 8192 | 114688
4 | "_timescaledb_internal"."_hyper_1_4_chunk" | {timeCustom,device_id} | {bigint,text} | {NULL,_timescaledb_internal.get_partition_for_key} | {"[1257892416000000000,1257895008000000000)","[0,1073741823)"} | 8192 | 98304 | 8192 | 114688
----------+--------------------------------------------+------------------------+---------------------------+-------------------------------------------------+-------------------------------------------------------------------------+-------------+-------------+-------------+-------------
1 | "_timescaledb_internal"."_hyper_1_1_chunk" | {timeCustom,device_id} | {bigint,text} | {NULL,_timescaledb_internal.get_partition_hash} | {"[1257892416000000000,1257895008000000000)","[1073741823,2147483647)"} | 8192 | 114688 | 8192 | 131072
2 | "_timescaledb_internal"."_hyper_1_2_chunk" | {timeCustom,device_id} | {bigint,text} | {NULL,_timescaledb_internal.get_partition_hash} | {"[1257897600000000000,1257900192000000000)","[1073741823,2147483647)"} | 8192 | 106496 | 8192 | 122880
3 | "_timescaledb_internal"."_hyper_1_3_chunk" | {timeCustom,device_id} | {bigint,text} | {NULL,_timescaledb_internal.get_partition_hash} | {"[1257985728000000000,1257988320000000000)","[1073741823,2147483647)"} | 8192 | 98304 | 8192 | 114688
4 | "_timescaledb_internal"."_hyper_1_4_chunk" | {timeCustom,device_id} | {bigint,text} | {NULL,_timescaledb_internal.get_partition_hash} | {"[1257892416000000000,1257895008000000000)","[0,1073741823)"} | 8192 | 98304 | 8192 | 114688
(4 rows)
SELECT * FROM chunk_relation_size_pretty('"public"."two_Partitions"');
chunk_id | chunk_table | partitioning_columns | partitioning_column_types | partitioning_hash_functions | ranges | table_size | index_size | toast_size | total_size
----------+--------------------------------------------+------------------------+---------------------------+----------------------------------------------------+-----------------------------------------------------------------------------+------------+------------+------------+------------
1 | "_timescaledb_internal"."_hyper_1_1_chunk" | {timeCustom,device_id} | {bigint,text} | {NULL,_timescaledb_internal.get_partition_for_key} | {"['1257892416000000000','1257895008000000000')","[1073741823,2147483647)"} | 8192 bytes | 112 kB | 8192 bytes | 128 kB
2 | "_timescaledb_internal"."_hyper_1_2_chunk" | {timeCustom,device_id} | {bigint,text} | {NULL,_timescaledb_internal.get_partition_for_key} | {"['1257897600000000000','1257900192000000000')","[1073741823,2147483647)"} | 8192 bytes | 104 kB | 8192 bytes | 120 kB
3 | "_timescaledb_internal"."_hyper_1_3_chunk" | {timeCustom,device_id} | {bigint,text} | {NULL,_timescaledb_internal.get_partition_for_key} | {"['1257985728000000000','1257988320000000000')","[1073741823,2147483647)"} | 8192 bytes | 96 kB | 8192 bytes | 112 kB
4 | "_timescaledb_internal"."_hyper_1_4_chunk" | {timeCustom,device_id} | {bigint,text} | {NULL,_timescaledb_internal.get_partition_for_key} | {"['1257892416000000000','1257895008000000000')","[0,1073741823)"} | 8192 bytes | 96 kB | 8192 bytes | 112 kB
----------+--------------------------------------------+------------------------+---------------------------+-------------------------------------------------+-----------------------------------------------------------------------------+------------+------------+------------+------------
1 | "_timescaledb_internal"."_hyper_1_1_chunk" | {timeCustom,device_id} | {bigint,text} | {NULL,_timescaledb_internal.get_partition_hash} | {"['1257892416000000000','1257895008000000000')","[1073741823,2147483647)"} | 8192 bytes | 112 kB | 8192 bytes | 128 kB
2 | "_timescaledb_internal"."_hyper_1_2_chunk" | {timeCustom,device_id} | {bigint,text} | {NULL,_timescaledb_internal.get_partition_hash} | {"['1257897600000000000','1257900192000000000')","[1073741823,2147483647)"} | 8192 bytes | 104 kB | 8192 bytes | 120 kB
3 | "_timescaledb_internal"."_hyper_1_3_chunk" | {timeCustom,device_id} | {bigint,text} | {NULL,_timescaledb_internal.get_partition_hash} | {"['1257985728000000000','1257988320000000000')","[1073741823,2147483647)"} | 8192 bytes | 96 kB | 8192 bytes | 112 kB
4 | "_timescaledb_internal"."_hyper_1_4_chunk" | {timeCustom,device_id} | {bigint,text} | {NULL,_timescaledb_internal.get_partition_hash} | {"['1257892416000000000','1257895008000000000')","[0,1073741823)"} | 8192 bytes | 96 kB | 8192 bytes | 112 kB
(4 rows)
SELECT * FROM indexes_relation_size('"public"."two_Partitions"');
@ -102,16 +102,16 @@ INSERT INTO timestamp_partitioned VALUES('2004-10-19 10:23:54', '10');
INSERT INTO timestamp_partitioned VALUES('2004-12-19 10:23:54', '30');
SELECT * FROM chunk_relation_size('timestamp_partitioned');
chunk_id | chunk_table | partitioning_columns | partitioning_column_types | partitioning_hash_functions | ranges | table_bytes | index_bytes | toast_bytes | total_bytes
----------+--------------------------------------------+----------------------+--------------------------------------+----------------------------------------------------+-------------------------------------------------------------------+-------------+-------------+-------------+-------------
5 | "_timescaledb_internal"."_hyper_2_5_chunk" | {time,value} | {"timestamp without time zone",text} | {NULL,_timescaledb_internal.get_partition_for_key} | {"[1096416000000000,1099008000000000)","[1073741823,2147483647)"} | 8192 | 32768 | 8192 | 49152
6 | "_timescaledb_internal"."_hyper_2_6_chunk" | {time,value} | {"timestamp without time zone",text} | {NULL,_timescaledb_internal.get_partition_for_key} | {"[1101600000000000,1104192000000000)","[1073741823,2147483647)"} | 8192 | 32768 | 8192 | 49152
----------+--------------------------------------------+----------------------+--------------------------------------+-------------------------------------------------+-------------------------------------------------------------------+-------------+-------------+-------------+-------------
5 | "_timescaledb_internal"."_hyper_2_5_chunk" | {time,value} | {"timestamp without time zone",text} | {NULL,_timescaledb_internal.get_partition_hash} | {"[1096416000000000,1099008000000000)","[1073741823,2147483647)"} | 8192 | 32768 | 8192 | 49152
6 | "_timescaledb_internal"."_hyper_2_6_chunk" | {time,value} | {"timestamp without time zone",text} | {NULL,_timescaledb_internal.get_partition_hash} | {"[1101600000000000,1104192000000000)","[1073741823,2147483647)"} | 8192 | 32768 | 8192 | 49152
(2 rows)
SELECT * FROM chunk_relation_size_pretty('timestamp_partitioned');
chunk_id | chunk_table | partitioning_columns | partitioning_column_types | partitioning_hash_functions | ranges | table_size | index_size | toast_size | total_size
----------+--------------------------------------------+----------------------+--------------------------------------+----------------------------------------------------+-----------------------------------------------------------------------------------------------+------------+------------+------------+------------
5 | "_timescaledb_internal"."_hyper_2_5_chunk" | {time,value} | {"timestamp without time zone",text} | {NULL,_timescaledb_internal.get_partition_for_key} | {"['Tue Sep 28 17:00:00 2004 PDT','Thu Oct 28 17:00:00 2004 PDT')","[1073741823,2147483647)"} | 8192 bytes | 32 kB | 8192 bytes | 48 kB
6 | "_timescaledb_internal"."_hyper_2_6_chunk" | {time,value} | {"timestamp without time zone",text} | {NULL,_timescaledb_internal.get_partition_for_key} | {"['Sat Nov 27 16:00:00 2004 PST','Mon Dec 27 16:00:00 2004 PST')","[1073741823,2147483647)"} | 8192 bytes | 32 kB | 8192 bytes | 48 kB
----------+--------------------------------------------+----------------------+--------------------------------------+-------------------------------------------------+-----------------------------------------------------------------------------------------------+------------+------------+------------+------------
5 | "_timescaledb_internal"."_hyper_2_5_chunk" | {time,value} | {"timestamp without time zone",text} | {NULL,_timescaledb_internal.get_partition_hash} | {"['Tue Sep 28 17:00:00 2004 PDT','Thu Oct 28 17:00:00 2004 PDT')","[1073741823,2147483647)"} | 8192 bytes | 32 kB | 8192 bytes | 48 kB
6 | "_timescaledb_internal"."_hyper_2_6_chunk" | {time,value} | {"timestamp without time zone",text} | {NULL,_timescaledb_internal.get_partition_hash} | {"['Sat Nov 27 16:00:00 2004 PST','Mon Dec 27 16:00:00 2004 PST')","[1073741823,2147483647)"} | 8192 bytes | 32 kB | 8192 bytes | 48 kB
(2 rows)
CREATE TABLE timestamp_partitioned_2(time TIMESTAMP, value CHAR(9));
@ -125,15 +125,15 @@ INSERT INTO timestamp_partitioned_2 VALUES('2004-10-19 10:23:54', '10');
INSERT INTO timestamp_partitioned_2 VALUES('2004-12-19 10:23:54', '30');
SELECT * FROM chunk_relation_size('timestamp_partitioned_2');
chunk_id | chunk_table | partitioning_columns | partitioning_column_types | partitioning_hash_functions | ranges | table_bytes | index_bytes | toast_bytes | total_bytes
----------+--------------------------------------------+----------------------+-------------------------------------------+----------------------------------------------------+-------------------------------------------------------------------+-------------+-------------+-------------+-------------
7 | "_timescaledb_internal"."_hyper_3_7_chunk" | {time,value} | {"timestamp without time zone",character} | {NULL,_timescaledb_internal.get_partition_for_key} | {"[1096416000000000,1099008000000000)","[1073741823,2147483647)"} | 8192 | 32768 | | 40960
8 | "_timescaledb_internal"."_hyper_3_8_chunk" | {time,value} | {"timestamp without time zone",character} | {NULL,_timescaledb_internal.get_partition_for_key} | {"[1101600000000000,1104192000000000)","[1073741823,2147483647)"} | 8192 | 32768 | | 40960
----------+--------------------------------------------+----------------------+-------------------------------------------+-------------------------------------------------+-------------------------------------------------------------------+-------------+-------------+-------------+-------------
7 | "_timescaledb_internal"."_hyper_3_7_chunk" | {time,value} | {"timestamp without time zone",character} | {NULL,_timescaledb_internal.get_partition_hash} | {"[1096416000000000,1099008000000000)","[1073741823,2147483647)"} | 8192 | 32768 | | 40960
8 | "_timescaledb_internal"."_hyper_3_8_chunk" | {time,value} | {"timestamp without time zone",character} | {NULL,_timescaledb_internal.get_partition_hash} | {"[1101600000000000,1104192000000000)","[1073741823,2147483647)"} | 8192 | 32768 | | 40960
(2 rows)
SELECT * FROM chunk_relation_size_pretty('timestamp_partitioned_2');
chunk_id | chunk_table | partitioning_columns | partitioning_column_types | partitioning_hash_functions | ranges | table_size | index_size | toast_size | total_size
----------+--------------------------------------------+----------------------+-------------------------------------------+----------------------------------------------------+-----------------------------------------------------------------------------------------------+------------+------------+------------+------------
7 | "_timescaledb_internal"."_hyper_3_7_chunk" | {time,value} | {"timestamp without time zone",character} | {NULL,_timescaledb_internal.get_partition_for_key} | {"['Tue Sep 28 17:00:00 2004 PDT','Thu Oct 28 17:00:00 2004 PDT')","[1073741823,2147483647)"} | 8192 bytes | 32 kB | | 40 kB
8 | "_timescaledb_internal"."_hyper_3_8_chunk" | {time,value} | {"timestamp without time zone",character} | {NULL,_timescaledb_internal.get_partition_for_key} | {"['Sat Nov 27 16:00:00 2004 PST','Mon Dec 27 16:00:00 2004 PST')","[1073741823,2147483647)"} | 8192 bytes | 32 kB | | 40 kB
----------+--------------------------------------------+----------------------+-------------------------------------------+-------------------------------------------------+-----------------------------------------------------------------------------------------------+------------+------------+------------+------------
7 | "_timescaledb_internal"."_hyper_3_7_chunk" | {time,value} | {"timestamp without time zone",character} | {NULL,_timescaledb_internal.get_partition_hash} | {"['Tue Sep 28 17:00:00 2004 PDT','Thu Oct 28 17:00:00 2004 PDT')","[1073741823,2147483647)"} | 8192 bytes | 32 kB | | 40 kB
8 | "_timescaledb_internal"."_hyper_3_8_chunk" | {time,value} | {"timestamp without time zone",character} | {NULL,_timescaledb_internal.get_partition_hash} | {"['Sat Nov 27 16:00:00 2004 PST','Mon Dec 27 16:00:00 2004 PST')","[1073741823,2147483647)"} | 8192 bytes | 32 kB | | 40 kB
(2 rows)

View File

@ -62,19 +62,19 @@ EXPLAIN (verbose ON, costs off) SELECT * FROM PUBLIC."two_Partitions";
Output: _hyper_1_4_chunk."timeCustom", _hyper_1_4_chunk.device_id, _hyper_1_4_chunk.series_0, _hyper_1_4_chunk.series_1, _hyper_1_4_chunk.series_2, _hyper_1_4_chunk.series_bool
(11 rows)
\echo "The following queries should NOT scan two_Partitions._hyper_1_1_0_partition"
"The following queries should NOT scan two_Partitions._hyper_1_1_0_partition"
\echo "The following queries should NOT scan two_Partitions._hyper_1_1_chunk"
"The following queries should NOT scan two_Partitions._hyper_1_1_chunk"
EXPLAIN (verbose ON, costs off) SELECT * FROM PUBLIC."two_Partitions" WHERE device_id = 'dev2';
QUERY PLAN
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Append
-> Seq Scan on public."two_Partitions"
Output: "two_Partitions"."timeCustom", "two_Partitions".device_id, "two_Partitions".series_0, "two_Partitions".series_1, "two_Partitions".series_2, "two_Partitions".series_bool
Filter: (("two_Partitions".device_id = 'dev2'::text) AND (_timescaledb_internal.get_partition_for_key("two_Partitions".device_id) = 405750566))
Filter: (("two_Partitions".device_id = 'dev2'::text) AND (_timescaledb_internal.get_partition_hash("two_Partitions".device_id) = 405750566))
-> Bitmap Heap Scan on _timescaledb_internal._hyper_1_4_chunk
Output: _hyper_1_4_chunk."timeCustom", _hyper_1_4_chunk.device_id, _hyper_1_4_chunk.series_0, _hyper_1_4_chunk.series_1, _hyper_1_4_chunk.series_2, _hyper_1_4_chunk.series_bool
Recheck Cond: (_hyper_1_4_chunk.device_id = 'dev2'::text)
Filter: (_timescaledb_internal.get_partition_for_key(_hyper_1_4_chunk.device_id) = 405750566)
Filter: (_timescaledb_internal.get_partition_hash(_hyper_1_4_chunk.device_id) = 405750566)
-> Bitmap Index Scan on "_hyper_1_4_chunk_two_Partitions_device_id_timeCustom_idx"
Index Cond: (_hyper_1_4_chunk.device_id = 'dev2'::text)
(10 rows)
@ -85,11 +85,11 @@ EXPLAIN (verbose ON, costs off) SELECT * FROM PUBLIC."two_Partitions" WHERE devi
Append
-> Seq Scan on public."two_Partitions"
Output: "two_Partitions"."timeCustom", "two_Partitions".device_id, "two_Partitions".series_0, "two_Partitions".series_1, "two_Partitions".series_2, "two_Partitions".series_bool
Filter: (("two_Partitions".device_id = 'dev2'::text) AND (_timescaledb_internal.get_partition_for_key("two_Partitions".device_id) = 405750566))
Filter: (("two_Partitions".device_id = 'dev2'::text) AND (_timescaledb_internal.get_partition_hash("two_Partitions".device_id) = 405750566))
-> Bitmap Heap Scan on _timescaledb_internal._hyper_1_4_chunk
Output: _hyper_1_4_chunk."timeCustom", _hyper_1_4_chunk.device_id, _hyper_1_4_chunk.series_0, _hyper_1_4_chunk.series_1, _hyper_1_4_chunk.series_2, _hyper_1_4_chunk.series_bool
Recheck Cond: (_hyper_1_4_chunk.device_id = 'dev2'::text)
Filter: (_timescaledb_internal.get_partition_for_key(_hyper_1_4_chunk.device_id) = 405750566)
Filter: (_timescaledb_internal.get_partition_hash(_hyper_1_4_chunk.device_id) = 405750566)
-> Bitmap Index Scan on "_hyper_1_4_chunk_two_Partitions_device_id_timeCustom_idx"
Index Cond: (_hyper_1_4_chunk.device_id = 'dev2'::text)
(10 rows)
@ -100,11 +100,11 @@ EXPLAIN (verbose ON, costs off) SELECT * FROM PUBLIC."two_Partitions" WHERE 'dev
Append
-> Seq Scan on public."two_Partitions"
Output: "two_Partitions"."timeCustom", "two_Partitions".device_id, "two_Partitions".series_0, "two_Partitions".series_1, "two_Partitions".series_2, "two_Partitions".series_bool
Filter: (('dev2'::text = "two_Partitions".device_id) AND (_timescaledb_internal.get_partition_for_key("two_Partitions".device_id) = 405750566))
Filter: (('dev2'::text = "two_Partitions".device_id) AND (_timescaledb_internal.get_partition_hash("two_Partitions".device_id) = 405750566))
-> Bitmap Heap Scan on _timescaledb_internal._hyper_1_4_chunk
Output: _hyper_1_4_chunk."timeCustom", _hyper_1_4_chunk.device_id, _hyper_1_4_chunk.series_0, _hyper_1_4_chunk.series_1, _hyper_1_4_chunk.series_2, _hyper_1_4_chunk.series_bool
Recheck Cond: ('dev2'::text = _hyper_1_4_chunk.device_id)
Filter: (_timescaledb_internal.get_partition_for_key(_hyper_1_4_chunk.device_id) = 405750566)
Filter: (_timescaledb_internal.get_partition_hash(_hyper_1_4_chunk.device_id) = 405750566)
-> Bitmap Index Scan on "_hyper_1_4_chunk_two_Partitions_device_id_timeCustom_idx"
Index Cond: ('dev2'::text = _hyper_1_4_chunk.device_id)
(10 rows)
@ -118,6 +118,37 @@ SELECT create_hypertable('"int_part"', 'time', 'object_id', 2);
(1 row)
INSERT INTO "int_part" VALUES('2017-01-20T09:00:01', 1, 22.5);
INSERT INTO "int_part" VALUES('2017-01-20T09:00:01', 2, 22.5);
--check that there are two chunks
\d _timescaledb_internal._hyper_2_*_chunk
Table "_timescaledb_internal._hyper_2_5_chunk"
Column | Type | Modifiers
-----------+-----------------------------+-----------
time | timestamp without time zone |
object_id | integer |
temp | double precision |
Indexes:
"_hyper_2_5_chunk_int_part_object_id_time_idx" btree (object_id, "time" DESC)
"_hyper_2_5_chunk_int_part_time_idx" btree ("time" DESC)
Check constraints:
"constraint_6" CHECK ("time" >= 'Sat Dec 24 16:00:00 2016'::timestamp without time zone AND "time" < 'Mon Jan 23 16:00:00 2017'::timestamp without time zone)
"constraint_7" CHECK (_timescaledb_internal.get_partition_hash(object_id) >= 0 AND _timescaledb_internal.get_partition_hash(object_id) < 1073741823)
Inherits: int_part
Table "_timescaledb_internal._hyper_2_6_chunk"
Column | Type | Modifiers
-----------+-----------------------------+-----------
time | timestamp without time zone |
object_id | integer |
temp | double precision |
Indexes:
"_hyper_2_6_chunk_int_part_object_id_time_idx" btree (object_id, "time" DESC)
"_hyper_2_6_chunk_int_part_time_idx" btree ("time" DESC)
Check constraints:
"constraint_6" CHECK ("time" >= 'Sat Dec 24 16:00:00 2016'::timestamp without time zone AND "time" < 'Mon Jan 23 16:00:00 2017'::timestamp without time zone)
"constraint_8" CHECK (_timescaledb_internal.get_partition_hash(object_id) >= 1073741823 AND _timescaledb_internal.get_partition_hash(object_id) < 2147483647)
Inherits: int_part
SELECT * FROM "int_part" WHERE object_id = 1;
time | object_id | temp
--------------------------+-----------+------
@ -127,15 +158,15 @@ SELECT * FROM "int_part" WHERE object_id = 1;
--make sure this touches only one partititon
EXPLAIN (verbose ON, costs off) SELECT * FROM "int_part" WHERE object_id = 1;
QUERY PLAN
---------------------------------------------------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------------------------------------
Append
-> Seq Scan on public.int_part
Output: int_part."time", int_part.object_id, int_part.temp
Filter: ((int_part.object_id = 1) AND (_timescaledb_internal.get_partition_for_key((int_part.object_id)::text) = 1516350201))
Filter: ((int_part.object_id = 1) AND (_timescaledb_internal.get_partition_hash(int_part.object_id) = 242423622))
-> Bitmap Heap Scan on _timescaledb_internal._hyper_2_5_chunk
Output: _hyper_2_5_chunk."time", _hyper_2_5_chunk.object_id, _hyper_2_5_chunk.temp
Recheck Cond: (_hyper_2_5_chunk.object_id = 1)
Filter: (_timescaledb_internal.get_partition_for_key((_hyper_2_5_chunk.object_id)::text) = 1516350201)
Filter: (_timescaledb_internal.get_partition_hash(_hyper_2_5_chunk.object_id) = 242423622)
-> Bitmap Index Scan on _hyper_2_5_chunk_int_part_object_id_time_idx
Index Cond: (_hyper_2_5_chunk.object_id = 1)
(10 rows)

View File

@ -27,12 +27,12 @@ CREATE TABLE chunk_test(time integer, temp float8, tag integer, color integer);
SELECT create_hypertable('chunk_test', 'time', 'tag', 2, chunk_time_interval => 3);
INSERT INTO chunk_test VALUES (4, 24.3, 3, 1);
INSERT INTO chunk_test VALUES (4, 24.3, 1, 1);
SELECT * FROM _timescaledb_catalog.dimension_slice;
INSERT INTO chunk_test VALUES (4, 24.3, 1, 1);
INSERT INTO chunk_test VALUES (10, 24.3, 1, 1);
INSERT INTO chunk_test VALUES (4, 24.3, 2, 1);
INSERT INTO chunk_test VALUES (10, 24.3, 2, 1);
SELECT c.table_name AS chunk_name, d.id AS dimension_id, ds.id AS slice_id, range_start, range_end FROM _timescaledb_catalog.chunk c
LEFT JOIN _timescaledb_catalog.chunk_constraint cc ON (c.id = cc.chunk_id)
@ -47,15 +47,15 @@ UPDATE _timescaledb_catalog.dimension SET num_slices = 3 WHERE id = 2;
\c single :ROLE_DEFAULT_PERM_USER
SELECT set_chunk_time_interval('chunk_test', 1::bigint);
INSERT INTO chunk_test VALUES (8, 24.3, 79669, 1);
INSERT INTO chunk_test VALUES (8, 24.3, 11233, 1);
SELECT set_chunk_time_interval('chunk_test', 5::bigint);
SELECT * FROM _timescaledb_catalog.dimension;
INSERT INTO chunk_test VALUES (7, 24.3, 11233, 1);
INSERT INTO chunk_test VALUES (8, 24.3, 11233, 1);
INSERT INTO chunk_test VALUES (10, 24.3, 79669, 1);
INSERT INTO chunk_test VALUES (16, 24.3, 79669, 1);
INSERT INTO chunk_test VALUES (7, 24.3, 79669, 1);
INSERT INTO chunk_test VALUES (8, 24.3, 79669, 1);
INSERT INTO chunk_test VALUES (10, 24.3, 11233, 1);
INSERT INTO chunk_test VALUES (16, 24.3, 11233, 1);
SELECT c.table_name AS chunk_name, d.id AS dimension_id, ds.id AS slice_id, range_start, range_end FROM _timescaledb_catalog.chunk c
LEFT JOIN _timescaledb_catalog.chunk_constraint cc ON (c.id = cc.chunk_id)

View File

@ -20,7 +20,11 @@ SELECT * FROM alter_test WHERE time > '2017-05-20T10:00:01';
ALTER TABLE alter_test RENAME COLUMN time TO time_us;
ALTER TABLE alter_test ALTER COLUMN time_us TYPE timestamp;
ALTER TABLE alter_test RENAME COLUMN color TO colorname;
\set ON_ERROR_STOP 0
-- Changing types on hash-partitioned columns is not safe for some
-- types and is therefore blocked.
ALTER TABLE alter_test ALTER COLUMN colorname TYPE text;
\set ON_ERROR_STOP 1
\d+ alter_test
\d+ _timescaledb_internal.*

64
test/sql/hash.sql Normal file
View File

@ -0,0 +1,64 @@
-- Test hashing Const values. We should expect the same hash value for
-- all integer types when values are compatible
SELECT _timescaledb_internal.get_partition_hash(1::int);
SELECT _timescaledb_internal.get_partition_hash(1::bigint);
SELECT _timescaledb_internal.get_partition_hash(1::smallint);
SELECT _timescaledb_internal.get_partition_hash(true);
-- Floating point types should also hash the same for compatible values
SELECT _timescaledb_internal.get_partition_hash(1.0::real);
SELECT _timescaledb_internal.get_partition_hash(1.0::double precision);
-- Float aliases
SELECT _timescaledb_internal.get_partition_hash(1.0::float);
SELECT _timescaledb_internal.get_partition_hash(1.0::float4);
SELECT _timescaledb_internal.get_partition_hash(1.0::float8);
SELECT _timescaledb_internal.get_partition_hash(1.0::numeric);
-- 'name' and '"char"' are internal PostgreSQL types, which are not
-- intended for use by the general user. They are included here only
-- for completeness
-- https://www.postgresql.org/docs/10/static/datatype-character.html#datatype-character-special-table
SELECT _timescaledb_internal.get_partition_hash('c'::name);
SELECT _timescaledb_internal.get_partition_hash('c'::"char");
-- String and character hashes should also have the same output for
-- compatible values
SELECT _timescaledb_internal.get_partition_hash('c'::char);
SELECT _timescaledb_internal.get_partition_hash('c'::varchar(2));
SELECT _timescaledb_internal.get_partition_hash('c'::text);
-- 'c' is 0x63 in ASCII
SELECT _timescaledb_internal.get_partition_hash(E'\\x63'::bytea);
-- Time and date types
SELECT _timescaledb_internal.get_partition_hash(interval '1 day');
SELECT _timescaledb_internal.get_partition_hash('2017-03-22T09:18:23'::timestamp);
SELECT _timescaledb_internal.get_partition_hash('2017-03-22T09:18:23'::timestamptz);
SELECT _timescaledb_internal.get_partition_hash('2017-03-22'::date);
SELECT _timescaledb_internal.get_partition_hash('10:00:00'::time);
SELECT _timescaledb_internal.get_partition_hash('10:00:00-1'::timetz);
-- Other types
SELECT _timescaledb_internal.get_partition_hash(ARRAY[1,2,3]);
SELECT _timescaledb_internal.get_partition_hash('08002b:010203'::macaddr);
SELECT _timescaledb_internal.get_partition_hash('192.168.100.128/25'::cidr);
SELECT _timescaledb_internal.get_partition_hash('192.168.100.128'::inet);
SELECT _timescaledb_internal.get_partition_hash('2001:4f8:3:ba:2e0:81ff:fe22:d1f1'::inet);
SELECT _timescaledb_internal.get_partition_hash('2001:4f8:3:ba:2e0:81ff:fe22:d1f1/128'::cidr);
SELECT _timescaledb_internal.get_partition_hash('{ "foo": "bar" }'::jsonb);
SELECT _timescaledb_internal.get_partition_hash('4b6a5eec-b344-11e7-abc4-cec278b6b50a'::uuid);
SELECT _timescaledb_internal.get_partition_hash(1::regclass);
SELECT _timescaledb_internal.get_partition_hash(int4range(10, 20));
SELECT _timescaledb_internal.get_partition_hash(int8range(10, 20));
SELECT _timescaledb_internal.get_partition_hash(numrange(10, 20));
SELECT _timescaledb_internal.get_partition_hash(tsrange('2017-03-22T09:18:23', '2017-03-23T09:18:23'));
SELECT _timescaledb_internal.get_partition_hash(tstzrange('2017-03-22T09:18:23+01', '2017-03-23T09:18:23+00'));
-- Test hashing Var values
CREATE TABLE hash_test(id int, value text);
INSERT INTO hash_test VALUES (1, 'test');
-- Test Vars
SELECT _timescaledb_internal.get_partition_hash(id) FROM hash_test;
SELECT _timescaledb_internal.get_partition_hash(value) FROM hash_test;
-- Test coerced value
SELECT _timescaledb_internal.get_partition_hash(id::text) FROM hash_test;

55
test/sql/partitioning.sql Normal file
View File

@ -0,0 +1,55 @@
CREATE TABLE part_legacy(time timestamptz, temp float, device int);
SELECT create_hypertable('part_legacy', 'time', 'device', 2);
SELECT * FROM _timescaledb_catalog.dimension;
\c single :ROLE_SUPERUSER
UPDATE _timescaledb_catalog.dimension SET partitioning_func = 'get_partition_for_key'
WHERE partitioning_func IS NOT NULL;
\c single :ROLE_DEFAULT_PERM_USER
-- Show updated partitioning function
SELECT * FROM _timescaledb_catalog.dimension;
INSERT INTO part_legacy VALUES ('2017-03-22T09:18:23', 23.4, 1);
INSERT INTO part_legacy VALUES ('2017-03-22T09:18:23', 23.4, 76);
VACUUM part_legacy;
-- Show two chunks and CHECK constraint with cast
\d+ _timescaledb_internal._hyper_1_*_chunk
-- Make sure constraint exclusion works on device column
EXPLAIN (verbose, costs off)
SELECT * FROM part_legacy WHERE device = 1;
CREATE TABLE part_new(time timestamptz, temp float, device int);
SELECT create_hypertable('part_new', 'time', 'device', 2);
SELECT * FROM _timescaledb_catalog.dimension;
INSERT INTO part_new VALUES ('2017-03-22T09:18:23', 23.4, 1);
INSERT INTO part_new VALUES ('2017-03-22T09:18:23', 23.4, 2);
VACUUM part_new;
-- Show two chunks and CHECK constraint without cast
\d+ _timescaledb_internal._hyper_2_*_chunk
-- Make sure constraint exclusion works on device column
EXPLAIN (verbose, costs off)
SELECT * FROM part_new WHERE device = 1;
CREATE TABLE part_new_convert1(time timestamptz, temp float8, device int);
SELECT create_hypertable('part_new_convert1', 'time', 'temp', 2);
INSERT INTO part_new_convert1 VALUES ('2017-03-22T09:18:23', 1.0, 2);
\set ON_ERROR_STOP 0
-- Changing the type of a hash-partitioned column should be unsupported
ALTER TABLE part_new_convert1 ALTER COLUMN temp TYPE numeric;
\set ON_ERROR_STOP 1
-- Should be able to change if not hash partitioned though
ALTER TABLE part_new_convert1 ALTER COLUMN time TYPE timestamp;
\d+ _timescaledb_internal._hyper_3_*_chunk

View File

@ -6,16 +6,20 @@ SELECT * FROM PUBLIC."two_Partitions";
EXPLAIN (verbose ON, costs off) SELECT * FROM PUBLIC."two_Partitions";
\echo "The following queries should NOT scan two_Partitions._hyper_1_1_0_partition"
\echo "The following queries should NOT scan two_Partitions._hyper_1_1_chunk"
EXPLAIN (verbose ON, costs off) SELECT * FROM PUBLIC."two_Partitions" WHERE device_id = 'dev2';
EXPLAIN (verbose ON, costs off) SELECT * FROM PUBLIC."two_Partitions" WHERE device_id = 'dev'||'2';
EXPLAIN (verbose ON, costs off) SELECT * FROM PUBLIC."two_Partitions" WHERE 'dev'||'2' = device_id;
--test integer partition key
CREATE TABLE "int_part"(time timestamp, object_id int, temp float);
SELECT create_hypertable('"int_part"', 'time', 'object_id', 2);
INSERT INTO "int_part" VALUES('2017-01-20T09:00:01', 1, 22.5);
INSERT INTO "int_part" VALUES('2017-01-20T09:00:01', 2, 22.5);
--check that there are two chunks
\d _timescaledb_internal._hyper_2_*_chunk
SELECT * FROM "int_part" WHERE object_id = 1;
--make sure this touches only one partititon
EXPLAIN (verbose ON, costs off) SELECT * FROM "int_part" WHERE object_id = 1;
@ -37,6 +41,3 @@ EXPLAIN (verbose ON, costs off)SELECT "timeCustom" t, min(series_0) FROM PUBLIC.
--TODO: time transform doesn't work
EXPLAIN (verbose ON, costs off)SELECT "timeCustom"/10 t, min(series_0) FROM PUBLIC."two_Partitions" GROUP BY t ORDER BY t DESC NULLS LAST limit 2;
EXPLAIN (verbose ON, costs off)SELECT "timeCustom"%10 t, min(series_0) FROM PUBLIC."two_Partitions" GROUP BY t ORDER BY t DESC NULLS LAST limit 2;

View File

@ -1,7 +1,8 @@
--keep same order of tables as tables.sql
SELECT * FROM _timescaledb_catalog.hypertable ORDER BY id;
SELECT * FROM _timescaledb_catalog.tablespace ORDER BY id;
SELECT * FROM _timescaledb_catalog.dimension ORDER BY id;
--partitioning function changed, so don't output
SELECT id, hypertable_id, column_name, column_type, aligned, num_slices, interval_length FROM _timescaledb_catalog.dimension ORDER BY id;
SELECT * FROM _timescaledb_catalog.dimension_slice ORDER BY id;
SELECT * FROM _timescaledb_catalog.chunk ORDER BY id;
SELECT * FROM _timescaledb_catalog.chunk_constraint ORDER BY chunk_id, dimension_slice_id, constraint_name;