【问题标题】:How to improve the performance of timescaledb getting last timestamp如何提高timescaledb获取最后一个时间戳的性能
【发布时间】:2020-07-26 05:33:29
【问题描述】:

SELECT timeseries_id, "timestamp" FROM enhydris_timeseriesrecord WHERE timeseries_id=6661 ORDER BY "timestamp" DESC LIMIT 1;

(表包含大约66m条记录,timeseries_id=6661的大约0.5m。)

这个查询运行大约需要 1-2 秒,我觉得这太多了。

如果它使用简单的 btree 索引,它应该在大约 30 次迭代后找到它正在寻找的内容。据我所见,当我为该查询执行EXPLAIN ANALYZE 时,它确实使用了索引,但它必须在每个块中这样做,并且显然有 1374 个块。

如何让查询变得更快?

                 Table "public.enhydris_timeseriesrecord"
    Column     |           Type           | Collation | Nullable | Default 
---------------+--------------------------+-----------+----------+---------
 timeseries_id | integer                  |           | not null | 
 timestamp     | timestamp with time zone |           | not null | 
 value         | double precision         |           |          | 
 flags         | character varying(237)   |           | not null | 
Indexes:
    "enhydris_timeseriesrecord_pk" PRIMARY KEY, btree (timeseries_id, "timestamp")
    "enhydris_timeseriesrecord_timeseries_id_idx" btree (timeseries_id)
    "enhydris_timeseriesrecord_timestamp_idx" btree ("timestamp" DESC)
    "enhydris_timeseriesrecord_timestamp_timeseries_id_idx" btree ("timestamp", timeseries_id)
Foreign-key constraints:
    "enhydris_timeseriesrecord_timeseries_fk" FOREIGN KEY (timeseries_id) REFERENCES enhydris_timeseries(id) DEFERRABLE INITIALLY DEFERRED
Triggers:
    ts_insert_blocker BEFORE INSERT ON enhydris_timeseriesrecord FOR EACH ROW EXECUTE PROCEDURE _timescaledb_internal.insert_blocker()
Number of child tables: 1374 (Use \d+ to list them.)

更新EXPLAIN plan

【问题讨论】:

  • 你能发布你的解释计划吗?
  • @BlagojAtanasovski 添加在问题的末尾。

标签: timescaledb


【解决方案1】:

数据库必须转到每个块的子索引并检索找到 timeseries_id=x 的最新时间戳。数据库正确使用索引(从解释中可以看出)它对每个块中的每个子索引进行索引扫描,而不是完整扫描。所以它会进行 >1000 次索引扫描。无法修剪任何块,因为规划器无法知道哪些块具有该特定 timeseries_id 的条目。

你有 1300 个块,只有 66m 条记录 -> 每个块约 50k 行。每个块的行数太少。从 Timescale Docs 他们有以下建议:

选择时间间隔的关键属性是属于最近间隔的块(包括索引)(或块,如果使用空间分区)适合内存。因此,我们通常建议设置间隔,使这些块不超过主内存的 25%。

https://docs.timescale.com/latest/using-timescaledb/hypertables#best-practices

减少块的数量将显着提高查询性能。

此外,如果您使用 TimescaleDB 压缩,您可能会获得更高的查询性能,这将进一步减少需要扫描的块数,您可以按 timeseries_id (https://docs.timescale.com/latest/api#compression) 进行分段,或者您可以定义一个连续聚合将保留每个 timeseries_id 的最后一项 (https://docs.timescale.com/latest/api#continuous-aggregates)

【讨论】:

  • 很抱歉,我忘了添加LIMIT 1。我只是在寻找最后一个时间戳,即找到时间序列的结尾。我在问题中解决了这个问题并替换了解释计划(尽管它本质上是相同的)。
  • 我将编辑我的答案,但延迟的主要原因仍然相同,块太多,并且它们都被索引扫描以找到它们的最新时间戳。规划器无法修剪哪些块可能具有 timeseries_id = x 的最后一个条目,因此它必须询问所有块。
猜你喜欢
  • 2021-06-12
  • 1970-01-01
  • 2021-11-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-08-26
  • 2018-05-06
  • 2021-06-01
相关资源
最近更新 更多