一旦不常用的数据被分层并迁移到对象存储层,仍然可以通过启用 timescaledb.enable_tiered_reads GUC 使用标准 SQL 进行查询。默认情况下,GUC 设置为 false,因此查询不会访问分层数据。

timescaledb.enable_tiered_reads GUC,即 Grand Unified Configuration 变量,是一个控制是否查询分层数据的设置。配置变量可以在不同级别设置,包括整个数据库服务器全局、单个数据库和单个会话。

启用分层读取后,即使数据分布在不同的存储层中,您也可以像平常一样查询数据。您的超表分布在各个层中,因此查询和 JOIN 都可以正常工作,并像往常一样获取相同的数据。

默认情况下,查询不会访问分层数据。查询分层数据可能会降低查询性能,因为数据没有本地存储在 Timescale 的高性能存储层上。请参阅性能注意事项

  1. 在查询包含分层数据的超表之前启用 timescaledb.enable_tiered_reads,并在完成后重置它

    set timescaledb.enable_tiered_reads = true; SELECT count(*) FROM example; set timescaledb.enable_tiered_reads = false;

    这将查询来自所有数据块的数据,包括分层数据块和非分层数据块

    ||count|
    |---|
    |1000|

通过在会话中启用 timescaledb.enable_tiered_reads,可以将会话中所有未来的查询配置为使用对象存储层。

  1. 为整个会话启用 timescaledb.enable_tiered_reads

    set timescaledb.enable_tiered_reads = true;

    该会话中所有未来的查询都将配置为从分层数据和本地存储数据中读取。

您还可以按照以下步骤,始终启用从分层数据中读取的查询

  1. 为所有未来会话启用 timescaledb.enable_tiered_reads

    alter database tsdb set timescaledb.enable_tiered_reads = true;

    在所有未来创建的会话中,timescaledb.enable_tiered_reads 初始化时都为 enabled

本节说明如何查询分层存储。

考虑一个简单的数据库,其中包含一个标准的 devices 表和一个 metrics 超表。启用分层存储后,您可以查看哪些数据块已分层到对象存储层

chunk_name | range_start | range_end
------------------+------------------------+------------------------
_hyper_2_4_chunk | 2015-12-31 00:00:00+00 | 2016-01-07 00:00:00+00
_hyper_2_3_chunk | 2017-08-17 00:00:00+00 | 2017-08-24 00:00:00+00
(2 rows)

以下查询仅从对象存储层获取数据。这根据查询指定的 WHERE 子句以及此超表上面列出的数据块范围是有意义的。

EXPLAIN SELECT * FROM metrics where ts < '2017-01-01 00:00+00';
QUERY PLAN
---------------------------------------------------------------------
Foreign Scan on osm_chunk_2 (cost=0.00..0.00 rows=2 width=20)
Filter: (ts < '2017-01-01 00:00:00'::timestamp without time zone)
Match tiered objects: 1
Row Groups:
_timescaledb_internal._hyper_2_4_chunk: 0
(5 rows)

如果您的查询不需要访问对象存储层,它将仅处理标准存储中的数据块。以下查询引用的是尚未分层到对象存储层的新数据。计划中的 Match tiered objects :0 表明没有分层数据与查询约束匹配。因此,根本不会访问对象存储中的数据。

EXPLAIN SELECT * FROM metrics where ts > '2022-01-01 00:00+00';
QUERY PLAN
--------------------------------------------------------------------------------
----------------------------------
Append (cost=0.15..25.02 rows=568 width=20)
-> Index Scan using _hyper_2_5_chunk_metrics_ts_idx on _hyper_2_5_chunk (co
st=0.15..22.18 rows=567 width=20)
Index Cond: (ts > '2022-01-01 00:00:00'::timestamp without time zone)
-> Foreign Scan on osm_chunk_2 (cost=0.00..0.00 rows=1 width=20)
Filter: (ts > '2022-01-01 00:00:00'::timestamp without time zone)
Match tiered objects: 0
Row Groups:
(7 rows)

这是另一个不访问分层数据的 JOIN 示例

EXPLAIN SELECT ts, device_id, description FROM metrics
JOIN devices ON metrics.device_id = devices.id
WHERE metrics.ts > '2023-08-01';
QUERY PLAN
--------------------------------------------------------------------------------
Hash Join (cost=32.12..184.55 rows=3607 width=44)
Hash Cond: (devices.id = _hyper_4_9_chunk.device_id)
-> Seq Scan on devices (cost=0.00..22.70 rows=1270 width=36)
-> Hash (cost=25.02..25.02 rows=568 width=12)
-> Append (cost=0.15..25.02 rows=568 width=12)
-> Index Scan using _hyper_4_9_chunk_metrics_ts_idx on _hyper_4_
9_chunk (cost=0.15..22.18 rows=567 width=12)
Index Cond: (ts > '2023-08-01 00:00:00+00'::timestamp with
time zone)
-> Foreign Scan on osm_chunk_3 (cost=0.00..0.00 rows=1 width=12
)
Filter: (ts > '2023-08-01 00:00:00+00'::timestamp with time
zone)
Match tiered objects: 0
Row Groups:
(11 rows)

与本地数据相比,对分层数据的查询预计会更慢。但是,在少数情况下,分层读取也可能影响本地数据的查询计划时间。为了防止应用程序查询出现任何意外的性能下降,我们将 GUC timescaledb.enable_tiered_reads 设置为 false

  • 在查询分层数据时,未指定时间边界的查询预计会执行得更慢,无论是在查询计划期间还是在查询执行期间。Timescale 的数据块排除算法不适用于这种情况。

    SELECT * FROM device_readings WHERE id = 10;
  • 运行时计算谓词的查询(例如 NOW())在计划时并不总是优化,因此在针对对象存储层进行查询时,其性能可能比静态分配的值慢。

    例如,此查询在计划时进行了优化

    SELECT * FROM metrics WHERE ts > '2023-01-01' AND ts < '2023-02-01'

    以下查询在查询计划时未进行数据块剪枝

    SELECT * FROM metrics WHERE ts < now() - '10 days':: interval

    目前,针对分层数据的查询在查询优化器可以应用计划时优化时效果最佳。

  • 当查询分层数据时,文本和非原生类型(JSON、JSONB、GIS)的过滤速度较慢。

关键词

在此页面发现问题吗?报告问题 或 在 GitHub 上编辑此页