【问题标题】:show_chunks() does not correspond to what DELETE complains aboutshow_chunks() 与 DELETE 抱怨的不对应
【发布时间】:2021-01-16 10:17:26
【问题描述】:

这真是令人费解。我需要从 timescaleDB 1.7 的超表中删除日期:

DELETE FROM raw WHERE tm::date = '2020-11-06' -- the local date style is YYYY-MM-DD

在此之前,我检查了我需要解压哪些块,给它一天的保证金,并收到两个块:

SELECT show_chunks('raw', newer_than => '2020-11-05 00:00'::timestamp)
---
Result:
"_timescaledb_internal._hyper_1_19_chunk"
"_timescaledb_internal._hyper_1_21_chunk"

所以我解压这两个。但是,当我运行上面的 DELETE 命令时,我仍然收到关于完全不同块的错误:

ERROR:  cannot update/delete rows from chunk "_hyper_1_1_chunk" as it
is compressed SQL state: XX000

顺便说一句,就我在 pgAdmin 中查看它所看到的而言,这个块是空的。知道发生了什么吗?对我来说似乎是一个错误,但也许我做错了什么?

谢谢!

编辑: 以下是@k_rus 要求的 EXPLAIN DELETE 结果的摘录:

EXPLAIN DELETE FROM raw WHERE tm::date = '2020-11-06'
Result:

"Delete on raw  (cost=0.00..719.63 rows=147 width=6)"
"  Delete on raw"
"  Delete on _hyper_1_1_chunk"
"  Delete on _hyper_1_2_chunk"

...

"  Delete on _hyper_1_22_chunk"
"  ->  Seq Scan on raw  (cost=0.00..0.00 rows=1 width=6)"
"        Filter: ((tm)::date = '2020-11-06'::date)"
"  ->  Custom Scan (CompressChunkDml) on _hyper_1_1_chunk  (cost=0.00..27.40 rows=6 width=6)"
"        ->  Seq Scan on _hyper_1_1_chunk  (cost=0.00..27.40 rows=6 width=6)"
"              Filter: ((tm)::date = '2020-11-06'::date)"
"  ->  Custom Scan (CompressChunkDml) on _hyper_1_2_chunk  (cost=0.00..27.40 rows=6 width=6)"
"        ->  Seq Scan on _hyper_1_2_chunk  (cost=0.00..27.40 rows=6 width=6)"
"              Filter: ((tm)::date = '2020-11-06'::date)"

...

"  ->  Custom Scan (CompressChunkDml) on _hyper_1_22_chunk  (cost=0.00..27.40 rows=6 width=6)"
"        ->  Seq Scan on _hyper_1_22_chunk  (cost=0.00..27.40 rows=6 width=6)"
"              Filter: ((tm)::date = '2020-11-06'::date)"

【问题讨论】:

  • 你能在你的 DELETE 语句上运行 EXPLAIN 并显示结果吗?
  • 嗨@k_rus,这里是:docs.google.com/document/d/…
  • 您能否将解释发布到您的问题中,因为回答它很重要?您可以省略重复的部分,只显示计划中的几个部分。

标签: compression timescaledb


【解决方案1】:

感谢您提供解释。解释表明,DELETE 语句计划触及超表的所有块,只有在运行时执行 DELETE 语句才会意识到它在许多块中没有什么可删除的:

EXPLAIN DELETE FROM raw WHERE tm::date = '2020-11-06'
Result:

"Delete on raw  (cost=0.00..719.63 rows=147 width=6)"
"  Delete on raw"
"  Delete on _hyper_1_1_chunk"
"  Delete on _hyper_1_2_chunk"

...

"  Delete on _hyper_1_22_chunk"
"  ->  Seq Scan on raw  (cost=0.00..0.00 rows=1 width=6)"
"        Filter: ((tm)::date = '2020-11-06'::date)"
"  ->  Custom Scan (CompressChunkDml) on _hyper_1_1_chunk  (cost=0.00..27.40 rows=6 width=6)"
"        ->  Seq Scan on _hyper_1_1_chunk  (cost=0.00..27.40 rows=6 width=6)"
"              Filter: ((tm)::date = '2020-11-06'::date)"
"  ->  Custom Scan (CompressChunkDml) on _hyper_1_2_chunk  (cost=0.00..27.40 rows=6 width=6)"
"        ->  Seq Scan on _hyper_1_2_chunk  (cost=0.00..27.40 rows=6 width=6)"
"              Filter: ((tm)::date = '2020-11-06'::date)"

...

"  ->  Custom Scan (CompressChunkDml) on _hyper_1_22_chunk  (cost=0.00..27.40 rows=6 width=6)"
"        ->  Seq Scan on _hyper_1_22_chunk  (cost=0.00..27.40 rows=6 width=6)"
"              Filter: ((tm)::date = '2020-11-06'::date)"

由于某些块被压缩,TimescaleDB 在为压缩块计划删除时返回错误。

不报错的唯一方法是在计划时有选择条件触发块排除。问题中选择条件为tm::date = '2020-11-06',它首先从tm列中提取日期,然后与常数进行比较。因此规划器无法决定块是否被过滤,而是将过滤器向下推,以便在每个块上运行时执行。

要解决这个问题,最好有一个选择条件,它将时间维度列与常数或值进行比较,可以在计划时计算。假设tm是超表raw中的时间维度列,我建议将常量日期转换为时间戳,例如'2020-11-06'::timestamp并保留该列。您需要指定时间戳范围以涵盖属于目标日期的所有行。

例如,DELETE 语句可以是:

DELETE FROM raw WHERE tm BETWEEN '2020-11-06 00:00' AND '2020-11-06 23:59'

问题解答:

show_chunks() 与 DELETE 抱怨的不符

show_chunk 语句和DELETE 语句的条件不同,不能直接比较。 show_chunk 只显示块,它涵盖了比给定常量更新的时间。而DELETE 计划检查每个块,因此它可以抱怨超表的任何块。

顺便说一句,就我在 pgAdmin 中查看它所看到的而言,这个块是空的。知道发生了什么吗?对我来说似乎是一个错误,但也许我做错了什么?

压缩块将数据存储在不同的内部块中,因此在_hyper_1_1_chunk 中看不到任何数据。 TimescaleDB 假设数据是通过超表读取的,而不是直接从块中读取的。 Hypertable 是一种抽象,它隐藏了 TimescaleDB 的实现细节。

【讨论】:

  • 太棒了,非常感谢!这真的很有意义。所以我知道计划者不能通过 ::date (并且可能不会在时间戳字段上使用任何修饰符或函数),因此它决定然后拉出通过所有块的核选项,这有点可以理解的。最重要的是,BETWEEN 的建议有效,所以这绝对是答案!谢谢大家!
【解决方案2】:

1.7 的具体版本是什么?这有一个错误,但应该从 1.7.3 开始修复。 https://github.com/timescale/timescaledb/pull/2092

如果您使用的是 1.7.3 或更高版本并且仍然看到此问题,最好在 timescaledb GitHub 存储库上打开一个问题。

您可以通过连接 psql 并运行 \dx 来检查您的版本

【讨论】:

  • 嗨@TDF,它在运行 \dx 后显示 1.7.4 BTW 整个实例是从 docker 运行的: docker run -d --name timescaledb -p 5432:5432 -e LANG=C timescale/ timescaledb:1.7.4-pg12
猜你喜欢
  • 2016-11-11
  • 2012-03-17
  • 2016-08-31
  • 1970-01-01
  • 2022-12-28
  • 2022-01-10
  • 2012-01-28
  • 2011-11-14
  • 2014-06-27
相关资源
最近更新 更多