mirror of
https://github.com/timescale/timescaledb.git
synced 2025-05-17 11:03:36 +08:00
Avoid extra projection when scanning a compressed chunk
We don't have to project the result of the underlying scan of DecompressChunk, because the latter can selectively decompress the resulting columns anyway. The projection slows down the things especially when we use JIT, when the projection has to be compiled for each chunk. To avoid this unnecessary work, use the physical targetlist for compressed scan if we can. This commit rewrites the function that determines what we have to decompress, and makes it use the targetlist generated by the planner, instead of building it from scratch. Then we can give it the physical targetlist when possible.
This commit is contained in:
parent
a0e25d9e24
commit
c73c5a74b9
@ -491,12 +491,24 @@ ts_decompress_chunk_generate_paths(PlannerInfo *root, RelOptInfo *chunk_rel, Hyp
|
||||
compressed_rel->reloptkind = RELOPT_DEADREL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Add a var for a particular column to the reltarget. attrs_used is a bitmap
|
||||
* of which columns we already have in reltarget. We do not add the columns that
|
||||
* are already there, and update it after adding something.
|
||||
*/
|
||||
static void
|
||||
compressed_reltarget_add_var_for_column(RelOptInfo *compressed_rel, Oid compressed_relid,
|
||||
const char *column_name, Bitmapset **attrs_used)
|
||||
{
|
||||
AttrNumber attnum = get_attnum(compressed_relid, column_name);
|
||||
Assert(attnum > 0);
|
||||
|
||||
if (bms_is_member(attnum, *attrs_used))
|
||||
{
|
||||
/* This column is already in reltarget, we don't need duplicates. */
|
||||
return;
|
||||
}
|
||||
|
||||
*attrs_used = bms_add_member(*attrs_used, attnum);
|
||||
|
||||
Oid typid, collid;
|
||||
@ -518,8 +530,30 @@ compressed_rel_setup_reltarget(RelOptInfo *compressed_rel, CompressionInfo *info
|
||||
Bitmapset *attrs_used = NULL;
|
||||
|
||||
Oid compressed_relid = info->compressed_rte->relid;
|
||||
|
||||
/*
|
||||
* We have to decompress three kinds of columns:
|
||||
* 1) output targetlist of the relation,
|
||||
* 2) columns required for the quals (WHERE),
|
||||
* 3) columns required for joins.
|
||||
*/
|
||||
List *exprs = list_copy(info->chunk_rel->reltarget->exprs);
|
||||
ListCell *lc;
|
||||
foreach (lc, info->chunk_rel->reltarget->exprs)
|
||||
foreach (lc, info->chunk_rel->baserestrictinfo)
|
||||
{
|
||||
exprs = lappend(exprs, ((RestrictInfo *) lfirst(lc))->clause);
|
||||
}
|
||||
foreach (lc, info->chunk_rel->joininfo)
|
||||
{
|
||||
exprs = lappend(exprs, ((RestrictInfo *) lfirst(lc))->clause);
|
||||
}
|
||||
|
||||
/*
|
||||
* Now go over the required expressions we prepared above, and add the
|
||||
* required columns to the compressed reltarget.
|
||||
*/
|
||||
info->compressed_rel->reltarget->exprs = NIL;
|
||||
foreach (lc, exprs)
|
||||
{
|
||||
ListCell *lc2;
|
||||
List *chunk_vars = pull_var_clause(lfirst(lc), PVC_RECURSE_PLACEHOLDERS);
|
||||
@ -531,9 +565,12 @@ compressed_rel_setup_reltarget(RelOptInfo *compressed_rel, CompressionInfo *info
|
||||
|
||||
/* skip vars that aren't from the uncompressed chunk */
|
||||
if (chunk_var->varno != info->chunk_rel->relid)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
/* if there's a system column or whole-row reference, add a whole-
|
||||
/*
|
||||
* If there's a system column or whole-row reference, add a whole-
|
||||
* row reference, and we're done.
|
||||
*/
|
||||
if (chunk_var->varattno <= 0)
|
||||
|
@ -144,7 +144,11 @@ initialize_column_state(DecompressChunkState *state)
|
||||
next_compressed_scan_attno++;
|
||||
|
||||
AttrNumber output_attno = lfirst_int(lc);
|
||||
Assert(output_attno != 0);
|
||||
if (output_attno == 0)
|
||||
{
|
||||
/* We are asked not to decompress this column, skip it. */
|
||||
continue;
|
||||
}
|
||||
|
||||
DecompressChunkColumnState *column = &state->columns[state->num_columns];
|
||||
state->num_columns++;
|
||||
|
@ -14,6 +14,7 @@
|
||||
#include <nodes/nodeFuncs.h>
|
||||
#include <optimizer/optimizer.h>
|
||||
#include <optimizer/paths.h>
|
||||
#include <optimizer/plancat.h>
|
||||
#include <optimizer/restrictinfo.h>
|
||||
#include <optimizer/tlist.h>
|
||||
#include <parser/parsetree.h>
|
||||
@ -40,118 +41,10 @@ _decompress_chunk_init(void)
|
||||
TryRegisterCustomScanMethods(&decompress_chunk_plan_methods);
|
||||
}
|
||||
|
||||
static TargetEntry *
|
||||
make_compressed_scan_meta_targetentry(DecompressChunkPath *path, char *column_name, int id,
|
||||
int tle_index)
|
||||
static void
|
||||
check_for_system_columns(Bitmapset *attrs_used)
|
||||
{
|
||||
Var *scan_var;
|
||||
AttrNumber compressed_attno = get_attnum(path->info->compressed_rte->relid, column_name);
|
||||
if (compressed_attno == InvalidAttrNumber)
|
||||
elog(ERROR, "lookup failed for column \"%s\"", column_name);
|
||||
|
||||
/*
|
||||
* this is called for adding the count and sequence num column which are both int4
|
||||
* if we ever need columns with different datatype here we need to add
|
||||
* dynamic type lookup
|
||||
*/
|
||||
Assert(get_atttype(path->info->compressed_rte->relid, compressed_attno) == INT4OID);
|
||||
scan_var = makeVar(path->info->compressed_rel->relid, compressed_attno, INT4OID, -1, 0, 0);
|
||||
path->decompression_map = lappend_int(path->decompression_map, id);
|
||||
|
||||
return makeTargetEntry((Expr *) scan_var, tle_index, NULL, false);
|
||||
}
|
||||
|
||||
/*
|
||||
* Find matching column attno for compressed chunk based on hypertable attno.
|
||||
*
|
||||
* Since we dont want aliasing to interfere we lookup directly in catalog
|
||||
* instead of using RangeTblEntry.
|
||||
*/
|
||||
static AttrNumber
|
||||
get_compressed_attno(CompressionInfo *info, AttrNumber ht_attno)
|
||||
{
|
||||
AttrNumber compressed_attno;
|
||||
Assert(info->ht_rte);
|
||||
char *chunk_col = get_attname(info->ht_rte->relid, ht_attno, false);
|
||||
compressed_attno = get_attnum(info->compressed_rte->relid, chunk_col);
|
||||
|
||||
if (compressed_attno == InvalidAttrNumber)
|
||||
elog(ERROR, "no matching column in compressed chunk found");
|
||||
|
||||
return compressed_attno;
|
||||
}
|
||||
|
||||
static TargetEntry *
|
||||
make_compressed_scan_targetentry(DecompressChunkPath *path, AttrNumber ht_attno, int tle_index)
|
||||
{
|
||||
Var *scan_var;
|
||||
char *ht_attname = get_attname(path->info->ht_rte->relid, ht_attno, false);
|
||||
FormData_hypertable_compression *ht_info =
|
||||
get_column_compressioninfo(path->info->hypertable_compression_info, ht_attname);
|
||||
AttrNumber scan_varattno = get_compressed_attno(path->info, ht_attno);
|
||||
AttrNumber chunk_attno = get_attnum(path->info->chunk_rte->relid, ht_attname);
|
||||
|
||||
Assert(!get_rte_attribute_is_dropped(path->info->ht_rte, ht_attno));
|
||||
Assert(!get_rte_attribute_is_dropped(path->info->chunk_rte, chunk_attno));
|
||||
Assert(!get_rte_attribute_is_dropped(path->info->compressed_rte, scan_varattno));
|
||||
|
||||
if (ht_info->algo_id == _INVALID_COMPRESSION_ALGORITHM)
|
||||
{
|
||||
Oid typid, collid;
|
||||
int32 typmod;
|
||||
get_atttypetypmodcoll(path->info->ht_rte->relid, ht_attno, &typid, &typmod, &collid);
|
||||
scan_var =
|
||||
makeVar(path->info->compressed_rel->relid, scan_varattno, typid, typmod, collid, 0);
|
||||
}
|
||||
else
|
||||
scan_var = makeVar(path->info->compressed_rel->relid,
|
||||
scan_varattno,
|
||||
ts_custom_type_cache_get(CUSTOM_TYPE_COMPRESSED_DATA)->type_oid,
|
||||
-1,
|
||||
0,
|
||||
0);
|
||||
path->decompression_map = lappend_int(path->decompression_map, chunk_attno);
|
||||
|
||||
return makeTargetEntry((Expr *) scan_var, tle_index, NULL, false);
|
||||
}
|
||||
|
||||
/*
|
||||
* build targetlist for scan on compressed chunk
|
||||
*
|
||||
* Since we do not adjust selectedCols in RangeTblEntry for chunks
|
||||
* we use selectedCols from the hypertable RangeTblEntry to
|
||||
* build the target list for the compressed chunk and adjust
|
||||
* attno accordingly
|
||||
*/
|
||||
static List *
|
||||
build_scan_tlist(DecompressChunkPath *path)
|
||||
{
|
||||
List *scan_tlist = NIL;
|
||||
Bitmapset *attrs_used = path->info->ht_rte->selectedCols;
|
||||
TargetEntry *tle;
|
||||
int bit;
|
||||
|
||||
path->decompression_map = NIL;
|
||||
|
||||
/* add count column */
|
||||
tle = make_compressed_scan_meta_targetentry(path,
|
||||
COMPRESSION_COLUMN_METADATA_COUNT_NAME,
|
||||
DECOMPRESS_CHUNK_COUNT_ID,
|
||||
list_length(scan_tlist) + 1);
|
||||
scan_tlist = lappend(scan_tlist, tle);
|
||||
|
||||
/* add sequence num column */
|
||||
if (path->needs_sequence_num)
|
||||
{
|
||||
tle = make_compressed_scan_meta_targetentry(path,
|
||||
COMPRESSION_COLUMN_METADATA_SEQUENCE_NUM_NAME,
|
||||
DECOMPRESS_CHUNK_SEQUENCE_NUM_ID,
|
||||
list_length(scan_tlist) + 1);
|
||||
scan_tlist = lappend(scan_tlist, tle);
|
||||
}
|
||||
|
||||
/* check for system columns */
|
||||
bit = bms_next_member(attrs_used, -1);
|
||||
int bit = bms_next_member(attrs_used, -1);
|
||||
if (bit > 0 && bit + FirstLowInvalidHeapAttributeNumber < 0)
|
||||
{
|
||||
/* we support tableoid so skip that */
|
||||
@ -161,48 +54,208 @@ build_scan_tlist(DecompressChunkPath *path)
|
||||
if (bit > 0 && bit + FirstLowInvalidHeapAttributeNumber < 0)
|
||||
elog(ERROR, "transparent decompression only supports tableoid system column");
|
||||
}
|
||||
}
|
||||
|
||||
/* check for reference to whole row */
|
||||
if (bms_is_member(0 - FirstLowInvalidHeapAttributeNumber, attrs_used))
|
||||
/*
|
||||
* Given the scan targetlist and the bitmapset of the needed columns, determine
|
||||
* which scan columns become which decompressed columns (fill decompression_map).
|
||||
*/
|
||||
static void
|
||||
build_decompression_map(DecompressChunkPath *path, List *scan_tlist, Bitmapset *chunk_attrs_needed)
|
||||
{
|
||||
/*
|
||||
* Track which normal and metadata columns we were able to find in the
|
||||
* targetlist.
|
||||
*/
|
||||
bool missing_count = true;
|
||||
bool missing_sequence = path->needs_sequence_num;
|
||||
Bitmapset *chunk_attrs_found = NULL;
|
||||
|
||||
/*
|
||||
* FIXME this way to determine which columns are used is actually wrong, see
|
||||
* https://github.com/timescale/timescaledb/issues/4195#issuecomment-1104238863
|
||||
* Left as is for now, because changing it uncovers a whole new story with
|
||||
* ctid.
|
||||
*/
|
||||
check_for_system_columns(path->info->ht_rte->selectedCols);
|
||||
|
||||
/*
|
||||
* We allow tableoid system column, it won't be in the targetlist but will
|
||||
* be added at decompression time. Always mark it as found.
|
||||
*/
|
||||
if (bms_is_member(TableOidAttributeNumber - FirstLowInvalidHeapAttributeNumber,
|
||||
chunk_attrs_needed))
|
||||
{
|
||||
ListCell *lc;
|
||||
AttrNumber ht_attno = 0;
|
||||
chunk_attrs_found =
|
||||
bms_add_member(chunk_attrs_found,
|
||||
TableOidAttributeNumber - FirstLowInvalidHeapAttributeNumber);
|
||||
}
|
||||
|
||||
foreach (lc, path->info->ht_rte->eref->colnames)
|
||||
/*
|
||||
* Fill the helper array of compressed attno -> compression info.
|
||||
*/
|
||||
FormData_hypertable_compression **compressed_attno_to_compression_info =
|
||||
palloc0(sizeof(void *) * (path->info->compressed_rel->max_attr + 1));
|
||||
ListCell *lc;
|
||||
foreach (lc, path->info->hypertable_compression_info)
|
||||
{
|
||||
FormData_hypertable_compression *fd = lfirst(lc);
|
||||
AttrNumber compressed_attno =
|
||||
get_attnum(path->info->compressed_rte->relid, NameStr(fd->attname));
|
||||
|
||||
if (compressed_attno == InvalidAttrNumber)
|
||||
{
|
||||
const char *chunk_col = strVal(lfirst(lc));
|
||||
ht_attno++;
|
||||
elog(ERROR,
|
||||
"column '%s' not found in the compressed chunk '%s'",
|
||||
NameStr(fd->attname),
|
||||
get_rel_name(path->info->compressed_rte->relid));
|
||||
}
|
||||
|
||||
compressed_attno_to_compression_info[compressed_attno] = fd;
|
||||
}
|
||||
|
||||
/*
|
||||
* Go over the scan targetlist and determine to which output column each
|
||||
* scan column goes.
|
||||
*/
|
||||
path->decompression_map = NIL;
|
||||
foreach (lc, scan_tlist)
|
||||
{
|
||||
TargetEntry *target = (TargetEntry *) lfirst(lc);
|
||||
if (!IsA(target->expr, Var))
|
||||
{
|
||||
elog(ERROR, "compressed scan targetlist entries must be Vars");
|
||||
}
|
||||
|
||||
Var *var = (Var *) target->expr;
|
||||
Assert(var->varno == path->info->compressed_rel->relid);
|
||||
AttrNumber compressed_attno = var->varattno;
|
||||
|
||||
if (compressed_attno == InvalidAttrNumber)
|
||||
{
|
||||
/*
|
||||
* We shouldn't have whole-row vars in the compressed scan tlist,
|
||||
* they are going to be built by final projection of DecompressChunk
|
||||
* custom scan.
|
||||
* See compressed_rel_setup_reltarget().
|
||||
*/
|
||||
elog(ERROR, "compressed scan targetlist must not have whole-row vars");
|
||||
}
|
||||
|
||||
const char *column_name = get_attname(path->info->compressed_rte->relid,
|
||||
compressed_attno,
|
||||
/* missing_ok = */ false);
|
||||
|
||||
AttrNumber destination_attno_in_uncompressed_chunk = 0;
|
||||
FormData_hypertable_compression *compression_info =
|
||||
compressed_attno_to_compression_info[compressed_attno];
|
||||
if (compression_info)
|
||||
{
|
||||
/*
|
||||
* Normal column, not a metadata column.
|
||||
*/
|
||||
AttrNumber hypertable_attno = get_attnum(path->info->ht_rte->relid, column_name);
|
||||
AttrNumber chunk_attno = get_attnum(path->info->chunk_rte->relid, column_name);
|
||||
Assert(hypertable_attno != InvalidAttrNumber);
|
||||
Assert(chunk_attno != InvalidAttrNumber);
|
||||
|
||||
/*
|
||||
* dropped columns have empty string
|
||||
* The versions older than this commit didn't set up the proper
|
||||
* collation and typmod for segmentby columns in compressed chunks,
|
||||
* so we have to determine them from the main hypertable.
|
||||
* Additionally, we have to set the proper type for the compressed
|
||||
* columns. It would be cool to get rid of this code someday and
|
||||
* just use the types from the compressed chunk, but the problem is
|
||||
* that we have to support the chunks created by the older versions
|
||||
* of TimescaleDB.
|
||||
*/
|
||||
if (IsA(lfirst(lc), String) && strlen(chunk_col) > 0)
|
||||
if (compression_info->algo_id == _INVALID_COMPRESSION_ALGORITHM)
|
||||
{
|
||||
tle = make_compressed_scan_targetentry(path, ht_attno, list_length(scan_tlist) + 1);
|
||||
scan_tlist = lappend(scan_tlist, tle);
|
||||
get_atttypetypmodcoll(path->info->ht_rte->relid,
|
||||
hypertable_attno,
|
||||
&var->vartype,
|
||||
&var->vartypmod,
|
||||
&var->varcollid);
|
||||
}
|
||||
|
||||
if (bms_is_member(0 - FirstLowInvalidHeapAttributeNumber, chunk_attrs_needed))
|
||||
{
|
||||
/*
|
||||
* attno = 0 means whole-row var. Output all the columns.
|
||||
*/
|
||||
destination_attno_in_uncompressed_chunk = chunk_attno;
|
||||
chunk_attrs_found =
|
||||
bms_add_member(chunk_attrs_found,
|
||||
chunk_attno - FirstLowInvalidHeapAttributeNumber);
|
||||
}
|
||||
else if (bms_is_member(chunk_attno - FirstLowInvalidHeapAttributeNumber,
|
||||
chunk_attrs_needed))
|
||||
{
|
||||
destination_attno_in_uncompressed_chunk = chunk_attno;
|
||||
chunk_attrs_found =
|
||||
bms_add_member(chunk_attrs_found,
|
||||
chunk_attno - FirstLowInvalidHeapAttributeNumber);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
* we only need to find unique varattno references here
|
||||
* multiple references to the same column will be handled by projection
|
||||
* we need to include junk columns because they might be needed for
|
||||
* filtering or sorting
|
||||
*/
|
||||
for (bit = bms_next_member(attrs_used, 0 - FirstLowInvalidHeapAttributeNumber); bit > 0;
|
||||
bit = bms_next_member(attrs_used, bit))
|
||||
else
|
||||
{
|
||||
/* bits are offset by FirstLowInvalidHeapAttributeNumber */
|
||||
AttrNumber ht_attno = bit + FirstLowInvalidHeapAttributeNumber;
|
||||
/*
|
||||
* Metadata column.
|
||||
* We always need count column, and sometimes a sequence number
|
||||
* column. We don't output them, but use them for decompression,
|
||||
* hence the special negative destination attnos.
|
||||
* The min/max metadata columns are normally not required for output
|
||||
* or decompression, they are used only as filter for the compressed
|
||||
* scan, so we skip them here.
|
||||
*/
|
||||
Assert(strncmp(column_name,
|
||||
COMPRESSION_COLUMN_METADATA_PREFIX,
|
||||
strlen(COMPRESSION_COLUMN_METADATA_PREFIX)) == 0);
|
||||
|
||||
tle = make_compressed_scan_targetentry(path, ht_attno, list_length(scan_tlist) + 1);
|
||||
scan_tlist = lappend(scan_tlist, tle);
|
||||
if (strcmp(column_name, COMPRESSION_COLUMN_METADATA_COUNT_NAME) == 0)
|
||||
{
|
||||
destination_attno_in_uncompressed_chunk = DECOMPRESS_CHUNK_COUNT_ID;
|
||||
missing_count = false;
|
||||
}
|
||||
else if (path->needs_sequence_num &&
|
||||
strcmp(column_name, COMPRESSION_COLUMN_METADATA_SEQUENCE_NUM_NAME) == 0)
|
||||
{
|
||||
destination_attno_in_uncompressed_chunk = DECOMPRESS_CHUNK_SEQUENCE_NUM_ID;
|
||||
missing_sequence = false;
|
||||
}
|
||||
}
|
||||
|
||||
path->decompression_map =
|
||||
lappend_int(path->decompression_map, destination_attno_in_uncompressed_chunk);
|
||||
}
|
||||
|
||||
return scan_tlist;
|
||||
/*
|
||||
* Check that we have found all the needed columns in the scan targetlist.
|
||||
* We can't conveniently check that we have all columns for all-row vars, so
|
||||
* skip attno 0 in this check.
|
||||
*/
|
||||
Bitmapset *attrs_not_found = bms_difference(chunk_attrs_needed, chunk_attrs_found);
|
||||
int bit = bms_next_member(attrs_not_found, 0 - FirstLowInvalidHeapAttributeNumber);
|
||||
if (bit >= 0)
|
||||
{
|
||||
elog(ERROR,
|
||||
"column '%s' (%d) not found in the scan targetlist for compressed chunk '%s'",
|
||||
get_attname(path->info->chunk_rte->relid,
|
||||
bit + FirstLowInvalidHeapAttributeNumber,
|
||||
/* missing_ok = */ true),
|
||||
bit + FirstLowInvalidHeapAttributeNumber,
|
||||
get_rel_name(path->info->compressed_rte->relid));
|
||||
}
|
||||
|
||||
if (missing_count)
|
||||
{
|
||||
elog(ERROR, "the count column was not found in the compressed scan targetlist");
|
||||
}
|
||||
|
||||
if (missing_sequence)
|
||||
{
|
||||
elog(ERROR, "the sequence column was not found in the compressed scan targetlist");
|
||||
}
|
||||
}
|
||||
|
||||
/* replace vars that reference the compressed table with ones that reference the
|
||||
@ -280,11 +333,11 @@ clause_has_compressed_attrs(Node *node, void *context)
|
||||
}
|
||||
|
||||
Plan *
|
||||
decompress_chunk_plan_create(PlannerInfo *root, RelOptInfo *rel, CustomPath *path, List *tlist,
|
||||
List *clauses, List *custom_plans)
|
||||
decompress_chunk_plan_create(PlannerInfo *root, RelOptInfo *rel, CustomPath *path,
|
||||
List *decompressed_tlist, List *clauses, List *custom_plans)
|
||||
{
|
||||
DecompressChunkPath *dcpath = (DecompressChunkPath *) path;
|
||||
CustomScan *cscan = makeNode(CustomScan);
|
||||
CustomScan *decompress_plan = makeNode(CustomScan);
|
||||
Scan *compressed_scan = linitial(custom_plans);
|
||||
Path *compressed_path = linitial(path->custom_paths);
|
||||
List *settings;
|
||||
@ -293,14 +346,14 @@ decompress_chunk_plan_create(PlannerInfo *root, RelOptInfo *rel, CustomPath *pat
|
||||
Assert(list_length(custom_plans) == 1);
|
||||
Assert(list_length(path->custom_paths) == 1);
|
||||
|
||||
cscan->flags = path->flags;
|
||||
cscan->methods = &decompress_chunk_plan_methods;
|
||||
cscan->scan.scanrelid = dcpath->info->chunk_rel->relid;
|
||||
decompress_plan->flags = path->flags;
|
||||
decompress_plan->methods = &decompress_chunk_plan_methods;
|
||||
decompress_plan->scan.scanrelid = dcpath->info->chunk_rel->relid;
|
||||
|
||||
/* output target list */
|
||||
cscan->scan.plan.targetlist = tlist;
|
||||
decompress_plan->scan.plan.targetlist = decompressed_tlist;
|
||||
/* input target list */
|
||||
cscan->custom_scan_tlist = NIL;
|
||||
decompress_plan->custom_scan_tlist = NIL;
|
||||
|
||||
if (IsA(compressed_path, IndexPath))
|
||||
{
|
||||
@ -313,7 +366,8 @@ decompress_chunk_plan_create(PlannerInfo *root, RelOptInfo *rel, CustomPath *pat
|
||||
RestrictInfo *rinfo = lfirst_node(RestrictInfo, lc);
|
||||
if (is_redundant_derived_clause(rinfo, ipath->indexclauses))
|
||||
continue; /* dup or derived from same EquivalenceClass */
|
||||
cscan->scan.plan.qual = lappend(cscan->scan.plan.qual, rinfo->clause);
|
||||
decompress_plan->scan.plan.qual =
|
||||
lappend(decompress_plan->scan.plan.qual, rinfo->clause);
|
||||
}
|
||||
/* joininfo clauses on the compressed chunk rel have to
|
||||
* contain clauses on both compressed and
|
||||
@ -322,7 +376,7 @@ decompress_chunk_plan_create(PlannerInfo *root, RelOptInfo *rel, CustomPath *pat
|
||||
* handle compressed attributes, so remove them from the
|
||||
* indexscans here. (these are included in the `clauses` passed in
|
||||
* to the function and so were added as filters
|
||||
* for cscan->scan.plan.qual in the loop above. )
|
||||
* for decompress_plan->scan.plan.qual in the loop above. )
|
||||
*/
|
||||
indexplan = linitial(custom_plans);
|
||||
Assert(IsA(indexplan, IndexScan) || IsA(indexplan, IndexOnlyScan));
|
||||
@ -348,7 +402,8 @@ decompress_chunk_plan_create(PlannerInfo *root, RelOptInfo *rel, CustomPath *pat
|
||||
foreach (lc, clauses)
|
||||
{
|
||||
RestrictInfo *rinfo = lfirst_node(RestrictInfo, lc);
|
||||
cscan->scan.plan.qual = lappend(cscan->scan.plan.qual, rinfo->clause);
|
||||
decompress_plan->scan.plan.qual =
|
||||
lappend(decompress_plan->scan.plan.qual, rinfo->clause);
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -356,25 +411,72 @@ decompress_chunk_plan_create(PlannerInfo *root, RelOptInfo *rel, CustomPath *pat
|
||||
foreach (lc, clauses)
|
||||
{
|
||||
RestrictInfo *rinfo = lfirst_node(RestrictInfo, lc);
|
||||
cscan->scan.plan.qual = lappend(cscan->scan.plan.qual, rinfo->clause);
|
||||
decompress_plan->scan.plan.qual =
|
||||
lappend(decompress_plan->scan.plan.qual, rinfo->clause);
|
||||
}
|
||||
}
|
||||
|
||||
cscan->scan.plan.qual =
|
||||
(List *) replace_compressed_vars((Node *) cscan->scan.plan.qual, dcpath->info);
|
||||
decompress_plan->scan.plan.qual =
|
||||
(List *) replace_compressed_vars((Node *) decompress_plan->scan.plan.qual, dcpath->info);
|
||||
|
||||
compressed_scan->plan.targetlist = build_scan_tlist(dcpath);
|
||||
/*
|
||||
* Try to use a physical tlist if possible. There's no reason to do the
|
||||
* extra work of projecting the result of compressed chunk scan, because
|
||||
* DecompressChunk can choose only the needed columns itself.
|
||||
* Note that Postgres uses the CP_EXACT_TLIST option when planning the child
|
||||
* paths of the Custom path, so we won't automatically get a phsyical tlist
|
||||
* here.
|
||||
*/
|
||||
if (compressed_path->pathtype == T_IndexOnlyScan)
|
||||
{
|
||||
compressed_scan->plan.targetlist = ((IndexPath *) compressed_path)->indexinfo->indextlist;
|
||||
}
|
||||
else
|
||||
{
|
||||
List *physical_tlist = build_physical_tlist(root, dcpath->info->compressed_rel);
|
||||
/* Can be null if the relation has dropped columns. */
|
||||
if (physical_tlist)
|
||||
{
|
||||
compressed_scan->plan.targetlist = physical_tlist;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Determine which columns we have to decompress.
|
||||
* decompressed_tlist is sometimes empty, e.g. for a direct select from
|
||||
* chunk. We have a ProjectionPath above DecompressChunk in this case, and
|
||||
* the targetlist for this path is not built by the planner
|
||||
* (CP_IGNORE_TLIST). This is why we have to examine rel pathtarget.
|
||||
* Looking at the targetlist is not enough, we also have to decompress the
|
||||
* columns participating in quals and in pathkeys.
|
||||
*/
|
||||
Bitmapset *chunk_attrs_needed = NULL;
|
||||
pull_varattnos((Node *) decompress_plan->scan.plan.qual,
|
||||
dcpath->info->chunk_rel->relid,
|
||||
&chunk_attrs_needed);
|
||||
pull_varattnos((Node *) dcpath->cpath.path.pathtarget->exprs,
|
||||
dcpath->info->chunk_rel->relid,
|
||||
&chunk_attrs_needed);
|
||||
|
||||
/*
|
||||
* Determine which compressed colum goes to which output column.
|
||||
*/
|
||||
build_decompression_map(dcpath, compressed_scan->plan.targetlist, chunk_attrs_needed);
|
||||
|
||||
/*
|
||||
* Add a sort if the compressed scan is not ordered appropriately.
|
||||
*/
|
||||
if (!pathkeys_contained_in(dcpath->compressed_pathkeys, compressed_path->pathkeys))
|
||||
{
|
||||
List *compressed_pks = dcpath->compressed_pathkeys;
|
||||
Sort *sort = ts_make_sort_from_pathkeys((Plan *) compressed_scan,
|
||||
compressed_pks,
|
||||
bms_make_singleton(compressed_scan->scanrelid));
|
||||
cscan->custom_plans = list_make1(sort);
|
||||
decompress_plan->custom_plans = list_make1(sort);
|
||||
}
|
||||
else
|
||||
{
|
||||
cscan->custom_plans = custom_plans;
|
||||
decompress_plan->custom_plans = custom_plans;
|
||||
}
|
||||
|
||||
Assert(list_length(custom_plans) == 1);
|
||||
@ -382,7 +484,7 @@ decompress_chunk_plan_create(PlannerInfo *root, RelOptInfo *rel, CustomPath *pat
|
||||
settings = list_make3_int(dcpath->info->hypertable_id,
|
||||
dcpath->info->chunk_rte->relid,
|
||||
dcpath->reverse);
|
||||
cscan->custom_private = list_make2(settings, dcpath->decompression_map);
|
||||
decompress_plan->custom_private = list_make2(settings, dcpath->decompression_map);
|
||||
|
||||
return &cscan->scan.plan;
|
||||
return &decompress_plan->scan.plan;
|
||||
}
|
||||
|
@ -35,12 +35,12 @@ explain (costs off, verbose)
|
||||
SELECT
|
||||
FROM hyper
|
||||
WHERE time > 2::bigint and time < 4;
|
||||
QUERY PLAN
|
||||
-----------------------------------------------------------------------------------------------------------------------------
|
||||
QUERY PLAN
|
||||
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_1_chunk
|
||||
Filter: ((_hyper_1_1_chunk."time" > '2'::bigint) AND (_hyper_1_1_chunk."time" < 4))
|
||||
-> Seq Scan on _timescaledb_internal.compress_hyper_2_3_chunk
|
||||
Output: compress_hyper_2_3_chunk._ts_meta_count, compress_hyper_2_3_chunk."time"
|
||||
Output: compress_hyper_2_3_chunk."time", compress_hyper_2_3_chunk.device_id, compress_hyper_2_3_chunk.val, compress_hyper_2_3_chunk._ts_meta_count, compress_hyper_2_3_chunk._ts_meta_sequence_num, compress_hyper_2_3_chunk._ts_meta_min_1, compress_hyper_2_3_chunk._ts_meta_max_1
|
||||
Filter: ((compress_hyper_2_3_chunk._ts_meta_max_1 > '2'::bigint) AND (compress_hyper_2_3_chunk._ts_meta_min_1 < 4))
|
||||
(5 rows)
|
||||
|
||||
@ -48,12 +48,12 @@ explain (costs off, verbose)
|
||||
SELECT
|
||||
FROM hyper
|
||||
WHERE time = 3::bigint;
|
||||
QUERY PLAN
|
||||
-----------------------------------------------------------------------------------------------------------------------------------------
|
||||
QUERY PLAN
|
||||
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_1_chunk
|
||||
Filter: (_hyper_1_1_chunk."time" = '3'::bigint)
|
||||
-> Seq Scan on _timescaledb_internal.compress_hyper_2_3_chunk
|
||||
Output: compress_hyper_2_3_chunk._ts_meta_count, compress_hyper_2_3_chunk."time"
|
||||
Output: compress_hyper_2_3_chunk."time", compress_hyper_2_3_chunk.device_id, compress_hyper_2_3_chunk.val, compress_hyper_2_3_chunk._ts_meta_count, compress_hyper_2_3_chunk._ts_meta_sequence_num, compress_hyper_2_3_chunk._ts_meta_min_1, compress_hyper_2_3_chunk._ts_meta_max_1
|
||||
Filter: ((compress_hyper_2_3_chunk._ts_meta_min_1 <= '3'::bigint) AND (compress_hyper_2_3_chunk._ts_meta_max_1 >= '3'::bigint))
|
||||
(5 rows)
|
||||
|
||||
@ -122,8 +122,8 @@ from metaseg_tab
|
||||
where fmid = 56
|
||||
and end_dt between '2012-12-10'::date and '2012-12-11'::date
|
||||
order by factorid, end_dt;
|
||||
QUERY PLAN
|
||||
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
QUERY PLAN
|
||||
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
Sort
|
||||
Output: _hyper_3_4_chunk.factorid, _hyper_3_4_chunk.end_dt, _hyper_3_4_chunk.logret
|
||||
Sort Key: _hyper_3_4_chunk.factorid, _hyper_3_4_chunk.end_dt
|
||||
@ -131,7 +131,7 @@ order by factorid, end_dt;
|
||||
Output: _hyper_3_4_chunk.factorid, _hyper_3_4_chunk.end_dt, _hyper_3_4_chunk.logret
|
||||
Filter: ((_hyper_3_4_chunk.end_dt >= '12-10-2012'::date) AND (_hyper_3_4_chunk.end_dt <= '12-11-2012'::date) AND (_hyper_3_4_chunk.fmid = 56))
|
||||
-> Seq Scan on _timescaledb_internal.compress_hyper_4_5_chunk
|
||||
Output: compress_hyper_4_5_chunk._ts_meta_count, compress_hyper_4_5_chunk.fmid, compress_hyper_4_5_chunk.factorid, compress_hyper_4_5_chunk.end_dt, compress_hyper_4_5_chunk.logret
|
||||
Output: compress_hyper_4_5_chunk.fmid, compress_hyper_4_5_chunk.factorid, compress_hyper_4_5_chunk.start_dt, compress_hyper_4_5_chunk.end_dt, compress_hyper_4_5_chunk.interval_number, compress_hyper_4_5_chunk.logret, compress_hyper_4_5_chunk.knowledge_date, compress_hyper_4_5_chunk._ts_meta_count, compress_hyper_4_5_chunk._ts_meta_sequence_num, compress_hyper_4_5_chunk._ts_meta_min_1, compress_hyper_4_5_chunk._ts_meta_max_1
|
||||
Filter: ((compress_hyper_4_5_chunk._ts_meta_max_1 >= '12-10-2012'::date) AND (compress_hyper_4_5_chunk._ts_meta_min_1 <= '12-11-2012'::date))
|
||||
(9 rows)
|
||||
|
||||
@ -152,8 +152,8 @@ from metaseg_tab
|
||||
where fmid = 56
|
||||
and end_dt::date between '2012-12-10'::timestamp and '2012-12-11'::date
|
||||
order by factorid, end_dt;
|
||||
QUERY PLAN
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
QUERY PLAN
|
||||
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
Sort
|
||||
Output: _hyper_3_4_chunk.factorid, _hyper_3_4_chunk.end_dt, _hyper_3_4_chunk.logret
|
||||
Sort Key: _hyper_3_4_chunk.factorid, _hyper_3_4_chunk.end_dt
|
||||
@ -161,7 +161,7 @@ order by factorid, end_dt;
|
||||
Output: _hyper_3_4_chunk.factorid, _hyper_3_4_chunk.end_dt, _hyper_3_4_chunk.logret
|
||||
Filter: ((_hyper_3_4_chunk.fmid = 56) AND ((_hyper_3_4_chunk.end_dt)::date >= 'Mon Dec 10 00:00:00 2012'::timestamp without time zone) AND ((_hyper_3_4_chunk.end_dt)::date <= '12-11-2012'::date))
|
||||
-> Seq Scan on _timescaledb_internal.compress_hyper_4_5_chunk
|
||||
Output: compress_hyper_4_5_chunk._ts_meta_count, compress_hyper_4_5_chunk.fmid, compress_hyper_4_5_chunk.factorid, compress_hyper_4_5_chunk.end_dt, compress_hyper_4_5_chunk.logret
|
||||
Output: compress_hyper_4_5_chunk.fmid, compress_hyper_4_5_chunk.factorid, compress_hyper_4_5_chunk.start_dt, compress_hyper_4_5_chunk.end_dt, compress_hyper_4_5_chunk.interval_number, compress_hyper_4_5_chunk.logret, compress_hyper_4_5_chunk.knowledge_date, compress_hyper_4_5_chunk._ts_meta_count, compress_hyper_4_5_chunk._ts_meta_sequence_num, compress_hyper_4_5_chunk._ts_meta_min_1, compress_hyper_4_5_chunk._ts_meta_max_1
|
||||
(8 rows)
|
||||
|
||||
--should fail
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -8,14 +8,14 @@ SELECT show_chunks('metrics_compressed') AS "TEST_TABLE" ORDER BY 1::text LIMIT
|
||||
-- this should use DecompressChunk node
|
||||
:PREFIX_VERBOSE
|
||||
SELECT * FROM :TEST_TABLE WHERE device_id = 1 ORDER BY time LIMIT 5;
|
||||
QUERY PLAN
|
||||
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
QUERY PLAN
|
||||
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
Limit (actual rows=5 loops=1)
|
||||
Output: _hyper_X_X_chunk."time", _hyper_X_X_chunk.device_id, _hyper_X_X_chunk.v0, _hyper_X_X_chunk.v1, _hyper_X_X_chunk.v2, _hyper_X_X_chunk.v3
|
||||
-> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_X_X_chunk (actual rows=5 loops=1)
|
||||
Output: _hyper_X_X_chunk."time", _hyper_X_X_chunk.device_id, _hyper_X_X_chunk.v0, _hyper_X_X_chunk.v1, _hyper_X_X_chunk.v2, _hyper_X_X_chunk.v3
|
||||
-> Index Scan Backward using compress_hyper_X_X_chunk__compressed_hypertable_4_device_id__t on _timescaledb_internal.compress_hyper_X_X_chunk (actual rows=1 loops=1)
|
||||
Output: compress_hyper_X_X_chunk._ts_meta_count, compress_hyper_X_X_chunk._ts_meta_sequence_num, compress_hyper_X_X_chunk."time", compress_hyper_X_X_chunk.device_id, compress_hyper_X_X_chunk.v0, compress_hyper_X_X_chunk.v1, compress_hyper_X_X_chunk.v2, compress_hyper_X_X_chunk.v3
|
||||
Output: compress_hyper_X_X_chunk."time", compress_hyper_X_X_chunk.device_id, compress_hyper_X_X_chunk.v0, compress_hyper_X_X_chunk.v1, compress_hyper_X_X_chunk.v2, compress_hyper_X_X_chunk.v3, compress_hyper_X_X_chunk._ts_meta_count, compress_hyper_X_X_chunk._ts_meta_sequence_num, compress_hyper_X_X_chunk._ts_meta_min_1, compress_hyper_X_X_chunk._ts_meta_max_1
|
||||
Index Cond: (compress_hyper_X_X_chunk.device_id = 1)
|
||||
(7 rows)
|
||||
|
||||
@ -121,8 +121,8 @@ ORDER BY time, device_id;
|
||||
--
|
||||
-- v3 is not segment by or order by column so should not be pushed down
|
||||
:PREFIX_VERBOSE SELECT * FROM :TEST_TABLE WHERE v3 > 10.0 ORDER BY time, device_id;
|
||||
QUERY PLAN
|
||||
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
QUERY PLAN
|
||||
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
Sort (actual rows=0 loops=1)
|
||||
Output: _hyper_X_X_chunk."time", _hyper_X_X_chunk.device_id, _hyper_X_X_chunk.v0, _hyper_X_X_chunk.v1, _hyper_X_X_chunk.v2, _hyper_X_X_chunk.v3
|
||||
Sort Key: _hyper_X_X_chunk."time", _hyper_X_X_chunk.device_id
|
||||
@ -132,7 +132,7 @@ ORDER BY time, device_id;
|
||||
Filter: (_hyper_X_X_chunk.v3 > '10'::double precision)
|
||||
Rows Removed by Filter: 17990
|
||||
-> Seq Scan on _timescaledb_internal.compress_hyper_X_X_chunk (actual rows=20 loops=1)
|
||||
Output: compress_hyper_X_X_chunk._ts_meta_count, compress_hyper_X_X_chunk."time", compress_hyper_X_X_chunk.device_id, compress_hyper_X_X_chunk.v0, compress_hyper_X_X_chunk.v1, compress_hyper_X_X_chunk.v2, compress_hyper_X_X_chunk.v3
|
||||
Output: compress_hyper_X_X_chunk."time", compress_hyper_X_X_chunk.device_id, compress_hyper_X_X_chunk.v0, compress_hyper_X_X_chunk.v1, compress_hyper_X_X_chunk.v2, compress_hyper_X_X_chunk.v3, compress_hyper_X_X_chunk._ts_meta_count, compress_hyper_X_X_chunk._ts_meta_sequence_num, compress_hyper_X_X_chunk._ts_meta_min_1, compress_hyper_X_X_chunk._ts_meta_max_1
|
||||
(10 rows)
|
||||
|
||||
-- device_id constraint should be pushed down
|
||||
@ -404,8 +404,8 @@ ORDER BY time, device_id;
|
||||
|
||||
--pushdown of quals on order by and segment by cols anded together
|
||||
:PREFIX_VERBOSE SELECT * FROM :TEST_TABLE WHERE time > '2000-01-01 1:00:00+0' AND device_id = 1 ORDER BY time, device_id LIMIT 10;
|
||||
QUERY PLAN
|
||||
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
QUERY PLAN
|
||||
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
Limit (actual rows=10 loops=1)
|
||||
Output: _hyper_X_X_chunk."time", _hyper_X_X_chunk.device_id, _hyper_X_X_chunk.v0, _hyper_X_X_chunk.v1, _hyper_X_X_chunk.v2, _hyper_X_X_chunk.v3
|
||||
-> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_X_X_chunk (actual rows=10 loops=1)
|
||||
@ -413,7 +413,7 @@ ORDER BY time, device_id;
|
||||
Filter: (_hyper_X_X_chunk."time" > 'Fri Dec 31 17:00:00 1999 PST'::timestamp with time zone)
|
||||
Rows Removed by Filter: 31
|
||||
-> Index Scan Backward using compress_hyper_X_X_chunk__compressed_hypertable_4_device_id__t on _timescaledb_internal.compress_hyper_X_X_chunk (actual rows=1 loops=1)
|
||||
Output: compress_hyper_X_X_chunk._ts_meta_count, compress_hyper_X_X_chunk._ts_meta_sequence_num, compress_hyper_X_X_chunk."time", compress_hyper_X_X_chunk.device_id, compress_hyper_X_X_chunk.v0, compress_hyper_X_X_chunk.v1, compress_hyper_X_X_chunk.v2, compress_hyper_X_X_chunk.v3
|
||||
Output: compress_hyper_X_X_chunk."time", compress_hyper_X_X_chunk.device_id, compress_hyper_X_X_chunk.v0, compress_hyper_X_X_chunk.v1, compress_hyper_X_X_chunk.v2, compress_hyper_X_X_chunk.v3, compress_hyper_X_X_chunk._ts_meta_count, compress_hyper_X_X_chunk._ts_meta_sequence_num, compress_hyper_X_X_chunk._ts_meta_min_1, compress_hyper_X_X_chunk._ts_meta_max_1
|
||||
Index Cond: (compress_hyper_X_X_chunk.device_id = 1)
|
||||
Filter: (compress_hyper_X_X_chunk._ts_meta_max_1 > 'Fri Dec 31 17:00:00 1999 PST'::timestamp with time zone)
|
||||
(10 rows)
|
||||
@ -557,56 +557,56 @@ SELECT * FROM q1 INNER JOIN q2 ON q1.time = q2.time ORDER BY q1.time;
|
||||
SET enable_seqscan TO FALSE;
|
||||
-- IndexScans should work
|
||||
:PREFIX_VERBOSE SELECT time, device_id FROM :TEST_TABLE WHERE device_id = 1 ORDER BY device_id, time;
|
||||
QUERY PLAN
|
||||
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
QUERY PLAN
|
||||
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_X_X_chunk (actual rows=3598 loops=1)
|
||||
Output: _hyper_X_X_chunk."time", _hyper_X_X_chunk.device_id
|
||||
-> Index Scan Backward using compress_hyper_X_X_chunk__compressed_hypertable_4_device_id__t on _timescaledb_internal.compress_hyper_X_X_chunk (actual rows=4 loops=1)
|
||||
Output: compress_hyper_X_X_chunk._ts_meta_count, compress_hyper_X_X_chunk._ts_meta_sequence_num, compress_hyper_X_X_chunk."time", compress_hyper_X_X_chunk.device_id
|
||||
Output: compress_hyper_X_X_chunk."time", compress_hyper_X_X_chunk.device_id, compress_hyper_X_X_chunk.v0, compress_hyper_X_X_chunk.v1, compress_hyper_X_X_chunk.v2, compress_hyper_X_X_chunk.v3, compress_hyper_X_X_chunk._ts_meta_count, compress_hyper_X_X_chunk._ts_meta_sequence_num, compress_hyper_X_X_chunk._ts_meta_min_1, compress_hyper_X_X_chunk._ts_meta_max_1
|
||||
Index Cond: (compress_hyper_X_X_chunk.device_id = 1)
|
||||
(5 rows)
|
||||
|
||||
-- globs should not plan IndexOnlyScans
|
||||
:PREFIX_VERBOSE SELECT * FROM :TEST_TABLE WHERE device_id = 1 ORDER BY device_id, time;
|
||||
QUERY PLAN
|
||||
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
QUERY PLAN
|
||||
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_X_X_chunk (actual rows=3598 loops=1)
|
||||
Output: _hyper_X_X_chunk."time", _hyper_X_X_chunk.device_id, _hyper_X_X_chunk.v0, _hyper_X_X_chunk.v1, _hyper_X_X_chunk.v2, _hyper_X_X_chunk.v3
|
||||
-> Index Scan Backward using compress_hyper_X_X_chunk__compressed_hypertable_4_device_id__t on _timescaledb_internal.compress_hyper_X_X_chunk (actual rows=4 loops=1)
|
||||
Output: compress_hyper_X_X_chunk._ts_meta_count, compress_hyper_X_X_chunk._ts_meta_sequence_num, compress_hyper_X_X_chunk."time", compress_hyper_X_X_chunk.device_id, compress_hyper_X_X_chunk.v0, compress_hyper_X_X_chunk.v1, compress_hyper_X_X_chunk.v2, compress_hyper_X_X_chunk.v3
|
||||
Output: compress_hyper_X_X_chunk."time", compress_hyper_X_X_chunk.device_id, compress_hyper_X_X_chunk.v0, compress_hyper_X_X_chunk.v1, compress_hyper_X_X_chunk.v2, compress_hyper_X_X_chunk.v3, compress_hyper_X_X_chunk._ts_meta_count, compress_hyper_X_X_chunk._ts_meta_sequence_num, compress_hyper_X_X_chunk._ts_meta_min_1, compress_hyper_X_X_chunk._ts_meta_max_1
|
||||
Index Cond: (compress_hyper_X_X_chunk.device_id = 1)
|
||||
(5 rows)
|
||||
|
||||
-- whole row reference should work
|
||||
:PREFIX_VERBOSE SELECT test_table FROM :TEST_TABLE AS test_table WHERE device_id = 1 ORDER BY device_id, time;
|
||||
QUERY PLAN
|
||||
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
QUERY PLAN
|
||||
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_X_X_chunk test_table (actual rows=3598 loops=1)
|
||||
Output: test_table.*, test_table.device_id, test_table."time"
|
||||
-> Index Scan Backward using compress_hyper_X_X_chunk__compressed_hypertable_4_device_id__t on _timescaledb_internal.compress_hyper_X_X_chunk (actual rows=4 loops=1)
|
||||
Output: compress_hyper_X_X_chunk._ts_meta_count, compress_hyper_X_X_chunk._ts_meta_sequence_num, compress_hyper_X_X_chunk."time", compress_hyper_X_X_chunk.device_id, compress_hyper_X_X_chunk.v0, compress_hyper_X_X_chunk.v1, compress_hyper_X_X_chunk.v2, compress_hyper_X_X_chunk.v3
|
||||
Output: compress_hyper_X_X_chunk."time", compress_hyper_X_X_chunk.device_id, compress_hyper_X_X_chunk.v0, compress_hyper_X_X_chunk.v1, compress_hyper_X_X_chunk.v2, compress_hyper_X_X_chunk.v3, compress_hyper_X_X_chunk._ts_meta_count, compress_hyper_X_X_chunk._ts_meta_sequence_num, compress_hyper_X_X_chunk._ts_meta_min_1, compress_hyper_X_X_chunk._ts_meta_max_1
|
||||
Index Cond: (compress_hyper_X_X_chunk.device_id = 1)
|
||||
(5 rows)
|
||||
|
||||
-- even when we select only a segmentby column, we still need count
|
||||
:PREFIX_VERBOSE SELECT device_id FROM :TEST_TABLE WHERE device_id = 1 ORDER BY device_id;
|
||||
QUERY PLAN
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
QUERY PLAN
|
||||
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_X_X_chunk (actual rows=3598 loops=1)
|
||||
Output: _hyper_X_X_chunk.device_id
|
||||
-> Index Scan using compress_hyper_X_X_chunk__compressed_hypertable_4_device_id__t on _timescaledb_internal.compress_hyper_X_X_chunk (actual rows=4 loops=1)
|
||||
Output: compress_hyper_X_X_chunk._ts_meta_count, compress_hyper_X_X_chunk.device_id
|
||||
Output: compress_hyper_X_X_chunk."time", compress_hyper_X_X_chunk.device_id, compress_hyper_X_X_chunk.v0, compress_hyper_X_X_chunk.v1, compress_hyper_X_X_chunk.v2, compress_hyper_X_X_chunk.v3, compress_hyper_X_X_chunk._ts_meta_count, compress_hyper_X_X_chunk._ts_meta_sequence_num, compress_hyper_X_X_chunk._ts_meta_min_1, compress_hyper_X_X_chunk._ts_meta_max_1
|
||||
Index Cond: (compress_hyper_X_X_chunk.device_id = 1)
|
||||
(5 rows)
|
||||
|
||||
:PREFIX_VERBOSE SELECT count(*) FROM :TEST_TABLE WHERE device_id = 1;
|
||||
QUERY PLAN
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
QUERY PLAN
|
||||
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
Aggregate (actual rows=1 loops=1)
|
||||
Output: count(*)
|
||||
-> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_X_X_chunk (actual rows=3598 loops=1)
|
||||
-> Index Scan using compress_hyper_X_X_chunk__compressed_hypertable_4_device_id__t on _timescaledb_internal.compress_hyper_X_X_chunk (actual rows=4 loops=1)
|
||||
Output: compress_hyper_X_X_chunk._ts_meta_count, compress_hyper_X_X_chunk.device_id
|
||||
Output: compress_hyper_X_X_chunk."time", compress_hyper_X_X_chunk.device_id, compress_hyper_X_X_chunk.v0, compress_hyper_X_X_chunk.v1, compress_hyper_X_X_chunk.v2, compress_hyper_X_X_chunk.v3, compress_hyper_X_X_chunk._ts_meta_count, compress_hyper_X_X_chunk._ts_meta_sequence_num, compress_hyper_X_X_chunk._ts_meta_min_1, compress_hyper_X_X_chunk._ts_meta_max_1
|
||||
Index Cond: (compress_hyper_X_X_chunk.device_id = 1)
|
||||
(6 rows)
|
||||
|
||||
@ -614,19 +614,19 @@ SET enable_seqscan TO FALSE;
|
||||
SET enable_seqscan TO TRUE;
|
||||
SET enable_hashjoin TO FALSE;
|
||||
:PREFIX_VERBOSE SELECT device_id FROM :TEST_TABLE WHERE device_id IN ( VALUES (1));
|
||||
QUERY PLAN
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
QUERY PLAN
|
||||
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_X_X_chunk (actual rows=3598 loops=1)
|
||||
Output: _hyper_X_X_chunk.device_id
|
||||
-> Index Scan using compress_hyper_X_X_chunk__compressed_hypertable_4_device_id__t on _timescaledb_internal.compress_hyper_X_X_chunk (actual rows=4 loops=1)
|
||||
Output: compress_hyper_X_X_chunk._ts_meta_count, compress_hyper_X_X_chunk.device_id
|
||||
Output: compress_hyper_X_X_chunk."time", compress_hyper_X_X_chunk.device_id, compress_hyper_X_X_chunk.v0, compress_hyper_X_X_chunk.v1, compress_hyper_X_X_chunk.v2, compress_hyper_X_X_chunk.v3, compress_hyper_X_X_chunk._ts_meta_count, compress_hyper_X_X_chunk._ts_meta_sequence_num, compress_hyper_X_X_chunk._ts_meta_min_1, compress_hyper_X_X_chunk._ts_meta_max_1
|
||||
Index Cond: (compress_hyper_X_X_chunk.device_id = 1)
|
||||
(5 rows)
|
||||
|
||||
--with multiple values can get a nested loop.
|
||||
:PREFIX_VERBOSE SELECT device_id FROM :TEST_TABLE WHERE device_id IN ( VALUES (1), (2));
|
||||
QUERY PLAN
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
QUERY PLAN
|
||||
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
Nested Loop (actual rows=7196 loops=1)
|
||||
Output: _hyper_X_X_chunk.device_id
|
||||
-> Unique (actual rows=2 loops=1)
|
||||
@ -641,25 +641,25 @@ SET enable_hashjoin TO FALSE;
|
||||
Output: _hyper_X_X_chunk.device_id
|
||||
Filter: ("*VALUES*".column1 = _hyper_X_X_chunk.device_id)
|
||||
-> Index Scan using compress_hyper_X_X_chunk__compressed_hypertable_4_device_id__t on _timescaledb_internal.compress_hyper_X_X_chunk (actual rows=4 loops=2)
|
||||
Output: compress_hyper_X_X_chunk._ts_meta_count, compress_hyper_X_X_chunk.device_id
|
||||
Output: compress_hyper_X_X_chunk."time", compress_hyper_X_X_chunk.device_id, compress_hyper_X_X_chunk.v0, compress_hyper_X_X_chunk.v1, compress_hyper_X_X_chunk.v2, compress_hyper_X_X_chunk.v3, compress_hyper_X_X_chunk._ts_meta_count, compress_hyper_X_X_chunk._ts_meta_sequence_num, compress_hyper_X_X_chunk._ts_meta_min_1, compress_hyper_X_X_chunk._ts_meta_max_1
|
||||
Index Cond: (compress_hyper_X_X_chunk.device_id = "*VALUES*".column1)
|
||||
(16 rows)
|
||||
|
||||
RESET enable_hashjoin;
|
||||
:PREFIX_VERBOSE SELECT device_id FROM :TEST_TABLE WHERE device_id IN (VALUES (1));
|
||||
QUERY PLAN
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
QUERY PLAN
|
||||
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_X_X_chunk (actual rows=3598 loops=1)
|
||||
Output: _hyper_X_X_chunk.device_id
|
||||
-> Index Scan using compress_hyper_X_X_chunk__compressed_hypertable_4_device_id__t on _timescaledb_internal.compress_hyper_X_X_chunk (actual rows=4 loops=1)
|
||||
Output: compress_hyper_X_X_chunk._ts_meta_count, compress_hyper_X_X_chunk.device_id
|
||||
Output: compress_hyper_X_X_chunk."time", compress_hyper_X_X_chunk.device_id, compress_hyper_X_X_chunk.v0, compress_hyper_X_X_chunk.v1, compress_hyper_X_X_chunk.v2, compress_hyper_X_X_chunk.v3, compress_hyper_X_X_chunk._ts_meta_count, compress_hyper_X_X_chunk._ts_meta_sequence_num, compress_hyper_X_X_chunk._ts_meta_min_1, compress_hyper_X_X_chunk._ts_meta_max_1
|
||||
Index Cond: (compress_hyper_X_X_chunk.device_id = 1)
|
||||
(5 rows)
|
||||
|
||||
--with multiple values can get a semi-join or nested loop depending on seq_page_cost.
|
||||
:PREFIX_VERBOSE SELECT device_id FROM :TEST_TABLE WHERE device_id IN (VALUES (1), (2));
|
||||
QUERY PLAN
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
QUERY PLAN
|
||||
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
Nested Loop (actual rows=7196 loops=1)
|
||||
Output: _hyper_X_X_chunk.device_id
|
||||
-> Unique (actual rows=2 loops=1)
|
||||
@ -674,15 +674,15 @@ RESET enable_hashjoin;
|
||||
Output: _hyper_X_X_chunk.device_id
|
||||
Filter: ("*VALUES*".column1 = _hyper_X_X_chunk.device_id)
|
||||
-> Index Scan using compress_hyper_X_X_chunk__compressed_hypertable_4_device_id__t on _timescaledb_internal.compress_hyper_X_X_chunk (actual rows=4 loops=2)
|
||||
Output: compress_hyper_X_X_chunk._ts_meta_count, compress_hyper_X_X_chunk.device_id
|
||||
Output: compress_hyper_X_X_chunk."time", compress_hyper_X_X_chunk.device_id, compress_hyper_X_X_chunk.v0, compress_hyper_X_X_chunk.v1, compress_hyper_X_X_chunk.v2, compress_hyper_X_X_chunk.v3, compress_hyper_X_X_chunk._ts_meta_count, compress_hyper_X_X_chunk._ts_meta_sequence_num, compress_hyper_X_X_chunk._ts_meta_min_1, compress_hyper_X_X_chunk._ts_meta_max_1
|
||||
Index Cond: (compress_hyper_X_X_chunk.device_id = "*VALUES*".column1)
|
||||
(16 rows)
|
||||
|
||||
SET seq_page_cost = 100;
|
||||
-- loop/row counts of this query is different on windows so we run it without analyze
|
||||
:PREFIX_NO_ANALYZE SELECT device_id FROM :TEST_TABLE WHERE device_id IN (VALUES (1), (2));
|
||||
QUERY PLAN
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
QUERY PLAN
|
||||
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
Nested Loop
|
||||
Output: _hyper_X_X_chunk.device_id
|
||||
-> Unique
|
||||
@ -696,7 +696,7 @@ SET seq_page_cost = 100;
|
||||
Output: _hyper_X_X_chunk.device_id
|
||||
Filter: ("*VALUES*".column1 = _hyper_X_X_chunk.device_id)
|
||||
-> Index Scan using compress_hyper_X_X_chunk__compressed_hypertable_4_device_id__t on _timescaledb_internal.compress_hyper_X_X_chunk
|
||||
Output: compress_hyper_X_X_chunk._ts_meta_count, compress_hyper_X_X_chunk.device_id
|
||||
Output: compress_hyper_X_X_chunk."time", compress_hyper_X_X_chunk.device_id, compress_hyper_X_X_chunk.v0, compress_hyper_X_X_chunk.v1, compress_hyper_X_X_chunk.v2, compress_hyper_X_X_chunk.v3, compress_hyper_X_X_chunk._ts_meta_count, compress_hyper_X_X_chunk._ts_meta_sequence_num, compress_hyper_X_X_chunk._ts_meta_min_1, compress_hyper_X_X_chunk._ts_meta_max_1
|
||||
Index Cond: (compress_hyper_X_X_chunk.device_id = "*VALUES*".column1)
|
||||
(15 rows)
|
||||
|
||||
|
@ -8,14 +8,14 @@ SELECT show_chunks('metrics_compressed') AS "TEST_TABLE" ORDER BY 1::text LIMIT
|
||||
-- this should use DecompressChunk node
|
||||
:PREFIX_VERBOSE
|
||||
SELECT * FROM :TEST_TABLE WHERE device_id = 1 ORDER BY time LIMIT 5;
|
||||
QUERY PLAN
|
||||
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
QUERY PLAN
|
||||
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
Limit (actual rows=5 loops=1)
|
||||
Output: _hyper_X_X_chunk."time", _hyper_X_X_chunk.device_id, _hyper_X_X_chunk.v0, _hyper_X_X_chunk.v1, _hyper_X_X_chunk.v2, _hyper_X_X_chunk.v3
|
||||
-> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_X_X_chunk (actual rows=5 loops=1)
|
||||
Output: _hyper_X_X_chunk."time", _hyper_X_X_chunk.device_id, _hyper_X_X_chunk.v0, _hyper_X_X_chunk.v1, _hyper_X_X_chunk.v2, _hyper_X_X_chunk.v3
|
||||
-> Index Scan Backward using compress_hyper_X_X_chunk__compressed_hypertable_4_device_id__t on _timescaledb_internal.compress_hyper_X_X_chunk (actual rows=1 loops=1)
|
||||
Output: compress_hyper_X_X_chunk._ts_meta_count, compress_hyper_X_X_chunk._ts_meta_sequence_num, compress_hyper_X_X_chunk."time", compress_hyper_X_X_chunk.device_id, compress_hyper_X_X_chunk.v0, compress_hyper_X_X_chunk.v1, compress_hyper_X_X_chunk.v2, compress_hyper_X_X_chunk.v3
|
||||
Output: compress_hyper_X_X_chunk."time", compress_hyper_X_X_chunk.device_id, compress_hyper_X_X_chunk.v0, compress_hyper_X_X_chunk.v1, compress_hyper_X_X_chunk.v2, compress_hyper_X_X_chunk.v3, compress_hyper_X_X_chunk._ts_meta_count, compress_hyper_X_X_chunk._ts_meta_sequence_num, compress_hyper_X_X_chunk._ts_meta_min_1, compress_hyper_X_X_chunk._ts_meta_max_1
|
||||
Index Cond: (compress_hyper_X_X_chunk.device_id = 1)
|
||||
(7 rows)
|
||||
|
||||
@ -121,8 +121,8 @@ ORDER BY time, device_id;
|
||||
--
|
||||
-- v3 is not segment by or order by column so should not be pushed down
|
||||
:PREFIX_VERBOSE SELECT * FROM :TEST_TABLE WHERE v3 > 10.0 ORDER BY time, device_id;
|
||||
QUERY PLAN
|
||||
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
QUERY PLAN
|
||||
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
Sort (actual rows=0 loops=1)
|
||||
Output: _hyper_X_X_chunk."time", _hyper_X_X_chunk.device_id, _hyper_X_X_chunk.v0, _hyper_X_X_chunk.v1, _hyper_X_X_chunk.v2, _hyper_X_X_chunk.v3
|
||||
Sort Key: _hyper_X_X_chunk."time", _hyper_X_X_chunk.device_id
|
||||
@ -132,7 +132,7 @@ ORDER BY time, device_id;
|
||||
Filter: (_hyper_X_X_chunk.v3 > '10'::double precision)
|
||||
Rows Removed by Filter: 17990
|
||||
-> Seq Scan on _timescaledb_internal.compress_hyper_X_X_chunk (actual rows=20 loops=1)
|
||||
Output: compress_hyper_X_X_chunk._ts_meta_count, compress_hyper_X_X_chunk."time", compress_hyper_X_X_chunk.device_id, compress_hyper_X_X_chunk.v0, compress_hyper_X_X_chunk.v1, compress_hyper_X_X_chunk.v2, compress_hyper_X_X_chunk.v3
|
||||
Output: compress_hyper_X_X_chunk."time", compress_hyper_X_X_chunk.device_id, compress_hyper_X_X_chunk.v0, compress_hyper_X_X_chunk.v1, compress_hyper_X_X_chunk.v2, compress_hyper_X_X_chunk.v3, compress_hyper_X_X_chunk._ts_meta_count, compress_hyper_X_X_chunk._ts_meta_sequence_num, compress_hyper_X_X_chunk._ts_meta_min_1, compress_hyper_X_X_chunk._ts_meta_max_1
|
||||
(10 rows)
|
||||
|
||||
-- device_id constraint should be pushed down
|
||||
@ -404,8 +404,8 @@ ORDER BY time, device_id;
|
||||
|
||||
--pushdown of quals on order by and segment by cols anded together
|
||||
:PREFIX_VERBOSE SELECT * FROM :TEST_TABLE WHERE time > '2000-01-01 1:00:00+0' AND device_id = 1 ORDER BY time, device_id LIMIT 10;
|
||||
QUERY PLAN
|
||||
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
QUERY PLAN
|
||||
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
Limit (actual rows=10 loops=1)
|
||||
Output: _hyper_X_X_chunk."time", _hyper_X_X_chunk.device_id, _hyper_X_X_chunk.v0, _hyper_X_X_chunk.v1, _hyper_X_X_chunk.v2, _hyper_X_X_chunk.v3
|
||||
-> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_X_X_chunk (actual rows=10 loops=1)
|
||||
@ -413,7 +413,7 @@ ORDER BY time, device_id;
|
||||
Filter: (_hyper_X_X_chunk."time" > 'Fri Dec 31 17:00:00 1999 PST'::timestamp with time zone)
|
||||
Rows Removed by Filter: 31
|
||||
-> Index Scan Backward using compress_hyper_X_X_chunk__compressed_hypertable_4_device_id__t on _timescaledb_internal.compress_hyper_X_X_chunk (actual rows=1 loops=1)
|
||||
Output: compress_hyper_X_X_chunk._ts_meta_count, compress_hyper_X_X_chunk._ts_meta_sequence_num, compress_hyper_X_X_chunk."time", compress_hyper_X_X_chunk.device_id, compress_hyper_X_X_chunk.v0, compress_hyper_X_X_chunk.v1, compress_hyper_X_X_chunk.v2, compress_hyper_X_X_chunk.v3
|
||||
Output: compress_hyper_X_X_chunk."time", compress_hyper_X_X_chunk.device_id, compress_hyper_X_X_chunk.v0, compress_hyper_X_X_chunk.v1, compress_hyper_X_X_chunk.v2, compress_hyper_X_X_chunk.v3, compress_hyper_X_X_chunk._ts_meta_count, compress_hyper_X_X_chunk._ts_meta_sequence_num, compress_hyper_X_X_chunk._ts_meta_min_1, compress_hyper_X_X_chunk._ts_meta_max_1
|
||||
Index Cond: (compress_hyper_X_X_chunk.device_id = 1)
|
||||
Filter: (compress_hyper_X_X_chunk._ts_meta_max_1 > 'Fri Dec 31 17:00:00 1999 PST'::timestamp with time zone)
|
||||
(10 rows)
|
||||
@ -559,56 +559,56 @@ SELECT * FROM q1 INNER JOIN q2 ON q1.time = q2.time ORDER BY q1.time;
|
||||
SET enable_seqscan TO FALSE;
|
||||
-- IndexScans should work
|
||||
:PREFIX_VERBOSE SELECT time, device_id FROM :TEST_TABLE WHERE device_id = 1 ORDER BY device_id, time;
|
||||
QUERY PLAN
|
||||
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
QUERY PLAN
|
||||
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_X_X_chunk (actual rows=3598 loops=1)
|
||||
Output: _hyper_X_X_chunk."time", _hyper_X_X_chunk.device_id
|
||||
-> Index Scan Backward using compress_hyper_X_X_chunk__compressed_hypertable_4_device_id__t on _timescaledb_internal.compress_hyper_X_X_chunk (actual rows=4 loops=1)
|
||||
Output: compress_hyper_X_X_chunk._ts_meta_count, compress_hyper_X_X_chunk._ts_meta_sequence_num, compress_hyper_X_X_chunk."time", compress_hyper_X_X_chunk.device_id
|
||||
Output: compress_hyper_X_X_chunk."time", compress_hyper_X_X_chunk.device_id, compress_hyper_X_X_chunk.v0, compress_hyper_X_X_chunk.v1, compress_hyper_X_X_chunk.v2, compress_hyper_X_X_chunk.v3, compress_hyper_X_X_chunk._ts_meta_count, compress_hyper_X_X_chunk._ts_meta_sequence_num, compress_hyper_X_X_chunk._ts_meta_min_1, compress_hyper_X_X_chunk._ts_meta_max_1
|
||||
Index Cond: (compress_hyper_X_X_chunk.device_id = 1)
|
||||
(5 rows)
|
||||
|
||||
-- globs should not plan IndexOnlyScans
|
||||
:PREFIX_VERBOSE SELECT * FROM :TEST_TABLE WHERE device_id = 1 ORDER BY device_id, time;
|
||||
QUERY PLAN
|
||||
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
QUERY PLAN
|
||||
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_X_X_chunk (actual rows=3598 loops=1)
|
||||
Output: _hyper_X_X_chunk."time", _hyper_X_X_chunk.device_id, _hyper_X_X_chunk.v0, _hyper_X_X_chunk.v1, _hyper_X_X_chunk.v2, _hyper_X_X_chunk.v3
|
||||
-> Index Scan Backward using compress_hyper_X_X_chunk__compressed_hypertable_4_device_id__t on _timescaledb_internal.compress_hyper_X_X_chunk (actual rows=4 loops=1)
|
||||
Output: compress_hyper_X_X_chunk._ts_meta_count, compress_hyper_X_X_chunk._ts_meta_sequence_num, compress_hyper_X_X_chunk."time", compress_hyper_X_X_chunk.device_id, compress_hyper_X_X_chunk.v0, compress_hyper_X_X_chunk.v1, compress_hyper_X_X_chunk.v2, compress_hyper_X_X_chunk.v3
|
||||
Output: compress_hyper_X_X_chunk."time", compress_hyper_X_X_chunk.device_id, compress_hyper_X_X_chunk.v0, compress_hyper_X_X_chunk.v1, compress_hyper_X_X_chunk.v2, compress_hyper_X_X_chunk.v3, compress_hyper_X_X_chunk._ts_meta_count, compress_hyper_X_X_chunk._ts_meta_sequence_num, compress_hyper_X_X_chunk._ts_meta_min_1, compress_hyper_X_X_chunk._ts_meta_max_1
|
||||
Index Cond: (compress_hyper_X_X_chunk.device_id = 1)
|
||||
(5 rows)
|
||||
|
||||
-- whole row reference should work
|
||||
:PREFIX_VERBOSE SELECT test_table FROM :TEST_TABLE AS test_table WHERE device_id = 1 ORDER BY device_id, time;
|
||||
QUERY PLAN
|
||||
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
QUERY PLAN
|
||||
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_X_X_chunk test_table (actual rows=3598 loops=1)
|
||||
Output: test_table.*, test_table.device_id, test_table."time"
|
||||
-> Index Scan Backward using compress_hyper_X_X_chunk__compressed_hypertable_4_device_id__t on _timescaledb_internal.compress_hyper_X_X_chunk (actual rows=4 loops=1)
|
||||
Output: compress_hyper_X_X_chunk._ts_meta_count, compress_hyper_X_X_chunk._ts_meta_sequence_num, compress_hyper_X_X_chunk."time", compress_hyper_X_X_chunk.device_id, compress_hyper_X_X_chunk.v0, compress_hyper_X_X_chunk.v1, compress_hyper_X_X_chunk.v2, compress_hyper_X_X_chunk.v3
|
||||
Output: compress_hyper_X_X_chunk."time", compress_hyper_X_X_chunk.device_id, compress_hyper_X_X_chunk.v0, compress_hyper_X_X_chunk.v1, compress_hyper_X_X_chunk.v2, compress_hyper_X_X_chunk.v3, compress_hyper_X_X_chunk._ts_meta_count, compress_hyper_X_X_chunk._ts_meta_sequence_num, compress_hyper_X_X_chunk._ts_meta_min_1, compress_hyper_X_X_chunk._ts_meta_max_1
|
||||
Index Cond: (compress_hyper_X_X_chunk.device_id = 1)
|
||||
(5 rows)
|
||||
|
||||
-- even when we select only a segmentby column, we still need count
|
||||
:PREFIX_VERBOSE SELECT device_id FROM :TEST_TABLE WHERE device_id = 1 ORDER BY device_id;
|
||||
QUERY PLAN
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
QUERY PLAN
|
||||
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_X_X_chunk (actual rows=3598 loops=1)
|
||||
Output: _hyper_X_X_chunk.device_id
|
||||
-> Index Scan using compress_hyper_X_X_chunk__compressed_hypertable_4_device_id__t on _timescaledb_internal.compress_hyper_X_X_chunk (actual rows=4 loops=1)
|
||||
Output: compress_hyper_X_X_chunk._ts_meta_count, compress_hyper_X_X_chunk.device_id
|
||||
Output: compress_hyper_X_X_chunk."time", compress_hyper_X_X_chunk.device_id, compress_hyper_X_X_chunk.v0, compress_hyper_X_X_chunk.v1, compress_hyper_X_X_chunk.v2, compress_hyper_X_X_chunk.v3, compress_hyper_X_X_chunk._ts_meta_count, compress_hyper_X_X_chunk._ts_meta_sequence_num, compress_hyper_X_X_chunk._ts_meta_min_1, compress_hyper_X_X_chunk._ts_meta_max_1
|
||||
Index Cond: (compress_hyper_X_X_chunk.device_id = 1)
|
||||
(5 rows)
|
||||
|
||||
:PREFIX_VERBOSE SELECT count(*) FROM :TEST_TABLE WHERE device_id = 1;
|
||||
QUERY PLAN
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
QUERY PLAN
|
||||
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
Aggregate (actual rows=1 loops=1)
|
||||
Output: count(*)
|
||||
-> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_X_X_chunk (actual rows=3598 loops=1)
|
||||
-> Index Scan using compress_hyper_X_X_chunk__compressed_hypertable_4_device_id__t on _timescaledb_internal.compress_hyper_X_X_chunk (actual rows=4 loops=1)
|
||||
Output: compress_hyper_X_X_chunk._ts_meta_count, compress_hyper_X_X_chunk.device_id
|
||||
Output: compress_hyper_X_X_chunk."time", compress_hyper_X_X_chunk.device_id, compress_hyper_X_X_chunk.v0, compress_hyper_X_X_chunk.v1, compress_hyper_X_X_chunk.v2, compress_hyper_X_X_chunk.v3, compress_hyper_X_X_chunk._ts_meta_count, compress_hyper_X_X_chunk._ts_meta_sequence_num, compress_hyper_X_X_chunk._ts_meta_min_1, compress_hyper_X_X_chunk._ts_meta_max_1
|
||||
Index Cond: (compress_hyper_X_X_chunk.device_id = 1)
|
||||
(6 rows)
|
||||
|
||||
@ -616,19 +616,19 @@ SET enable_seqscan TO FALSE;
|
||||
SET enable_seqscan TO TRUE;
|
||||
SET enable_hashjoin TO FALSE;
|
||||
:PREFIX_VERBOSE SELECT device_id FROM :TEST_TABLE WHERE device_id IN ( VALUES (1));
|
||||
QUERY PLAN
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
QUERY PLAN
|
||||
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_X_X_chunk (actual rows=3598 loops=1)
|
||||
Output: _hyper_X_X_chunk.device_id
|
||||
-> Index Scan using compress_hyper_X_X_chunk__compressed_hypertable_4_device_id__t on _timescaledb_internal.compress_hyper_X_X_chunk (actual rows=4 loops=1)
|
||||
Output: compress_hyper_X_X_chunk._ts_meta_count, compress_hyper_X_X_chunk.device_id
|
||||
Output: compress_hyper_X_X_chunk."time", compress_hyper_X_X_chunk.device_id, compress_hyper_X_X_chunk.v0, compress_hyper_X_X_chunk.v1, compress_hyper_X_X_chunk.v2, compress_hyper_X_X_chunk.v3, compress_hyper_X_X_chunk._ts_meta_count, compress_hyper_X_X_chunk._ts_meta_sequence_num, compress_hyper_X_X_chunk._ts_meta_min_1, compress_hyper_X_X_chunk._ts_meta_max_1
|
||||
Index Cond: (compress_hyper_X_X_chunk.device_id = 1)
|
||||
(5 rows)
|
||||
|
||||
--with multiple values can get a nested loop.
|
||||
:PREFIX_VERBOSE SELECT device_id FROM :TEST_TABLE WHERE device_id IN ( VALUES (1), (2));
|
||||
QUERY PLAN
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
QUERY PLAN
|
||||
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
Nested Loop (actual rows=7196 loops=1)
|
||||
Output: _hyper_X_X_chunk.device_id
|
||||
-> Unique (actual rows=2 loops=1)
|
||||
@ -643,25 +643,25 @@ SET enable_hashjoin TO FALSE;
|
||||
Output: _hyper_X_X_chunk.device_id
|
||||
Filter: ("*VALUES*".column1 = _hyper_X_X_chunk.device_id)
|
||||
-> Index Scan using compress_hyper_X_X_chunk__compressed_hypertable_4_device_id__t on _timescaledb_internal.compress_hyper_X_X_chunk (actual rows=4 loops=2)
|
||||
Output: compress_hyper_X_X_chunk._ts_meta_count, compress_hyper_X_X_chunk.device_id
|
||||
Output: compress_hyper_X_X_chunk."time", compress_hyper_X_X_chunk.device_id, compress_hyper_X_X_chunk.v0, compress_hyper_X_X_chunk.v1, compress_hyper_X_X_chunk.v2, compress_hyper_X_X_chunk.v3, compress_hyper_X_X_chunk._ts_meta_count, compress_hyper_X_X_chunk._ts_meta_sequence_num, compress_hyper_X_X_chunk._ts_meta_min_1, compress_hyper_X_X_chunk._ts_meta_max_1
|
||||
Index Cond: (compress_hyper_X_X_chunk.device_id = "*VALUES*".column1)
|
||||
(16 rows)
|
||||
|
||||
RESET enable_hashjoin;
|
||||
:PREFIX_VERBOSE SELECT device_id FROM :TEST_TABLE WHERE device_id IN (VALUES (1));
|
||||
QUERY PLAN
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
QUERY PLAN
|
||||
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_X_X_chunk (actual rows=3598 loops=1)
|
||||
Output: _hyper_X_X_chunk.device_id
|
||||
-> Index Scan using compress_hyper_X_X_chunk__compressed_hypertable_4_device_id__t on _timescaledb_internal.compress_hyper_X_X_chunk (actual rows=4 loops=1)
|
||||
Output: compress_hyper_X_X_chunk._ts_meta_count, compress_hyper_X_X_chunk.device_id
|
||||
Output: compress_hyper_X_X_chunk."time", compress_hyper_X_X_chunk.device_id, compress_hyper_X_X_chunk.v0, compress_hyper_X_X_chunk.v1, compress_hyper_X_X_chunk.v2, compress_hyper_X_X_chunk.v3, compress_hyper_X_X_chunk._ts_meta_count, compress_hyper_X_X_chunk._ts_meta_sequence_num, compress_hyper_X_X_chunk._ts_meta_min_1, compress_hyper_X_X_chunk._ts_meta_max_1
|
||||
Index Cond: (compress_hyper_X_X_chunk.device_id = 1)
|
||||
(5 rows)
|
||||
|
||||
--with multiple values can get a semi-join or nested loop depending on seq_page_cost.
|
||||
:PREFIX_VERBOSE SELECT device_id FROM :TEST_TABLE WHERE device_id IN (VALUES (1), (2));
|
||||
QUERY PLAN
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
QUERY PLAN
|
||||
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
Nested Loop (actual rows=7196 loops=1)
|
||||
Output: _hyper_X_X_chunk.device_id
|
||||
-> Unique (actual rows=2 loops=1)
|
||||
@ -676,15 +676,15 @@ RESET enable_hashjoin;
|
||||
Output: _hyper_X_X_chunk.device_id
|
||||
Filter: ("*VALUES*".column1 = _hyper_X_X_chunk.device_id)
|
||||
-> Index Scan using compress_hyper_X_X_chunk__compressed_hypertable_4_device_id__t on _timescaledb_internal.compress_hyper_X_X_chunk (actual rows=4 loops=2)
|
||||
Output: compress_hyper_X_X_chunk._ts_meta_count, compress_hyper_X_X_chunk.device_id
|
||||
Output: compress_hyper_X_X_chunk."time", compress_hyper_X_X_chunk.device_id, compress_hyper_X_X_chunk.v0, compress_hyper_X_X_chunk.v1, compress_hyper_X_X_chunk.v2, compress_hyper_X_X_chunk.v3, compress_hyper_X_X_chunk._ts_meta_count, compress_hyper_X_X_chunk._ts_meta_sequence_num, compress_hyper_X_X_chunk._ts_meta_min_1, compress_hyper_X_X_chunk._ts_meta_max_1
|
||||
Index Cond: (compress_hyper_X_X_chunk.device_id = "*VALUES*".column1)
|
||||
(16 rows)
|
||||
|
||||
SET seq_page_cost = 100;
|
||||
-- loop/row counts of this query is different on windows so we run it without analyze
|
||||
:PREFIX_NO_ANALYZE SELECT device_id FROM :TEST_TABLE WHERE device_id IN (VALUES (1), (2));
|
||||
QUERY PLAN
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
QUERY PLAN
|
||||
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
Nested Loop
|
||||
Output: _hyper_X_X_chunk.device_id
|
||||
-> Unique
|
||||
@ -698,7 +698,7 @@ SET seq_page_cost = 100;
|
||||
Output: _hyper_X_X_chunk.device_id
|
||||
Filter: ("*VALUES*".column1 = _hyper_X_X_chunk.device_id)
|
||||
-> Index Scan using compress_hyper_X_X_chunk__compressed_hypertable_4_device_id__t on _timescaledb_internal.compress_hyper_X_X_chunk
|
||||
Output: compress_hyper_X_X_chunk._ts_meta_count, compress_hyper_X_X_chunk.device_id
|
||||
Output: compress_hyper_X_X_chunk."time", compress_hyper_X_X_chunk.device_id, compress_hyper_X_X_chunk.v0, compress_hyper_X_X_chunk.v1, compress_hyper_X_X_chunk.v2, compress_hyper_X_X_chunk.v3, compress_hyper_X_X_chunk._ts_meta_count, compress_hyper_X_X_chunk._ts_meta_sequence_num, compress_hyper_X_X_chunk._ts_meta_min_1, compress_hyper_X_X_chunk._ts_meta_max_1
|
||||
Index Cond: (compress_hyper_X_X_chunk.device_id = "*VALUES*".column1)
|
||||
(15 rows)
|
||||
|
||||
|
@ -8,14 +8,14 @@ SELECT show_chunks('metrics_compressed') AS "TEST_TABLE" ORDER BY 1::text LIMIT
|
||||
-- this should use DecompressChunk node
|
||||
:PREFIX_VERBOSE
|
||||
SELECT * FROM :TEST_TABLE WHERE device_id = 1 ORDER BY time LIMIT 5;
|
||||
QUERY PLAN
|
||||
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
QUERY PLAN
|
||||
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
Limit (actual rows=5 loops=1)
|
||||
Output: _hyper_X_X_chunk."time", _hyper_X_X_chunk.device_id, _hyper_X_X_chunk.v0, _hyper_X_X_chunk.v1, _hyper_X_X_chunk.v2, _hyper_X_X_chunk.v3
|
||||
-> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_X_X_chunk (actual rows=5 loops=1)
|
||||
Output: _hyper_X_X_chunk."time", _hyper_X_X_chunk.device_id, _hyper_X_X_chunk.v0, _hyper_X_X_chunk.v1, _hyper_X_X_chunk.v2, _hyper_X_X_chunk.v3
|
||||
-> Index Scan Backward using compress_hyper_X_X_chunk__compressed_hypertable_4_device_id__t on _timescaledb_internal.compress_hyper_X_X_chunk (actual rows=1 loops=1)
|
||||
Output: compress_hyper_X_X_chunk._ts_meta_count, compress_hyper_X_X_chunk._ts_meta_sequence_num, compress_hyper_X_X_chunk."time", compress_hyper_X_X_chunk.device_id, compress_hyper_X_X_chunk.v0, compress_hyper_X_X_chunk.v1, compress_hyper_X_X_chunk.v2, compress_hyper_X_X_chunk.v3
|
||||
Output: compress_hyper_X_X_chunk."time", compress_hyper_X_X_chunk.device_id, compress_hyper_X_X_chunk.v0, compress_hyper_X_X_chunk.v1, compress_hyper_X_X_chunk.v2, compress_hyper_X_X_chunk.v3, compress_hyper_X_X_chunk._ts_meta_count, compress_hyper_X_X_chunk._ts_meta_sequence_num, compress_hyper_X_X_chunk._ts_meta_min_1, compress_hyper_X_X_chunk._ts_meta_max_1
|
||||
Index Cond: (compress_hyper_X_X_chunk.device_id = 1)
|
||||
(7 rows)
|
||||
|
||||
@ -121,8 +121,8 @@ ORDER BY time, device_id;
|
||||
--
|
||||
-- v3 is not segment by or order by column so should not be pushed down
|
||||
:PREFIX_VERBOSE SELECT * FROM :TEST_TABLE WHERE v3 > 10.0 ORDER BY time, device_id;
|
||||
QUERY PLAN
|
||||
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
QUERY PLAN
|
||||
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
Sort (actual rows=0 loops=1)
|
||||
Output: _hyper_X_X_chunk."time", _hyper_X_X_chunk.device_id, _hyper_X_X_chunk.v0, _hyper_X_X_chunk.v1, _hyper_X_X_chunk.v2, _hyper_X_X_chunk.v3
|
||||
Sort Key: _hyper_X_X_chunk."time", _hyper_X_X_chunk.device_id
|
||||
@ -132,7 +132,7 @@ ORDER BY time, device_id;
|
||||
Filter: (_hyper_X_X_chunk.v3 > '10'::double precision)
|
||||
Rows Removed by Filter: 17990
|
||||
-> Seq Scan on _timescaledb_internal.compress_hyper_X_X_chunk (actual rows=20 loops=1)
|
||||
Output: compress_hyper_X_X_chunk._ts_meta_count, compress_hyper_X_X_chunk."time", compress_hyper_X_X_chunk.device_id, compress_hyper_X_X_chunk.v0, compress_hyper_X_X_chunk.v1, compress_hyper_X_X_chunk.v2, compress_hyper_X_X_chunk.v3
|
||||
Output: compress_hyper_X_X_chunk."time", compress_hyper_X_X_chunk.device_id, compress_hyper_X_X_chunk.v0, compress_hyper_X_X_chunk.v1, compress_hyper_X_X_chunk.v2, compress_hyper_X_X_chunk.v3, compress_hyper_X_X_chunk._ts_meta_count, compress_hyper_X_X_chunk._ts_meta_sequence_num, compress_hyper_X_X_chunk._ts_meta_min_1, compress_hyper_X_X_chunk._ts_meta_max_1
|
||||
(10 rows)
|
||||
|
||||
-- device_id constraint should be pushed down
|
||||
@ -404,8 +404,8 @@ ORDER BY time, device_id;
|
||||
|
||||
--pushdown of quals on order by and segment by cols anded together
|
||||
:PREFIX_VERBOSE SELECT * FROM :TEST_TABLE WHERE time > '2000-01-01 1:00:00+0' AND device_id = 1 ORDER BY time, device_id LIMIT 10;
|
||||
QUERY PLAN
|
||||
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
QUERY PLAN
|
||||
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
Limit (actual rows=10 loops=1)
|
||||
Output: _hyper_X_X_chunk."time", _hyper_X_X_chunk.device_id, _hyper_X_X_chunk.v0, _hyper_X_X_chunk.v1, _hyper_X_X_chunk.v2, _hyper_X_X_chunk.v3
|
||||
-> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_X_X_chunk (actual rows=10 loops=1)
|
||||
@ -413,7 +413,7 @@ ORDER BY time, device_id;
|
||||
Filter: (_hyper_X_X_chunk."time" > 'Fri Dec 31 17:00:00 1999 PST'::timestamp with time zone)
|
||||
Rows Removed by Filter: 31
|
||||
-> Index Scan Backward using compress_hyper_X_X_chunk__compressed_hypertable_4_device_id__t on _timescaledb_internal.compress_hyper_X_X_chunk (actual rows=1 loops=1)
|
||||
Output: compress_hyper_X_X_chunk._ts_meta_count, compress_hyper_X_X_chunk._ts_meta_sequence_num, compress_hyper_X_X_chunk."time", compress_hyper_X_X_chunk.device_id, compress_hyper_X_X_chunk.v0, compress_hyper_X_X_chunk.v1, compress_hyper_X_X_chunk.v2, compress_hyper_X_X_chunk.v3
|
||||
Output: compress_hyper_X_X_chunk."time", compress_hyper_X_X_chunk.device_id, compress_hyper_X_X_chunk.v0, compress_hyper_X_X_chunk.v1, compress_hyper_X_X_chunk.v2, compress_hyper_X_X_chunk.v3, compress_hyper_X_X_chunk._ts_meta_count, compress_hyper_X_X_chunk._ts_meta_sequence_num, compress_hyper_X_X_chunk._ts_meta_min_1, compress_hyper_X_X_chunk._ts_meta_max_1
|
||||
Index Cond: (compress_hyper_X_X_chunk.device_id = 1)
|
||||
Filter: (compress_hyper_X_X_chunk._ts_meta_max_1 > 'Fri Dec 31 17:00:00 1999 PST'::timestamp with time zone)
|
||||
(10 rows)
|
||||
@ -559,56 +559,56 @@ SELECT * FROM q1 INNER JOIN q2 ON q1.time = q2.time ORDER BY q1.time;
|
||||
SET enable_seqscan TO FALSE;
|
||||
-- IndexScans should work
|
||||
:PREFIX_VERBOSE SELECT time, device_id FROM :TEST_TABLE WHERE device_id = 1 ORDER BY device_id, time;
|
||||
QUERY PLAN
|
||||
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
QUERY PLAN
|
||||
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_X_X_chunk (actual rows=3598 loops=1)
|
||||
Output: _hyper_X_X_chunk."time", _hyper_X_X_chunk.device_id
|
||||
-> Index Scan Backward using compress_hyper_X_X_chunk__compressed_hypertable_4_device_id__t on _timescaledb_internal.compress_hyper_X_X_chunk (actual rows=4 loops=1)
|
||||
Output: compress_hyper_X_X_chunk._ts_meta_count, compress_hyper_X_X_chunk._ts_meta_sequence_num, compress_hyper_X_X_chunk."time", compress_hyper_X_X_chunk.device_id
|
||||
Output: compress_hyper_X_X_chunk."time", compress_hyper_X_X_chunk.device_id, compress_hyper_X_X_chunk.v0, compress_hyper_X_X_chunk.v1, compress_hyper_X_X_chunk.v2, compress_hyper_X_X_chunk.v3, compress_hyper_X_X_chunk._ts_meta_count, compress_hyper_X_X_chunk._ts_meta_sequence_num, compress_hyper_X_X_chunk._ts_meta_min_1, compress_hyper_X_X_chunk._ts_meta_max_1
|
||||
Index Cond: (compress_hyper_X_X_chunk.device_id = 1)
|
||||
(5 rows)
|
||||
|
||||
-- globs should not plan IndexOnlyScans
|
||||
:PREFIX_VERBOSE SELECT * FROM :TEST_TABLE WHERE device_id = 1 ORDER BY device_id, time;
|
||||
QUERY PLAN
|
||||
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
QUERY PLAN
|
||||
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_X_X_chunk (actual rows=3598 loops=1)
|
||||
Output: _hyper_X_X_chunk."time", _hyper_X_X_chunk.device_id, _hyper_X_X_chunk.v0, _hyper_X_X_chunk.v1, _hyper_X_X_chunk.v2, _hyper_X_X_chunk.v3
|
||||
-> Index Scan Backward using compress_hyper_X_X_chunk__compressed_hypertable_4_device_id__t on _timescaledb_internal.compress_hyper_X_X_chunk (actual rows=4 loops=1)
|
||||
Output: compress_hyper_X_X_chunk._ts_meta_count, compress_hyper_X_X_chunk._ts_meta_sequence_num, compress_hyper_X_X_chunk."time", compress_hyper_X_X_chunk.device_id, compress_hyper_X_X_chunk.v0, compress_hyper_X_X_chunk.v1, compress_hyper_X_X_chunk.v2, compress_hyper_X_X_chunk.v3
|
||||
Output: compress_hyper_X_X_chunk."time", compress_hyper_X_X_chunk.device_id, compress_hyper_X_X_chunk.v0, compress_hyper_X_X_chunk.v1, compress_hyper_X_X_chunk.v2, compress_hyper_X_X_chunk.v3, compress_hyper_X_X_chunk._ts_meta_count, compress_hyper_X_X_chunk._ts_meta_sequence_num, compress_hyper_X_X_chunk._ts_meta_min_1, compress_hyper_X_X_chunk._ts_meta_max_1
|
||||
Index Cond: (compress_hyper_X_X_chunk.device_id = 1)
|
||||
(5 rows)
|
||||
|
||||
-- whole row reference should work
|
||||
:PREFIX_VERBOSE SELECT test_table FROM :TEST_TABLE AS test_table WHERE device_id = 1 ORDER BY device_id, time;
|
||||
QUERY PLAN
|
||||
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
QUERY PLAN
|
||||
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_X_X_chunk test_table (actual rows=3598 loops=1)
|
||||
Output: test_table.*, test_table.device_id, test_table."time"
|
||||
-> Index Scan Backward using compress_hyper_X_X_chunk__compressed_hypertable_4_device_id__t on _timescaledb_internal.compress_hyper_X_X_chunk (actual rows=4 loops=1)
|
||||
Output: compress_hyper_X_X_chunk._ts_meta_count, compress_hyper_X_X_chunk._ts_meta_sequence_num, compress_hyper_X_X_chunk."time", compress_hyper_X_X_chunk.device_id, compress_hyper_X_X_chunk.v0, compress_hyper_X_X_chunk.v1, compress_hyper_X_X_chunk.v2, compress_hyper_X_X_chunk.v3
|
||||
Output: compress_hyper_X_X_chunk."time", compress_hyper_X_X_chunk.device_id, compress_hyper_X_X_chunk.v0, compress_hyper_X_X_chunk.v1, compress_hyper_X_X_chunk.v2, compress_hyper_X_X_chunk.v3, compress_hyper_X_X_chunk._ts_meta_count, compress_hyper_X_X_chunk._ts_meta_sequence_num, compress_hyper_X_X_chunk._ts_meta_min_1, compress_hyper_X_X_chunk._ts_meta_max_1
|
||||
Index Cond: (compress_hyper_X_X_chunk.device_id = 1)
|
||||
(5 rows)
|
||||
|
||||
-- even when we select only a segmentby column, we still need count
|
||||
:PREFIX_VERBOSE SELECT device_id FROM :TEST_TABLE WHERE device_id = 1 ORDER BY device_id;
|
||||
QUERY PLAN
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
QUERY PLAN
|
||||
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_X_X_chunk (actual rows=3598 loops=1)
|
||||
Output: _hyper_X_X_chunk.device_id
|
||||
-> Index Scan using compress_hyper_X_X_chunk__compressed_hypertable_4_device_id__t on _timescaledb_internal.compress_hyper_X_X_chunk (actual rows=4 loops=1)
|
||||
Output: compress_hyper_X_X_chunk._ts_meta_count, compress_hyper_X_X_chunk.device_id
|
||||
Output: compress_hyper_X_X_chunk."time", compress_hyper_X_X_chunk.device_id, compress_hyper_X_X_chunk.v0, compress_hyper_X_X_chunk.v1, compress_hyper_X_X_chunk.v2, compress_hyper_X_X_chunk.v3, compress_hyper_X_X_chunk._ts_meta_count, compress_hyper_X_X_chunk._ts_meta_sequence_num, compress_hyper_X_X_chunk._ts_meta_min_1, compress_hyper_X_X_chunk._ts_meta_max_1
|
||||
Index Cond: (compress_hyper_X_X_chunk.device_id = 1)
|
||||
(5 rows)
|
||||
|
||||
:PREFIX_VERBOSE SELECT count(*) FROM :TEST_TABLE WHERE device_id = 1;
|
||||
QUERY PLAN
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
QUERY PLAN
|
||||
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
Aggregate (actual rows=1 loops=1)
|
||||
Output: count(*)
|
||||
-> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_X_X_chunk (actual rows=3598 loops=1)
|
||||
-> Index Scan using compress_hyper_X_X_chunk__compressed_hypertable_4_device_id__t on _timescaledb_internal.compress_hyper_X_X_chunk (actual rows=4 loops=1)
|
||||
Output: compress_hyper_X_X_chunk._ts_meta_count, compress_hyper_X_X_chunk.device_id
|
||||
Output: compress_hyper_X_X_chunk."time", compress_hyper_X_X_chunk.device_id, compress_hyper_X_X_chunk.v0, compress_hyper_X_X_chunk.v1, compress_hyper_X_X_chunk.v2, compress_hyper_X_X_chunk.v3, compress_hyper_X_X_chunk._ts_meta_count, compress_hyper_X_X_chunk._ts_meta_sequence_num, compress_hyper_X_X_chunk._ts_meta_min_1, compress_hyper_X_X_chunk._ts_meta_max_1
|
||||
Index Cond: (compress_hyper_X_X_chunk.device_id = 1)
|
||||
(6 rows)
|
||||
|
||||
@ -616,19 +616,19 @@ SET enable_seqscan TO FALSE;
|
||||
SET enable_seqscan TO TRUE;
|
||||
SET enable_hashjoin TO FALSE;
|
||||
:PREFIX_VERBOSE SELECT device_id FROM :TEST_TABLE WHERE device_id IN ( VALUES (1));
|
||||
QUERY PLAN
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
QUERY PLAN
|
||||
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_X_X_chunk (actual rows=3598 loops=1)
|
||||
Output: _hyper_X_X_chunk.device_id
|
||||
-> Index Scan using compress_hyper_X_X_chunk__compressed_hypertable_4_device_id__t on _timescaledb_internal.compress_hyper_X_X_chunk (actual rows=4 loops=1)
|
||||
Output: compress_hyper_X_X_chunk._ts_meta_count, compress_hyper_X_X_chunk.device_id
|
||||
Output: compress_hyper_X_X_chunk."time", compress_hyper_X_X_chunk.device_id, compress_hyper_X_X_chunk.v0, compress_hyper_X_X_chunk.v1, compress_hyper_X_X_chunk.v2, compress_hyper_X_X_chunk.v3, compress_hyper_X_X_chunk._ts_meta_count, compress_hyper_X_X_chunk._ts_meta_sequence_num, compress_hyper_X_X_chunk._ts_meta_min_1, compress_hyper_X_X_chunk._ts_meta_max_1
|
||||
Index Cond: (compress_hyper_X_X_chunk.device_id = 1)
|
||||
(5 rows)
|
||||
|
||||
--with multiple values can get a nested loop.
|
||||
:PREFIX_VERBOSE SELECT device_id FROM :TEST_TABLE WHERE device_id IN ( VALUES (1), (2));
|
||||
QUERY PLAN
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
QUERY PLAN
|
||||
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
Nested Loop (actual rows=7196 loops=1)
|
||||
Output: _hyper_X_X_chunk.device_id
|
||||
-> Unique (actual rows=2 loops=1)
|
||||
@ -643,25 +643,25 @@ SET enable_hashjoin TO FALSE;
|
||||
Output: _hyper_X_X_chunk.device_id
|
||||
Filter: ("*VALUES*".column1 = _hyper_X_X_chunk.device_id)
|
||||
-> Index Scan using compress_hyper_X_X_chunk__compressed_hypertable_4_device_id__t on _timescaledb_internal.compress_hyper_X_X_chunk (actual rows=4 loops=2)
|
||||
Output: compress_hyper_X_X_chunk._ts_meta_count, compress_hyper_X_X_chunk.device_id
|
||||
Output: compress_hyper_X_X_chunk."time", compress_hyper_X_X_chunk.device_id, compress_hyper_X_X_chunk.v0, compress_hyper_X_X_chunk.v1, compress_hyper_X_X_chunk.v2, compress_hyper_X_X_chunk.v3, compress_hyper_X_X_chunk._ts_meta_count, compress_hyper_X_X_chunk._ts_meta_sequence_num, compress_hyper_X_X_chunk._ts_meta_min_1, compress_hyper_X_X_chunk._ts_meta_max_1
|
||||
Index Cond: (compress_hyper_X_X_chunk.device_id = "*VALUES*".column1)
|
||||
(16 rows)
|
||||
|
||||
RESET enable_hashjoin;
|
||||
:PREFIX_VERBOSE SELECT device_id FROM :TEST_TABLE WHERE device_id IN (VALUES (1));
|
||||
QUERY PLAN
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
QUERY PLAN
|
||||
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_X_X_chunk (actual rows=3598 loops=1)
|
||||
Output: _hyper_X_X_chunk.device_id
|
||||
-> Index Scan using compress_hyper_X_X_chunk__compressed_hypertable_4_device_id__t on _timescaledb_internal.compress_hyper_X_X_chunk (actual rows=4 loops=1)
|
||||
Output: compress_hyper_X_X_chunk._ts_meta_count, compress_hyper_X_X_chunk.device_id
|
||||
Output: compress_hyper_X_X_chunk."time", compress_hyper_X_X_chunk.device_id, compress_hyper_X_X_chunk.v0, compress_hyper_X_X_chunk.v1, compress_hyper_X_X_chunk.v2, compress_hyper_X_X_chunk.v3, compress_hyper_X_X_chunk._ts_meta_count, compress_hyper_X_X_chunk._ts_meta_sequence_num, compress_hyper_X_X_chunk._ts_meta_min_1, compress_hyper_X_X_chunk._ts_meta_max_1
|
||||
Index Cond: (compress_hyper_X_X_chunk.device_id = 1)
|
||||
(5 rows)
|
||||
|
||||
--with multiple values can get a semi-join or nested loop depending on seq_page_cost.
|
||||
:PREFIX_VERBOSE SELECT device_id FROM :TEST_TABLE WHERE device_id IN (VALUES (1), (2));
|
||||
QUERY PLAN
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
QUERY PLAN
|
||||
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
Nested Loop (actual rows=7196 loops=1)
|
||||
Output: _hyper_X_X_chunk.device_id
|
||||
-> Unique (actual rows=2 loops=1)
|
||||
@ -676,15 +676,15 @@ RESET enable_hashjoin;
|
||||
Output: _hyper_X_X_chunk.device_id
|
||||
Filter: ("*VALUES*".column1 = _hyper_X_X_chunk.device_id)
|
||||
-> Index Scan using compress_hyper_X_X_chunk__compressed_hypertable_4_device_id__t on _timescaledb_internal.compress_hyper_X_X_chunk (actual rows=4 loops=2)
|
||||
Output: compress_hyper_X_X_chunk._ts_meta_count, compress_hyper_X_X_chunk.device_id
|
||||
Output: compress_hyper_X_X_chunk."time", compress_hyper_X_X_chunk.device_id, compress_hyper_X_X_chunk.v0, compress_hyper_X_X_chunk.v1, compress_hyper_X_X_chunk.v2, compress_hyper_X_X_chunk.v3, compress_hyper_X_X_chunk._ts_meta_count, compress_hyper_X_X_chunk._ts_meta_sequence_num, compress_hyper_X_X_chunk._ts_meta_min_1, compress_hyper_X_X_chunk._ts_meta_max_1
|
||||
Index Cond: (compress_hyper_X_X_chunk.device_id = "*VALUES*".column1)
|
||||
(16 rows)
|
||||
|
||||
SET seq_page_cost = 100;
|
||||
-- loop/row counts of this query is different on windows so we run it without analyze
|
||||
:PREFIX_NO_ANALYZE SELECT device_id FROM :TEST_TABLE WHERE device_id IN (VALUES (1), (2));
|
||||
QUERY PLAN
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
QUERY PLAN
|
||||
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
Nested Loop
|
||||
Output: _hyper_X_X_chunk.device_id
|
||||
-> Unique
|
||||
@ -698,7 +698,7 @@ SET seq_page_cost = 100;
|
||||
Output: _hyper_X_X_chunk.device_id
|
||||
Filter: ("*VALUES*".column1 = _hyper_X_X_chunk.device_id)
|
||||
-> Index Scan using compress_hyper_X_X_chunk__compressed_hypertable_4_device_id__t on _timescaledb_internal.compress_hyper_X_X_chunk
|
||||
Output: compress_hyper_X_X_chunk._ts_meta_count, compress_hyper_X_X_chunk.device_id
|
||||
Output: compress_hyper_X_X_chunk."time", compress_hyper_X_X_chunk.device_id, compress_hyper_X_X_chunk.v0, compress_hyper_X_X_chunk.v1, compress_hyper_X_X_chunk.v2, compress_hyper_X_X_chunk.v3, compress_hyper_X_X_chunk._ts_meta_count, compress_hyper_X_X_chunk._ts_meta_sequence_num, compress_hyper_X_X_chunk._ts_meta_min_1, compress_hyper_X_X_chunk._ts_meta_max_1
|
||||
Index Cond: (compress_hyper_X_X_chunk.device_id = "*VALUES*".column1)
|
||||
(15 rows)
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user