Add query tests for ORDER BY time DESC queries LIMIT queries

These tests show that non-aggregated queries that have an ORDER BY time
DESC LIMIT x structure perform well. Postgres processes such queries by
using a time DESC index and then performs a MergeAppend. Some further
optimization to avoid touching unnecessary tables due to constraints
can be added but they are not a priority. Much worse is that these
optimizations do not work when grouping by time (either through
integer division or using date_trunc).

In order to use the non-aggregated query optimizations we had
to create an index with time as the leading field and no
WHERE clause on the index.
This commit is contained in:
Matvey Arye 2017-03-19 20:13:32 -04:00
parent b32c3789cf
commit e0d63e915c
7 changed files with 409 additions and 65 deletions

View File

@ -29,6 +29,7 @@ CREATE INDEX ON PUBLIC."testNs" ("timeCustom" DESC NULLS LAST, series_0) WHERE s
CREATE INDEX ON PUBLIC."testNs" ("timeCustom" DESC NULLS LAST, series_1) WHERE series_1 IS NOT NULL;
CREATE INDEX ON PUBLIC."testNs" ("timeCustom" DESC NULLS LAST, series_2) WHERE series_2 IS NOT NULL;
CREATE INDEX ON PUBLIC."testNs" ("timeCustom" DESC NULLS LAST, series_bool) WHERE series_bool IS NOT NULL;
CREATE INDEX ON PUBLIC."testNs" ("timeCustom" DESC NULLS LAST, device_id);
SELECT * FROM create_hypertable('"public"."testNs"'::regclass, 'timeCustom'::name, 'device_id'::name, associated_schema_name=>'_timescaledb_internal'::text, number_partitions => 2);
BEGIN;
\COPY public."testNs" FROM 'data/ds1_dev1_1.tsv' NULL AS '';

View File

@ -31,6 +31,7 @@ CREATE INDEX ON PUBLIC."testNs" ("timeCustom" DESC NULLS LAST, series_0) WHERE s
CREATE INDEX ON PUBLIC."testNs" ("timeCustom" DESC NULLS LAST, series_1) WHERE series_1 IS NOT NULL;
CREATE INDEX ON PUBLIC."testNs" ("timeCustom" DESC NULLS LAST, series_2) WHERE series_2 IS NOT NULL;
CREATE INDEX ON PUBLIC."testNs" ("timeCustom" DESC NULLS LAST, series_bool) WHERE series_bool IS NOT NULL;
CREATE INDEX ON PUBLIC."testNs" ("timeCustom" DESC NULLS LAST, device_id);
SELECT * FROM create_hypertable('"public"."testNs"'::regclass, 'timeCustom'::name, 'device_id'::name, associated_schema_name=>'_timescaledb_internal'::text, number_partitions => 2);
BEGIN;
\COPY public."testNs" FROM 'data/ds1_dev1_1.tsv' NULL AS '';
@ -72,48 +73,69 @@ Index "_timescaledb_internal.1-testNs_device_id_timeCustom_idx"
timeCustom | bigint | "timeCustom" | plain
btree, for table "_timescaledb_internal._hyper_1_1_0_1_data", predicate (device_id IS NOT NULL)
Index "_timescaledb_internal.10-testNs_timeCustom_series_bool_idx"
Index "_timescaledb_internal.10-testNs_timeCustom_series_2_idx"
Column | Type | Definition | Storage
------------+------------------+--------------+---------
timeCustom | bigint | "timeCustom" | plain
series_2 | double precision | series_2 | plain
btree, for table "_timescaledb_internal._hyper_1_1_0_2_data", predicate (series_2 IS NOT NULL)
Index "_timescaledb_internal.11-testNs_timeCustom_series_bool_idx"
Column | Type | Definition | Storage
-------------+---------+--------------+---------
timeCustom | bigint | "timeCustom" | plain
series_bool | boolean | series_bool | plain
btree, for table "_timescaledb_internal._hyper_1_1_0_2_data", predicate (series_bool IS NOT NULL)
Index "_timescaledb_internal.11-testNs_device_id_timeCustom_idx"
Index "_timescaledb_internal.12-testNs_timeCustom_device_id_idx"
Column | Type | Definition | Storage
------------+--------+--------------+----------
timeCustom | bigint | "timeCustom" | plain
device_id | text | device_id | extended
btree, for table "_timescaledb_internal._hyper_1_1_0_2_data"
Index "_timescaledb_internal.13-testNs_device_id_timeCustom_idx"
Column | Type | Definition | Storage
------------+--------+--------------+----------
device_id | text | device_id | extended
timeCustom | bigint | "timeCustom" | plain
btree, for table "_timescaledb_internal._hyper_1_2_0_3_data", predicate (device_id IS NOT NULL)
Index "_timescaledb_internal.12-testNs_timeCustom_series_0_idx"
Index "_timescaledb_internal.14-testNs_timeCustom_series_0_idx"
Column | Type | Definition | Storage
------------+------------------+--------------+---------
timeCustom | bigint | "timeCustom" | plain
series_0 | double precision | series_0 | plain
btree, for table "_timescaledb_internal._hyper_1_2_0_3_data", predicate (series_0 IS NOT NULL)
Index "_timescaledb_internal.13-testNs_timeCustom_series_1_idx"
Index "_timescaledb_internal.15-testNs_timeCustom_series_1_idx"
Column | Type | Definition | Storage
------------+------------------+--------------+---------
timeCustom | bigint | "timeCustom" | plain
series_1 | double precision | series_1 | plain
btree, for table "_timescaledb_internal._hyper_1_2_0_3_data", predicate (series_1 IS NOT NULL)
Index "_timescaledb_internal.14-testNs_timeCustom_series_2_idx"
Index "_timescaledb_internal.16-testNs_timeCustom_series_2_idx"
Column | Type | Definition | Storage
------------+------------------+--------------+---------
timeCustom | bigint | "timeCustom" | plain
series_2 | double precision | series_2 | plain
btree, for table "_timescaledb_internal._hyper_1_2_0_3_data", predicate (series_2 IS NOT NULL)
Index "_timescaledb_internal.15-testNs_timeCustom_series_bool_idx"
Index "_timescaledb_internal.17-testNs_timeCustom_series_bool_idx"
Column | Type | Definition | Storage
-------------+---------+--------------+---------
timeCustom | bigint | "timeCustom" | plain
series_bool | boolean | series_bool | plain
btree, for table "_timescaledb_internal._hyper_1_2_0_3_data", predicate (series_bool IS NOT NULL)
Index "_timescaledb_internal.18-testNs_timeCustom_device_id_idx"
Column | Type | Definition | Storage
------------+--------+--------------+----------
timeCustom | bigint | "timeCustom" | plain
device_id | text | device_id | extended
btree, for table "_timescaledb_internal._hyper_1_2_0_3_data"
Index "_timescaledb_internal.2-testNs_timeCustom_series_0_idx"
Column | Type | Definition | Storage
------------+------------------+--------------+---------
@ -142,34 +164,34 @@ Index "_timescaledb_internal.5-testNs_timeCustom_series_bool_idx"
series_bool | boolean | series_bool | plain
btree, for table "_timescaledb_internal._hyper_1_1_0_1_data", predicate (series_bool IS NOT NULL)
Index "_timescaledb_internal.6-testNs_device_id_timeCustom_idx"
Index "_timescaledb_internal.6-testNs_timeCustom_device_id_idx"
Column | Type | Definition | Storage
------------+--------+--------------+----------
timeCustom | bigint | "timeCustom" | plain
device_id | text | device_id | extended
btree, for table "_timescaledb_internal._hyper_1_1_0_1_data"
Index "_timescaledb_internal.7-testNs_device_id_timeCustom_idx"
Column | Type | Definition | Storage
------------+--------+--------------+----------
device_id | text | device_id | extended
timeCustom | bigint | "timeCustom" | plain
btree, for table "_timescaledb_internal._hyper_1_1_0_2_data", predicate (device_id IS NOT NULL)
Index "_timescaledb_internal.7-testNs_timeCustom_series_0_idx"
Index "_timescaledb_internal.8-testNs_timeCustom_series_0_idx"
Column | Type | Definition | Storage
------------+------------------+--------------+---------
timeCustom | bigint | "timeCustom" | plain
series_0 | double precision | series_0 | plain
btree, for table "_timescaledb_internal._hyper_1_1_0_2_data", predicate (series_0 IS NOT NULL)
Index "_timescaledb_internal.8-testNs_timeCustom_series_1_idx"
Index "_timescaledb_internal.9-testNs_timeCustom_series_1_idx"
Column | Type | Definition | Storage
------------+------------------+--------------+---------
timeCustom | bigint | "timeCustom" | plain
series_1 | double precision | series_1 | plain
btree, for table "_timescaledb_internal._hyper_1_1_0_2_data", predicate (series_1 IS NOT NULL)
Index "_timescaledb_internal.9-testNs_timeCustom_series_2_idx"
Column | Type | Definition | Storage
------------+------------------+--------------+---------
timeCustom | bigint | "timeCustom" | plain
series_2 | double precision | series_2 | plain
btree, for table "_timescaledb_internal._hyper_1_1_0_2_data", predicate (series_2 IS NOT NULL)
Table "_timescaledb_internal._hyper_1_0_replica"
Column | Type | Modifiers | Storage | Stats target | Description
-------------+------------------+-----------+----------+--------------+-------------
@ -198,6 +220,7 @@ Indexes:
"3-testNs_timeCustom_series_1_idx" btree ("timeCustom" DESC NULLS LAST, series_1) WHERE series_1 IS NOT NULL
"4-testNs_timeCustom_series_2_idx" btree ("timeCustom" DESC NULLS LAST, series_2) WHERE series_2 IS NOT NULL
"5-testNs_timeCustom_series_bool_idx" btree ("timeCustom" DESC NULLS LAST, series_bool) WHERE series_bool IS NOT NULL
"6-testNs_timeCustom_device_id_idx" btree ("timeCustom" DESC NULLS LAST, device_id)
Check constraints:
"partition" CHECK (_timescaledb_catalog.get_partition_for_key(device_id, 32768) >= '0'::smallint AND _timescaledb_catalog.get_partition_for_key(device_id, 32768) <= '16383'::smallint)
"time_range" CHECK ("timeCustom" <= '1257897600000000000'::bigint) NOT VALID
@ -213,11 +236,12 @@ Inherits: _timescaledb_internal._hyper_1_1_0_partition
series_2 | double precision | | plain | |
series_bool | boolean | | plain | |
Indexes:
"10-testNs_timeCustom_series_bool_idx" btree ("timeCustom" DESC NULLS LAST, series_bool) WHERE series_bool IS NOT NULL
"6-testNs_device_id_timeCustom_idx" btree (device_id, "timeCustom" DESC NULLS LAST) WHERE device_id IS NOT NULL
"7-testNs_timeCustom_series_0_idx" btree ("timeCustom" DESC NULLS LAST, series_0) WHERE series_0 IS NOT NULL
"8-testNs_timeCustom_series_1_idx" btree ("timeCustom" DESC NULLS LAST, series_1) WHERE series_1 IS NOT NULL
"9-testNs_timeCustom_series_2_idx" btree ("timeCustom" DESC NULLS LAST, series_2) WHERE series_2 IS NOT NULL
"10-testNs_timeCustom_series_2_idx" btree ("timeCustom" DESC NULLS LAST, series_2) WHERE series_2 IS NOT NULL
"11-testNs_timeCustom_series_bool_idx" btree ("timeCustom" DESC NULLS LAST, series_bool) WHERE series_bool IS NOT NULL
"12-testNs_timeCustom_device_id_idx" btree ("timeCustom" DESC NULLS LAST, device_id)
"7-testNs_device_id_timeCustom_idx" btree (device_id, "timeCustom" DESC NULLS LAST) WHERE device_id IS NOT NULL
"8-testNs_timeCustom_series_0_idx" btree ("timeCustom" DESC NULLS LAST, series_0) WHERE series_0 IS NOT NULL
"9-testNs_timeCustom_series_1_idx" btree ("timeCustom" DESC NULLS LAST, series_1) WHERE series_1 IS NOT NULL
Check constraints:
"partition" CHECK (_timescaledb_catalog.get_partition_for_key(device_id, 32768) >= '0'::smallint AND _timescaledb_catalog.get_partition_for_key(device_id, 32768) <= '16383'::smallint)
"time_range" CHECK ("timeCustom" >= '1257897600000000001'::bigint) NOT VALID
@ -248,11 +272,12 @@ Child tables: _timescaledb_internal._hyper_1_1_0_1_data,
series_2 | double precision | | plain | |
series_bool | boolean | | plain | |
Indexes:
"11-testNs_device_id_timeCustom_idx" btree (device_id, "timeCustom" DESC NULLS LAST) WHERE device_id IS NOT NULL
"12-testNs_timeCustom_series_0_idx" btree ("timeCustom" DESC NULLS LAST, series_0) WHERE series_0 IS NOT NULL
"13-testNs_timeCustom_series_1_idx" btree ("timeCustom" DESC NULLS LAST, series_1) WHERE series_1 IS NOT NULL
"14-testNs_timeCustom_series_2_idx" btree ("timeCustom" DESC NULLS LAST, series_2) WHERE series_2 IS NOT NULL
"15-testNs_timeCustom_series_bool_idx" btree ("timeCustom" DESC NULLS LAST, series_bool) WHERE series_bool IS NOT NULL
"13-testNs_device_id_timeCustom_idx" btree (device_id, "timeCustom" DESC NULLS LAST) WHERE device_id IS NOT NULL
"14-testNs_timeCustom_series_0_idx" btree ("timeCustom" DESC NULLS LAST, series_0) WHERE series_0 IS NOT NULL
"15-testNs_timeCustom_series_1_idx" btree ("timeCustom" DESC NULLS LAST, series_1) WHERE series_1 IS NOT NULL
"16-testNs_timeCustom_series_2_idx" btree ("timeCustom" DESC NULLS LAST, series_2) WHERE series_2 IS NOT NULL
"17-testNs_timeCustom_series_bool_idx" btree ("timeCustom" DESC NULLS LAST, series_bool) WHERE series_bool IS NOT NULL
"18-testNs_timeCustom_device_id_idx" btree ("timeCustom" DESC NULLS LAST, device_id)
Check constraints:
"partition" CHECK (_timescaledb_catalog.get_partition_for_key(device_id, 32768) >= '16384'::smallint AND _timescaledb_catalog.get_partition_for_key(device_id, 32768) <= '32767'::smallint)
Inherits: _timescaledb_internal._hyper_1_2_0_partition
@ -386,20 +411,23 @@ drop cascades to table _timescaledb_internal._hyper_1_1_0_2_data
drop cascades to table _timescaledb_internal._hyper_1_2_0_partition
drop cascades to table _timescaledb_internal._hyper_1_2_0_3_data
NOTICE: index "1-testNs_device_id_timeCustom_idx" does not exist, skipping
NOTICE: index "6-testNs_device_id_timeCustom_idx" does not exist, skipping
NOTICE: index "11-testNs_device_id_timeCustom_idx" does not exist, skipping
NOTICE: index "7-testNs_device_id_timeCustom_idx" does not exist, skipping
NOTICE: index "13-testNs_device_id_timeCustom_idx" does not exist, skipping
NOTICE: index "2-testNs_timeCustom_series_0_idx" does not exist, skipping
NOTICE: index "7-testNs_timeCustom_series_0_idx" does not exist, skipping
NOTICE: index "12-testNs_timeCustom_series_0_idx" does not exist, skipping
NOTICE: index "8-testNs_timeCustom_series_0_idx" does not exist, skipping
NOTICE: index "14-testNs_timeCustom_series_0_idx" does not exist, skipping
NOTICE: index "3-testNs_timeCustom_series_1_idx" does not exist, skipping
NOTICE: index "8-testNs_timeCustom_series_1_idx" does not exist, skipping
NOTICE: index "13-testNs_timeCustom_series_1_idx" does not exist, skipping
NOTICE: index "9-testNs_timeCustom_series_1_idx" does not exist, skipping
NOTICE: index "15-testNs_timeCustom_series_1_idx" does not exist, skipping
NOTICE: index "4-testNs_timeCustom_series_2_idx" does not exist, skipping
NOTICE: index "9-testNs_timeCustom_series_2_idx" does not exist, skipping
NOTICE: index "14-testNs_timeCustom_series_2_idx" does not exist, skipping
NOTICE: index "10-testNs_timeCustom_series_2_idx" does not exist, skipping
NOTICE: index "16-testNs_timeCustom_series_2_idx" does not exist, skipping
NOTICE: index "5-testNs_timeCustom_series_bool_idx" does not exist, skipping
NOTICE: index "10-testNs_timeCustom_series_bool_idx" does not exist, skipping
NOTICE: index "15-testNs_timeCustom_series_bool_idx" does not exist, skipping
NOTICE: index "11-testNs_timeCustom_series_bool_idx" does not exist, skipping
NOTICE: index "17-testNs_timeCustom_series_bool_idx" does not exist, skipping
NOTICE: index "6-testNs_timeCustom_device_id_idx" does not exist, skipping
NOTICE: index "12-testNs_timeCustom_device_id_idx" does not exist, skipping
NOTICE: index "18-testNs_timeCustom_device_id_idx" does not exist, skipping
SELECT * FROM _timescaledb_catalog.hypertable;
id | schema_name | table_name | associated_schema_name | associated_table_prefix | root_schema_name | root_table_name | replication_factor | placement | time_column_name | time_column_type | created_on | chunk_size_bytes
----+-------------+--------------------+------------------------+-------------------------+-----------------------+-----------------+--------------------+-----------+------------------+------------------+------------+------------------

View File

@ -34,6 +34,7 @@ CREATE INDEX ON PUBLIC."testNs" ("timeCustom" DESC NULLS LAST, series_0) WHERE s
CREATE INDEX ON PUBLIC."testNs" ("timeCustom" DESC NULLS LAST, series_1) WHERE series_1 IS NOT NULL;
CREATE INDEX ON PUBLIC."testNs" ("timeCustom" DESC NULLS LAST, series_2) WHERE series_2 IS NOT NULL;
CREATE INDEX ON PUBLIC."testNs" ("timeCustom" DESC NULLS LAST, series_bool) WHERE series_bool IS NOT NULL;
CREATE INDEX ON PUBLIC."testNs" ("timeCustom" DESC NULLS LAST, device_id);
SELECT * FROM create_hypertable('"public"."testNs"'::regclass, 'timeCustom'::name, 'device_id'::name, associated_schema_name=>'_timescaledb_internal'::text, number_partitions => 2);
create_hypertable
-------------------
@ -101,48 +102,69 @@ Index "_timescaledb_internal.1-testNs_device_id_timeCustom_idx"
timeCustom | bigint | "timeCustom" | plain
btree, for table "_timescaledb_internal._hyper_1_1_0_1_data", predicate (device_id IS NOT NULL)
Index "_timescaledb_internal.10-testNs_timeCustom_series_bool_idx"
Index "_timescaledb_internal.10-testNs_timeCustom_series_2_idx"
Column | Type | Definition | Storage
------------+------------------+--------------+---------
timeCustom | bigint | "timeCustom" | plain
series_2 | double precision | series_2 | plain
btree, for table "_timescaledb_internal._hyper_1_1_0_2_data", predicate (series_2 IS NOT NULL)
Index "_timescaledb_internal.11-testNs_timeCustom_series_bool_idx"
Column | Type | Definition | Storage
-------------+---------+--------------+---------
timeCustom | bigint | "timeCustom" | plain
series_bool | boolean | series_bool | plain
btree, for table "_timescaledb_internal._hyper_1_1_0_2_data", predicate (series_bool IS NOT NULL)
Index "_timescaledb_internal.11-testNs_device_id_timeCustom_idx"
Index "_timescaledb_internal.12-testNs_timeCustom_device_id_idx"
Column | Type | Definition | Storage
------------+--------+--------------+----------
timeCustom | bigint | "timeCustom" | plain
device_id | text | device_id | extended
btree, for table "_timescaledb_internal._hyper_1_1_0_2_data"
Index "_timescaledb_internal.13-testNs_device_id_timeCustom_idx"
Column | Type | Definition | Storage
------------+--------+--------------+----------
device_id | text | device_id | extended
timeCustom | bigint | "timeCustom" | plain
btree, for table "_timescaledb_internal._hyper_1_2_0_3_data", predicate (device_id IS NOT NULL)
Index "_timescaledb_internal.12-testNs_timeCustom_series_0_idx"
Index "_timescaledb_internal.14-testNs_timeCustom_series_0_idx"
Column | Type | Definition | Storage
------------+------------------+--------------+---------
timeCustom | bigint | "timeCustom" | plain
series_0 | double precision | series_0 | plain
btree, for table "_timescaledb_internal._hyper_1_2_0_3_data", predicate (series_0 IS NOT NULL)
Index "_timescaledb_internal.13-testNs_timeCustom_series_1_idx"
Index "_timescaledb_internal.15-testNs_timeCustom_series_1_idx"
Column | Type | Definition | Storage
------------+------------------+--------------+---------
timeCustom | bigint | "timeCustom" | plain
series_1 | double precision | series_1 | plain
btree, for table "_timescaledb_internal._hyper_1_2_0_3_data", predicate (series_1 IS NOT NULL)
Index "_timescaledb_internal.14-testNs_timeCustom_series_2_idx"
Index "_timescaledb_internal.16-testNs_timeCustom_series_2_idx"
Column | Type | Definition | Storage
------------+------------------+--------------+---------
timeCustom | bigint | "timeCustom" | plain
series_2 | double precision | series_2 | plain
btree, for table "_timescaledb_internal._hyper_1_2_0_3_data", predicate (series_2 IS NOT NULL)
Index "_timescaledb_internal.15-testNs_timeCustom_series_bool_idx"
Index "_timescaledb_internal.17-testNs_timeCustom_series_bool_idx"
Column | Type | Definition | Storage
-------------+---------+--------------+---------
timeCustom | bigint | "timeCustom" | plain
series_bool | boolean | series_bool | plain
btree, for table "_timescaledb_internal._hyper_1_2_0_3_data", predicate (series_bool IS NOT NULL)
Index "_timescaledb_internal.18-testNs_timeCustom_device_id_idx"
Column | Type | Definition | Storage
------------+--------+--------------+----------
timeCustom | bigint | "timeCustom" | plain
device_id | text | device_id | extended
btree, for table "_timescaledb_internal._hyper_1_2_0_3_data"
Index "_timescaledb_internal.2-testNs_timeCustom_series_0_idx"
Column | Type | Definition | Storage
------------+------------------+--------------+---------
@ -171,34 +193,34 @@ Index "_timescaledb_internal.5-testNs_timeCustom_series_bool_idx"
series_bool | boolean | series_bool | plain
btree, for table "_timescaledb_internal._hyper_1_1_0_1_data", predicate (series_bool IS NOT NULL)
Index "_timescaledb_internal.6-testNs_device_id_timeCustom_idx"
Index "_timescaledb_internal.6-testNs_timeCustom_device_id_idx"
Column | Type | Definition | Storage
------------+--------+--------------+----------
timeCustom | bigint | "timeCustom" | plain
device_id | text | device_id | extended
btree, for table "_timescaledb_internal._hyper_1_1_0_1_data"
Index "_timescaledb_internal.7-testNs_device_id_timeCustom_idx"
Column | Type | Definition | Storage
------------+--------+--------------+----------
device_id | text | device_id | extended
timeCustom | bigint | "timeCustom" | plain
btree, for table "_timescaledb_internal._hyper_1_1_0_2_data", predicate (device_id IS NOT NULL)
Index "_timescaledb_internal.7-testNs_timeCustom_series_0_idx"
Index "_timescaledb_internal.8-testNs_timeCustom_series_0_idx"
Column | Type | Definition | Storage
------------+------------------+--------------+---------
timeCustom | bigint | "timeCustom" | plain
series_0 | double precision | series_0 | plain
btree, for table "_timescaledb_internal._hyper_1_1_0_2_data", predicate (series_0 IS NOT NULL)
Index "_timescaledb_internal.8-testNs_timeCustom_series_1_idx"
Index "_timescaledb_internal.9-testNs_timeCustom_series_1_idx"
Column | Type | Definition | Storage
------------+------------------+--------------+---------
timeCustom | bigint | "timeCustom" | plain
series_1 | double precision | series_1 | plain
btree, for table "_timescaledb_internal._hyper_1_1_0_2_data", predicate (series_1 IS NOT NULL)
Index "_timescaledb_internal.9-testNs_timeCustom_series_2_idx"
Column | Type | Definition | Storage
------------+------------------+--------------+---------
timeCustom | bigint | "timeCustom" | plain
series_2 | double precision | series_2 | plain
btree, for table "_timescaledb_internal._hyper_1_1_0_2_data", predicate (series_2 IS NOT NULL)
Table "_timescaledb_internal._hyper_1_0_replica"
Column | Type | Modifiers | Storage | Stats target | Description
-------------+------------------+-----------+----------+--------------+-------------
@ -227,6 +249,7 @@ Indexes:
"3-testNs_timeCustom_series_1_idx" btree ("timeCustom" DESC NULLS LAST, series_1) WHERE series_1 IS NOT NULL
"4-testNs_timeCustom_series_2_idx" btree ("timeCustom" DESC NULLS LAST, series_2) WHERE series_2 IS NOT NULL
"5-testNs_timeCustom_series_bool_idx" btree ("timeCustom" DESC NULLS LAST, series_bool) WHERE series_bool IS NOT NULL
"6-testNs_timeCustom_device_id_idx" btree ("timeCustom" DESC NULLS LAST, device_id)
Check constraints:
"partition" CHECK (_timescaledb_catalog.get_partition_for_key(device_id, 32768) >= '0'::smallint AND _timescaledb_catalog.get_partition_for_key(device_id, 32768) <= '16383'::smallint)
"time_range" CHECK ("timeCustom" <= '1257897600000000000'::bigint) NOT VALID
@ -242,11 +265,12 @@ Inherits: _timescaledb_internal._hyper_1_1_0_partition
series_2 | double precision | | plain | |
series_bool | boolean | | plain | |
Indexes:
"10-testNs_timeCustom_series_bool_idx" btree ("timeCustom" DESC NULLS LAST, series_bool) WHERE series_bool IS NOT NULL
"6-testNs_device_id_timeCustom_idx" btree (device_id, "timeCustom" DESC NULLS LAST) WHERE device_id IS NOT NULL
"7-testNs_timeCustom_series_0_idx" btree ("timeCustom" DESC NULLS LAST, series_0) WHERE series_0 IS NOT NULL
"8-testNs_timeCustom_series_1_idx" btree ("timeCustom" DESC NULLS LAST, series_1) WHERE series_1 IS NOT NULL
"9-testNs_timeCustom_series_2_idx" btree ("timeCustom" DESC NULLS LAST, series_2) WHERE series_2 IS NOT NULL
"10-testNs_timeCustom_series_2_idx" btree ("timeCustom" DESC NULLS LAST, series_2) WHERE series_2 IS NOT NULL
"11-testNs_timeCustom_series_bool_idx" btree ("timeCustom" DESC NULLS LAST, series_bool) WHERE series_bool IS NOT NULL
"12-testNs_timeCustom_device_id_idx" btree ("timeCustom" DESC NULLS LAST, device_id)
"7-testNs_device_id_timeCustom_idx" btree (device_id, "timeCustom" DESC NULLS LAST) WHERE device_id IS NOT NULL
"8-testNs_timeCustom_series_0_idx" btree ("timeCustom" DESC NULLS LAST, series_0) WHERE series_0 IS NOT NULL
"9-testNs_timeCustom_series_1_idx" btree ("timeCustom" DESC NULLS LAST, series_1) WHERE series_1 IS NOT NULL
Check constraints:
"partition" CHECK (_timescaledb_catalog.get_partition_for_key(device_id, 32768) >= '0'::smallint AND _timescaledb_catalog.get_partition_for_key(device_id, 32768) <= '16383'::smallint)
"time_range" CHECK ("timeCustom" >= '1257897600000000001'::bigint) NOT VALID
@ -277,11 +301,12 @@ Child tables: _timescaledb_internal._hyper_1_1_0_1_data,
series_2 | double precision | | plain | |
series_bool | boolean | | plain | |
Indexes:
"11-testNs_device_id_timeCustom_idx" btree (device_id, "timeCustom" DESC NULLS LAST) WHERE device_id IS NOT NULL
"12-testNs_timeCustom_series_0_idx" btree ("timeCustom" DESC NULLS LAST, series_0) WHERE series_0 IS NOT NULL
"13-testNs_timeCustom_series_1_idx" btree ("timeCustom" DESC NULLS LAST, series_1) WHERE series_1 IS NOT NULL
"14-testNs_timeCustom_series_2_idx" btree ("timeCustom" DESC NULLS LAST, series_2) WHERE series_2 IS NOT NULL
"15-testNs_timeCustom_series_bool_idx" btree ("timeCustom" DESC NULLS LAST, series_bool) WHERE series_bool IS NOT NULL
"13-testNs_device_id_timeCustom_idx" btree (device_id, "timeCustom" DESC NULLS LAST) WHERE device_id IS NOT NULL
"14-testNs_timeCustom_series_0_idx" btree ("timeCustom" DESC NULLS LAST, series_0) WHERE series_0 IS NOT NULL
"15-testNs_timeCustom_series_1_idx" btree ("timeCustom" DESC NULLS LAST, series_1) WHERE series_1 IS NOT NULL
"16-testNs_timeCustom_series_2_idx" btree ("timeCustom" DESC NULLS LAST, series_2) WHERE series_2 IS NOT NULL
"17-testNs_timeCustom_series_bool_idx" btree ("timeCustom" DESC NULLS LAST, series_bool) WHERE series_bool IS NOT NULL
"18-testNs_timeCustom_device_id_idx" btree ("timeCustom" DESC NULLS LAST, device_id)
Check constraints:
"partition" CHECK (_timescaledb_catalog.get_partition_for_key(device_id, 32768) >= '16384'::smallint AND _timescaledb_catalog.get_partition_for_key(device_id, 32768) <= '32767'::smallint)
Inherits: _timescaledb_internal._hyper_1_2_0_partition

View File

@ -31,6 +31,7 @@ CREATE INDEX ON PUBLIC."testNs" ("timeCustom" DESC NULLS LAST, series_0) WHERE s
CREATE INDEX ON PUBLIC."testNs" ("timeCustom" DESC NULLS LAST, series_1) WHERE series_1 IS NOT NULL;
CREATE INDEX ON PUBLIC."testNs" ("timeCustom" DESC NULLS LAST, series_2) WHERE series_2 IS NOT NULL;
CREATE INDEX ON PUBLIC."testNs" ("timeCustom" DESC NULLS LAST, series_bool) WHERE series_bool IS NOT NULL;
CREATE INDEX ON PUBLIC."testNs" ("timeCustom" DESC NULLS LAST, device_id);
SELECT * FROM create_hypertable('"public"."testNs"'::regclass, 'timeCustom'::name, 'device_id'::name, associated_schema_name=>'_timescaledb_internal'::text, number_partitions => 2);
BEGIN;
\COPY public."testNs" FROM 'data/ds1_dev1_1.tsv' NULL AS '';

View File

@ -29,6 +29,7 @@ CREATE INDEX ON PUBLIC."testNs" ("timeCustom" DESC NULLS LAST, series_0) WHERE s
CREATE INDEX ON PUBLIC."testNs" ("timeCustom" DESC NULLS LAST, series_1) WHERE series_1 IS NOT NULL;
CREATE INDEX ON PUBLIC."testNs" ("timeCustom" DESC NULLS LAST, series_2) WHERE series_2 IS NOT NULL;
CREATE INDEX ON PUBLIC."testNs" ("timeCustom" DESC NULLS LAST, series_bool) WHERE series_bool IS NOT NULL;
CREATE INDEX ON PUBLIC."testNs" ("timeCustom" DESC NULLS LAST, device_id);
SELECT * FROM create_hypertable('"public"."testNs"'::regclass, 'timeCustom'::name, 'device_id'::name, associated_schema_name=>'_timescaledb_internal'::text, number_partitions => 2);
BEGIN;
\COPY public."testNs" FROM 'data/ds1_dev1_1.tsv' NULL AS '';
@ -111,7 +112,7 @@ EXPLAIN (verbose ON, costs off) SELECT * FROM PUBLIC."testNs" WHERE device_id =
Output: _hyper_1_2_0_3_data."timeCustom", _hyper_1_2_0_3_data.device_id, _hyper_1_2_0_3_data.series_0, _hyper_1_2_0_3_data.series_1, _hyper_1_2_0_3_data.series_2, _hyper_1_2_0_3_data.series_bool
Recheck Cond: (_hyper_1_2_0_3_data.device_id = 'dev20'::text)
Filter: (_timescaledb_catalog.get_partition_for_key(_hyper_1_2_0_3_data.device_id, 32768) = '28646'::smallint)
-> Bitmap Index Scan on "11-testNs_device_id_timeCustom_idx"
-> Bitmap Index Scan on "13-testNs_device_id_timeCustom_idx"
Index Cond: (_hyper_1_2_0_3_data.device_id = 'dev20'::text)
(13 rows)
@ -129,7 +130,7 @@ EXPLAIN (verbose ON, costs off) SELECT * FROM PUBLIC."testNs" WHERE device_id =
Output: _hyper_1_2_0_3_data."timeCustom", _hyper_1_2_0_3_data.device_id, _hyper_1_2_0_3_data.series_0, _hyper_1_2_0_3_data.series_1, _hyper_1_2_0_3_data.series_2, _hyper_1_2_0_3_data.series_bool
Recheck Cond: (_hyper_1_2_0_3_data.device_id = 'dev20'::text)
Filter: (_timescaledb_catalog.get_partition_for_key(_hyper_1_2_0_3_data.device_id, 32768) = '28646'::smallint)
-> Bitmap Index Scan on "11-testNs_device_id_timeCustom_idx"
-> Bitmap Index Scan on "13-testNs_device_id_timeCustom_idx"
Index Cond: (_hyper_1_2_0_3_data.device_id = 'dev20'::text)
(13 rows)
@ -147,9 +148,263 @@ EXPLAIN (verbose ON, costs off) SELECT * FROM PUBLIC."testNs" WHERE 'dev'||'20'
Output: _hyper_1_2_0_3_data."timeCustom", _hyper_1_2_0_3_data.device_id, _hyper_1_2_0_3_data.series_0, _hyper_1_2_0_3_data.series_1, _hyper_1_2_0_3_data.series_2, _hyper_1_2_0_3_data.series_bool
Recheck Cond: ('dev20'::text = _hyper_1_2_0_3_data.device_id)
Filter: (_timescaledb_catalog.get_partition_for_key(_hyper_1_2_0_3_data.device_id, 32768) = '28646'::smallint)
-> Bitmap Index Scan on "11-testNs_device_id_timeCustom_idx"
-> Bitmap Index Scan on "13-testNs_device_id_timeCustom_idx"
Index Cond: ('dev20'::text = _hyper_1_2_0_3_data.device_id)
(13 rows)
--TODO: handle this later?
--EXPLAIN (verbose ON, costs off) SELECT * FROM "testNs" WHERE device_id IN ('dev20', 'dev21');
\echo "The following shows non-aggregated queries with time desc using merge append"
"The following shows non-aggregated queries with time desc using merge append"
EXPLAIN (verbose ON, costs off)SELECT * FROM PUBLIC."testNs" ORDER BY "timeCustom" DESC NULLS LAST limit 2;
QUERY PLAN
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Limit
Output: _hyper_1_0_replica."timeCustom", _hyper_1_0_replica.device_id, _hyper_1_0_replica.series_0, _hyper_1_0_replica.series_1, _hyper_1_0_replica.series_2, _hyper_1_0_replica.series_bool
-> Merge Append
Sort Key: _hyper_1_0_replica."timeCustom" DESC NULLS LAST
-> Sort
Output: _hyper_1_0_replica."timeCustom", _hyper_1_0_replica.device_id, _hyper_1_0_replica.series_0, _hyper_1_0_replica.series_1, _hyper_1_0_replica.series_2, _hyper_1_0_replica.series_bool
Sort Key: _hyper_1_0_replica."timeCustom" DESC NULLS LAST
-> Seq Scan on _timescaledb_internal._hyper_1_0_replica
Output: _hyper_1_0_replica."timeCustom", _hyper_1_0_replica.device_id, _hyper_1_0_replica.series_0, _hyper_1_0_replica.series_1, _hyper_1_0_replica.series_2, _hyper_1_0_replica.series_bool
-> Sort
Output: _hyper_1_1_0_partition."timeCustom", _hyper_1_1_0_partition.device_id, _hyper_1_1_0_partition.series_0, _hyper_1_1_0_partition.series_1, _hyper_1_1_0_partition.series_2, _hyper_1_1_0_partition.series_bool
Sort Key: _hyper_1_1_0_partition."timeCustom" DESC NULLS LAST
-> Seq Scan on _timescaledb_internal._hyper_1_1_0_partition
Output: _hyper_1_1_0_partition."timeCustom", _hyper_1_1_0_partition.device_id, _hyper_1_1_0_partition.series_0, _hyper_1_1_0_partition.series_1, _hyper_1_1_0_partition.series_2, _hyper_1_1_0_partition.series_bool
-> Sort
Output: _hyper_1_2_0_partition."timeCustom", _hyper_1_2_0_partition.device_id, _hyper_1_2_0_partition.series_0, _hyper_1_2_0_partition.series_1, _hyper_1_2_0_partition.series_2, _hyper_1_2_0_partition.series_bool
Sort Key: _hyper_1_2_0_partition."timeCustom" DESC NULLS LAST
-> Seq Scan on _timescaledb_internal._hyper_1_2_0_partition
Output: _hyper_1_2_0_partition."timeCustom", _hyper_1_2_0_partition.device_id, _hyper_1_2_0_partition.series_0, _hyper_1_2_0_partition.series_1, _hyper_1_2_0_partition.series_2, _hyper_1_2_0_partition.series_bool
-> Index Scan using "6-testNs_timeCustom_device_id_idx" on _timescaledb_internal._hyper_1_1_0_1_data
Output: _hyper_1_1_0_1_data."timeCustom", _hyper_1_1_0_1_data.device_id, _hyper_1_1_0_1_data.series_0, _hyper_1_1_0_1_data.series_1, _hyper_1_1_0_1_data.series_2, _hyper_1_1_0_1_data.series_bool
-> Index Scan using "12-testNs_timeCustom_device_id_idx" on _timescaledb_internal._hyper_1_1_0_2_data
Output: _hyper_1_1_0_2_data."timeCustom", _hyper_1_1_0_2_data.device_id, _hyper_1_1_0_2_data.series_0, _hyper_1_1_0_2_data.series_1, _hyper_1_1_0_2_data.series_2, _hyper_1_1_0_2_data.series_bool
-> Index Scan using "18-testNs_timeCustom_device_id_idx" on _timescaledb_internal._hyper_1_2_0_3_data
Output: _hyper_1_2_0_3_data."timeCustom", _hyper_1_2_0_3_data.device_id, _hyper_1_2_0_3_data.series_0, _hyper_1_2_0_3_data.series_1, _hyper_1_2_0_3_data.series_2, _hyper_1_2_0_3_data.series_bool
(25 rows)
--shows that more specific indexes are used if the WHERE clauses "match", uses the series_1 index here.
EXPLAIN (verbose ON, costs off)SELECT * FROM PUBLIC."testNs" WHERE series_1 IS NOT NULL ORDER BY "timeCustom" DESC NULLS LAST limit 2;
QUERY PLAN
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Limit
Output: _hyper_1_0_replica."timeCustom", _hyper_1_0_replica.device_id, _hyper_1_0_replica.series_0, _hyper_1_0_replica.series_1, _hyper_1_0_replica.series_2, _hyper_1_0_replica.series_bool
-> Merge Append
Sort Key: _hyper_1_0_replica."timeCustom" DESC NULLS LAST
-> Sort
Output: _hyper_1_0_replica."timeCustom", _hyper_1_0_replica.device_id, _hyper_1_0_replica.series_0, _hyper_1_0_replica.series_1, _hyper_1_0_replica.series_2, _hyper_1_0_replica.series_bool
Sort Key: _hyper_1_0_replica."timeCustom" DESC NULLS LAST
-> Seq Scan on _timescaledb_internal._hyper_1_0_replica
Output: _hyper_1_0_replica."timeCustom", _hyper_1_0_replica.device_id, _hyper_1_0_replica.series_0, _hyper_1_0_replica.series_1, _hyper_1_0_replica.series_2, _hyper_1_0_replica.series_bool
Filter: (_hyper_1_0_replica.series_1 IS NOT NULL)
-> Sort
Output: _hyper_1_1_0_partition."timeCustom", _hyper_1_1_0_partition.device_id, _hyper_1_1_0_partition.series_0, _hyper_1_1_0_partition.series_1, _hyper_1_1_0_partition.series_2, _hyper_1_1_0_partition.series_bool
Sort Key: _hyper_1_1_0_partition."timeCustom" DESC NULLS LAST
-> Seq Scan on _timescaledb_internal._hyper_1_1_0_partition
Output: _hyper_1_1_0_partition."timeCustom", _hyper_1_1_0_partition.device_id, _hyper_1_1_0_partition.series_0, _hyper_1_1_0_partition.series_1, _hyper_1_1_0_partition.series_2, _hyper_1_1_0_partition.series_bool
Filter: (_hyper_1_1_0_partition.series_1 IS NOT NULL)
-> Sort
Output: _hyper_1_2_0_partition."timeCustom", _hyper_1_2_0_partition.device_id, _hyper_1_2_0_partition.series_0, _hyper_1_2_0_partition.series_1, _hyper_1_2_0_partition.series_2, _hyper_1_2_0_partition.series_bool
Sort Key: _hyper_1_2_0_partition."timeCustom" DESC NULLS LAST
-> Seq Scan on _timescaledb_internal._hyper_1_2_0_partition
Output: _hyper_1_2_0_partition."timeCustom", _hyper_1_2_0_partition.device_id, _hyper_1_2_0_partition.series_0, _hyper_1_2_0_partition.series_1, _hyper_1_2_0_partition.series_2, _hyper_1_2_0_partition.series_bool
Filter: (_hyper_1_2_0_partition.series_1 IS NOT NULL)
-> Index Scan using "3-testNs_timeCustom_series_1_idx" on _timescaledb_internal._hyper_1_1_0_1_data
Output: _hyper_1_1_0_1_data."timeCustom", _hyper_1_1_0_1_data.device_id, _hyper_1_1_0_1_data.series_0, _hyper_1_1_0_1_data.series_1, _hyper_1_1_0_1_data.series_2, _hyper_1_1_0_1_data.series_bool
-> Index Scan using "9-testNs_timeCustom_series_1_idx" on _timescaledb_internal._hyper_1_1_0_2_data
Output: _hyper_1_1_0_2_data."timeCustom", _hyper_1_1_0_2_data.device_id, _hyper_1_1_0_2_data.series_0, _hyper_1_1_0_2_data.series_1, _hyper_1_1_0_2_data.series_2, _hyper_1_1_0_2_data.series_bool
-> Index Scan using "15-testNs_timeCustom_series_1_idx" on _timescaledb_internal._hyper_1_2_0_3_data
Output: _hyper_1_2_0_3_data."timeCustom", _hyper_1_2_0_3_data.device_id, _hyper_1_2_0_3_data.series_0, _hyper_1_2_0_3_data.series_1, _hyper_1_2_0_3_data.series_2, _hyper_1_2_0_3_data.series_bool
(28 rows)
--here the "match" is implication series_1 > 1 => series_1 IS NOT NULL
EXPLAIN (verbose ON, costs off)SELECT * FROM PUBLIC."testNs" WHERE series_1 > 1 ORDER BY "timeCustom" DESC NULLS LAST limit 2;
QUERY PLAN
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Limit
Output: _hyper_1_0_replica."timeCustom", _hyper_1_0_replica.device_id, _hyper_1_0_replica.series_0, _hyper_1_0_replica.series_1, _hyper_1_0_replica.series_2, _hyper_1_0_replica.series_bool
-> Merge Append
Sort Key: _hyper_1_0_replica."timeCustom" DESC NULLS LAST
-> Sort
Output: _hyper_1_0_replica."timeCustom", _hyper_1_0_replica.device_id, _hyper_1_0_replica.series_0, _hyper_1_0_replica.series_1, _hyper_1_0_replica.series_2, _hyper_1_0_replica.series_bool
Sort Key: _hyper_1_0_replica."timeCustom" DESC NULLS LAST
-> Seq Scan on _timescaledb_internal._hyper_1_0_replica
Output: _hyper_1_0_replica."timeCustom", _hyper_1_0_replica.device_id, _hyper_1_0_replica.series_0, _hyper_1_0_replica.series_1, _hyper_1_0_replica.series_2, _hyper_1_0_replica.series_bool
Filter: (_hyper_1_0_replica.series_1 > '1'::double precision)
-> Sort
Output: _hyper_1_1_0_partition."timeCustom", _hyper_1_1_0_partition.device_id, _hyper_1_1_0_partition.series_0, _hyper_1_1_0_partition.series_1, _hyper_1_1_0_partition.series_2, _hyper_1_1_0_partition.series_bool
Sort Key: _hyper_1_1_0_partition."timeCustom" DESC NULLS LAST
-> Seq Scan on _timescaledb_internal._hyper_1_1_0_partition
Output: _hyper_1_1_0_partition."timeCustom", _hyper_1_1_0_partition.device_id, _hyper_1_1_0_partition.series_0, _hyper_1_1_0_partition.series_1, _hyper_1_1_0_partition.series_2, _hyper_1_1_0_partition.series_bool
Filter: (_hyper_1_1_0_partition.series_1 > '1'::double precision)
-> Sort
Output: _hyper_1_2_0_partition."timeCustom", _hyper_1_2_0_partition.device_id, _hyper_1_2_0_partition.series_0, _hyper_1_2_0_partition.series_1, _hyper_1_2_0_partition.series_2, _hyper_1_2_0_partition.series_bool
Sort Key: _hyper_1_2_0_partition."timeCustom" DESC NULLS LAST
-> Seq Scan on _timescaledb_internal._hyper_1_2_0_partition
Output: _hyper_1_2_0_partition."timeCustom", _hyper_1_2_0_partition.device_id, _hyper_1_2_0_partition.series_0, _hyper_1_2_0_partition.series_1, _hyper_1_2_0_partition.series_2, _hyper_1_2_0_partition.series_bool
Filter: (_hyper_1_2_0_partition.series_1 > '1'::double precision)
-> Index Scan using "3-testNs_timeCustom_series_1_idx" on _timescaledb_internal._hyper_1_1_0_1_data
Output: _hyper_1_1_0_1_data."timeCustom", _hyper_1_1_0_1_data.device_id, _hyper_1_1_0_1_data.series_0, _hyper_1_1_0_1_data.series_1, _hyper_1_1_0_1_data.series_2, _hyper_1_1_0_1_data.series_bool
Index Cond: (_hyper_1_1_0_1_data.series_1 > '1'::double precision)
-> Index Scan using "9-testNs_timeCustom_series_1_idx" on _timescaledb_internal._hyper_1_1_0_2_data
Output: _hyper_1_1_0_2_data."timeCustom", _hyper_1_1_0_2_data.device_id, _hyper_1_1_0_2_data.series_0, _hyper_1_1_0_2_data.series_1, _hyper_1_1_0_2_data.series_2, _hyper_1_1_0_2_data.series_bool
Index Cond: (_hyper_1_1_0_2_data.series_1 > '1'::double precision)
-> Index Scan using "15-testNs_timeCustom_series_1_idx" on _timescaledb_internal._hyper_1_2_0_3_data
Output: _hyper_1_2_0_3_data."timeCustom", _hyper_1_2_0_3_data.device_id, _hyper_1_2_0_3_data.series_0, _hyper_1_2_0_3_data.series_1, _hyper_1_2_0_3_data.series_2, _hyper_1_2_0_3_data.series_bool
Index Cond: (_hyper_1_2_0_3_data.series_1 > '1'::double precision)
(31 rows)
--note that without time transform things work too
EXPLAIN (verbose ON, costs off)SELECT "timeCustom" t, min(series_0) FROM PUBLIC."testNs" GROUP BY t ORDER BY t DESC NULLS LAST limit 2;
QUERY PLAN
----------------------------------------------------------------------------------------------------------------------
Limit
Output: _hyper_1_0_replica."timeCustom", (min(_hyper_1_0_replica.series_0))
-> GroupAggregate
Output: _hyper_1_0_replica."timeCustom", min(_hyper_1_0_replica.series_0)
Group Key: _hyper_1_0_replica."timeCustom"
-> Merge Append
Sort Key: _hyper_1_0_replica."timeCustom" DESC NULLS LAST
-> Sort
Output: _hyper_1_0_replica."timeCustom", _hyper_1_0_replica.series_0
Sort Key: _hyper_1_0_replica."timeCustom" DESC NULLS LAST
-> Seq Scan on _timescaledb_internal._hyper_1_0_replica
Output: _hyper_1_0_replica."timeCustom", _hyper_1_0_replica.series_0
-> Sort
Output: _hyper_1_1_0_partition."timeCustom", _hyper_1_1_0_partition.series_0
Sort Key: _hyper_1_1_0_partition."timeCustom" DESC NULLS LAST
-> Seq Scan on _timescaledb_internal._hyper_1_1_0_partition
Output: _hyper_1_1_0_partition."timeCustom", _hyper_1_1_0_partition.series_0
-> Sort
Output: _hyper_1_2_0_partition."timeCustom", _hyper_1_2_0_partition.series_0
Sort Key: _hyper_1_2_0_partition."timeCustom" DESC NULLS LAST
-> Seq Scan on _timescaledb_internal._hyper_1_2_0_partition
Output: _hyper_1_2_0_partition."timeCustom", _hyper_1_2_0_partition.series_0
-> Index Scan using "6-testNs_timeCustom_device_id_idx" on _timescaledb_internal._hyper_1_1_0_1_data
Output: _hyper_1_1_0_1_data."timeCustom", _hyper_1_1_0_1_data.series_0
-> Index Scan using "12-testNs_timeCustom_device_id_idx" on _timescaledb_internal._hyper_1_1_0_2_data
Output: _hyper_1_1_0_2_data."timeCustom", _hyper_1_1_0_2_data.series_0
-> Index Scan using "18-testNs_timeCustom_device_id_idx" on _timescaledb_internal._hyper_1_2_0_3_data
Output: _hyper_1_2_0_3_data."timeCustom", _hyper_1_2_0_3_data.series_0
(28 rows)
--TODO: time transform doesn't work
EXPLAIN (verbose ON, costs off)SELECT "timeCustom"/10 t, min(series_0) FROM PUBLIC."testNs" GROUP BY t ORDER BY t DESC NULLS LAST limit 2;
QUERY PLAN
--------------------------------------------------------------------------------------------------------------
Limit
Output: ((_hyper_1_0_replica."timeCustom" / 10)), (min(_hyper_1_0_replica.series_0))
-> Sort
Output: ((_hyper_1_0_replica."timeCustom" / 10)), (min(_hyper_1_0_replica.series_0))
Sort Key: ((_hyper_1_0_replica."timeCustom" / 10)) DESC NULLS LAST
-> HashAggregate
Output: ((_hyper_1_0_replica."timeCustom" / 10)), min(_hyper_1_0_replica.series_0)
Group Key: (_hyper_1_0_replica."timeCustom" / 10)
-> Result
Output: (_hyper_1_0_replica."timeCustom" / 10), _hyper_1_0_replica.series_0
-> Append
-> Seq Scan on _timescaledb_internal._hyper_1_0_replica
Output: _hyper_1_0_replica."timeCustom", _hyper_1_0_replica.series_0
-> Seq Scan on _timescaledb_internal._hyper_1_1_0_partition
Output: _hyper_1_1_0_partition."timeCustom", _hyper_1_1_0_partition.series_0
-> Seq Scan on _timescaledb_internal._hyper_1_2_0_partition
Output: _hyper_1_2_0_partition."timeCustom", _hyper_1_2_0_partition.series_0
-> Seq Scan on _timescaledb_internal._hyper_1_1_0_1_data
Output: _hyper_1_1_0_1_data."timeCustom", _hyper_1_1_0_1_data.series_0
-> Seq Scan on _timescaledb_internal._hyper_1_1_0_2_data
Output: _hyper_1_1_0_2_data."timeCustom", _hyper_1_1_0_2_data.series_0
-> Seq Scan on _timescaledb_internal._hyper_1_2_0_3_data
Output: _hyper_1_2_0_3_data."timeCustom", _hyper_1_2_0_3_data.series_0
(23 rows)
EXPLAIN (verbose ON, costs off)SELECT "timeCustom"%10 t, min(series_0) FROM PUBLIC."testNs" GROUP BY t ORDER BY t DESC NULLS LAST limit 2;
QUERY PLAN
--------------------------------------------------------------------------------------------------------------
Limit
Output: ((_hyper_1_0_replica."timeCustom" % '10'::bigint)), (min(_hyper_1_0_replica.series_0))
-> Sort
Output: ((_hyper_1_0_replica."timeCustom" % '10'::bigint)), (min(_hyper_1_0_replica.series_0))
Sort Key: ((_hyper_1_0_replica."timeCustom" % '10'::bigint)) DESC NULLS LAST
-> HashAggregate
Output: ((_hyper_1_0_replica."timeCustom" % '10'::bigint)), min(_hyper_1_0_replica.series_0)
Group Key: (_hyper_1_0_replica."timeCustom" % '10'::bigint)
-> Result
Output: (_hyper_1_0_replica."timeCustom" % '10'::bigint), _hyper_1_0_replica.series_0
-> Append
-> Seq Scan on _timescaledb_internal._hyper_1_0_replica
Output: _hyper_1_0_replica."timeCustom", _hyper_1_0_replica.series_0
-> Seq Scan on _timescaledb_internal._hyper_1_1_0_partition
Output: _hyper_1_1_0_partition."timeCustom", _hyper_1_1_0_partition.series_0
-> Seq Scan on _timescaledb_internal._hyper_1_2_0_partition
Output: _hyper_1_2_0_partition."timeCustom", _hyper_1_2_0_partition.series_0
-> Seq Scan on _timescaledb_internal._hyper_1_1_0_1_data
Output: _hyper_1_1_0_1_data."timeCustom", _hyper_1_1_0_1_data.series_0
-> Seq Scan on _timescaledb_internal._hyper_1_1_0_2_data
Output: _hyper_1_1_0_2_data."timeCustom", _hyper_1_1_0_2_data.series_0
-> Seq Scan on _timescaledb_internal._hyper_1_2_0_3_data
Output: _hyper_1_2_0_3_data."timeCustom", _hyper_1_2_0_3_data.series_0
(23 rows)
--make table with timestamp. Test timestamp instead of int time.
CREATE TABLE PUBLIC.hyper_1 (
time TIMESTAMPTZ NOT NULL,
series_0 DOUBLE PRECISION NULL,
series_1 DOUBLE PRECISION NULL,
series_2 DOUBLE PRECISION NULL
);
CREATE INDEX ON PUBLIC.hyper_1 (time DESC, series_0);
SELECT * FROM create_hypertable('"public"."hyper_1"'::regclass, 'time'::name, number_partitions => 1, chunk_size_bytes=>100000);
create_hypertable
-------------------
(1 row)
INSERT INTO hyper_1 SELECT to_timestamp(generate_series(0,10000)), random(), random(), random();
--non-aggragated uses MergeAppend correctly
EXPLAIN (verbose ON, costs off)SELECT * FROM hyper_1 ORDER BY "time" DESC limit 2;
QUERY PLAN
--------------------------------------------------------------------------------------------------------------------------------------------------------------
Limit
Output: _hyper_3_0_replica."time", _hyper_3_0_replica.series_0, _hyper_3_0_replica.series_1, _hyper_3_0_replica.series_2
-> Merge Append
Sort Key: _hyper_3_0_replica."time" DESC
-> Sort
Output: _hyper_3_0_replica."time", _hyper_3_0_replica.series_0, _hyper_3_0_replica.series_1, _hyper_3_0_replica.series_2
Sort Key: _hyper_3_0_replica."time" DESC
-> Seq Scan on _timescaledb_internal._hyper_3_0_replica
Output: _hyper_3_0_replica."time", _hyper_3_0_replica.series_0, _hyper_3_0_replica.series_1, _hyper_3_0_replica.series_2
-> Sort
Output: _hyper_3_5_0_partition."time", _hyper_3_5_0_partition.series_0, _hyper_3_5_0_partition.series_1, _hyper_3_5_0_partition.series_2
Sort Key: _hyper_3_5_0_partition."time" DESC
-> Seq Scan on _timescaledb_internal._hyper_3_5_0_partition
Output: _hyper_3_5_0_partition."time", _hyper_3_5_0_partition.series_0, _hyper_3_5_0_partition.series_1, _hyper_3_5_0_partition.series_2
-> Index Scan using "19-hyper_1_time_series_0_idx" on _timescaledb_internal._hyper_3_5_0_7_data
Output: _hyper_3_5_0_7_data."time", _hyper_3_5_0_7_data.series_0, _hyper_3_5_0_7_data.series_1, _hyper_3_5_0_7_data.series_2
(16 rows)
--TODO: aggregated with date_trunc doesn't work
EXPLAIN (verbose ON, costs off)SELECT date_trunc('minute', time) t, min(series_0) FROM hyper_1 GROUP BY t ORDER BY t DESC limit 2;
QUERY PLAN
-----------------------------------------------------------------------------------------------------------------
Limit
Output: (date_trunc('minute'::text, _hyper_3_0_replica."time")), (min(_hyper_3_0_replica.series_0))
-> Sort
Output: (date_trunc('minute'::text, _hyper_3_0_replica."time")), (min(_hyper_3_0_replica.series_0))
Sort Key: (date_trunc('minute'::text, _hyper_3_0_replica."time")) DESC
-> HashAggregate
Output: (date_trunc('minute'::text, _hyper_3_0_replica."time")), min(_hyper_3_0_replica.series_0)
Group Key: date_trunc('minute'::text, _hyper_3_0_replica."time")
-> Result
Output: date_trunc('minute'::text, _hyper_3_0_replica."time"), _hyper_3_0_replica.series_0
-> Append
-> Seq Scan on _timescaledb_internal._hyper_3_0_replica
Output: _hyper_3_0_replica."time", _hyper_3_0_replica.series_0
-> Seq Scan on _timescaledb_internal._hyper_3_5_0_partition
Output: _hyper_3_5_0_partition."time", _hyper_3_5_0_partition.series_0
-> Seq Scan on _timescaledb_internal._hyper_3_5_0_7_data
Output: _hyper_3_5_0_7_data."time", _hyper_3_5_0_7_data.series_0
(17 rows)

View File

@ -17,6 +17,7 @@ CREATE INDEX ON PUBLIC."testNs" ("timeCustom" DESC NULLS LAST, series_0) WHERE s
CREATE INDEX ON PUBLIC."testNs" ("timeCustom" DESC NULLS LAST, series_1) WHERE series_1 IS NOT NULL;
CREATE INDEX ON PUBLIC."testNs" ("timeCustom" DESC NULLS LAST, series_2) WHERE series_2 IS NOT NULL;
CREATE INDEX ON PUBLIC."testNs" ("timeCustom" DESC NULLS LAST, series_bool) WHERE series_bool IS NOT NULL;
CREATE INDEX ON PUBLIC."testNs" ("timeCustom" DESC NULLS LAST, device_id);
SELECT * FROM create_hypertable('"public"."testNs"'::regclass, 'timeCustom'::name, 'device_id'::name, associated_schema_name=>'_timescaledb_internal'::text, number_partitions => 2);

View File

@ -19,3 +19,36 @@ EXPLAIN (verbose ON, costs off) SELECT * FROM PUBLIC."testNs" WHERE 'dev'||'20'
--TODO: handle this later?
--EXPLAIN (verbose ON, costs off) SELECT * FROM "testNs" WHERE device_id IN ('dev20', 'dev21');
\echo "The following shows non-aggregated queries with time desc using merge append"
EXPLAIN (verbose ON, costs off)SELECT * FROM PUBLIC."testNs" ORDER BY "timeCustom" DESC NULLS LAST limit 2;
--shows that more specific indexes are used if the WHERE clauses "match", uses the series_1 index here.
EXPLAIN (verbose ON, costs off)SELECT * FROM PUBLIC."testNs" WHERE series_1 IS NOT NULL ORDER BY "timeCustom" DESC NULLS LAST limit 2;
--here the "match" is implication series_1 > 1 => series_1 IS NOT NULL
EXPLAIN (verbose ON, costs off)SELECT * FROM PUBLIC."testNs" WHERE series_1 > 1 ORDER BY "timeCustom" DESC NULLS LAST limit 2;
--note that without time transform things work too
EXPLAIN (verbose ON, costs off)SELECT "timeCustom" t, min(series_0) FROM PUBLIC."testNs" GROUP BY t ORDER BY t DESC NULLS LAST limit 2;
--TODO: time transform doesn't work
EXPLAIN (verbose ON, costs off)SELECT "timeCustom"/10 t, min(series_0) FROM PUBLIC."testNs" GROUP BY t ORDER BY t DESC NULLS LAST limit 2;
EXPLAIN (verbose ON, costs off)SELECT "timeCustom"%10 t, min(series_0) FROM PUBLIC."testNs" GROUP BY t ORDER BY t DESC NULLS LAST limit 2;
--make table with timestamp. Test timestamp instead of int time.
CREATE TABLE PUBLIC.hyper_1 (
time TIMESTAMPTZ NOT NULL,
series_0 DOUBLE PRECISION NULL,
series_1 DOUBLE PRECISION NULL,
series_2 DOUBLE PRECISION NULL
);
CREATE INDEX ON PUBLIC.hyper_1 (time DESC, series_0);
SELECT * FROM create_hypertable('"public"."hyper_1"'::regclass, 'time'::name, number_partitions => 1, chunk_size_bytes=>100000);
INSERT INTO hyper_1 SELECT to_timestamp(generate_series(0,10000)), random(), random(), random();
--non-aggragated uses MergeAppend correctly
EXPLAIN (verbose ON, costs off)SELECT * FROM hyper_1 ORDER BY "time" DESC limit 2;
--TODO: aggregated with date_trunc doesn't work
EXPLAIN (verbose ON, costs off)SELECT date_trunc('minute', time) t, min(series_0) FROM hyper_1 GROUP BY t ORDER BY t DESC limit 2;