show_chunks() не соответствует тому, на что жалуется DELETE

#compression #timescaledb

#сжатие #timescaledb

Вопрос:

Это действительно озадачивает. Мне нужно удалить дату из гипертаблицы из 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"
 

Поэтому я распаковываю эти два. Однако, когда я запускаю команду УДАЛЕНИЯ выше, я все равно получаю сообщение об ошибке о совершенно другом фрагменте:

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

Кстати, этот фрагмент пуст, насколько я могу видеть, посмотрев на него в pgAdmin. Есть идеи, что происходит? Для меня это похоже на ошибку, но, может быть, я делаю что-то не так?

Спасибо!

Редактировать: ниже приведен отрывок из результата EXPLAIN DELETE, запрошенный @k_rus:

 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)"
 

Комментарии:

1. Можете ли вы выполнить EXPLAIN для вашего оператора DELETE и показать результат?

2. Привет @k_rus, вот оно: docs.google.com/document/d /…

3. Можете ли вы опубликовать объяснение в своем вопросе, поскольку на него важно ответить? Вы можете опустить повторяющуюся часть и показать только несколько фрагментов из плана.

Ответ №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 предполагает, что данные считываются через гипертаблицу, а не непосредственно из блоков. Гипертаблица — это абстракция, которая скрывает детали реализации TimescaleDB .

Комментарии:

1. Потрясающе, большое вам спасибо! Это действительно имеет смысл. Итак, я понимаю, что планировщик не может пройти через ::date (и, вероятно, не будет использовать какой-либо модификатор или функцию в поле метки времени), и поэтому он решает использовать ядерный вариант прохождения всех фрагментов, что отчасти понятно. И самое главное, предложение с BETWEEN работает, так что это определенно ответ! Огромное спасибо!

Ответ №2:

Какая конкретная версия 1.7? В этом была ошибка, но она должна быть исправлена с 1.7.3 вперед. https://github.com/timescale/timescaledb/pull/2092

Если вы используете 1.7.3 или более позднюю версию и все еще видите это, было бы лучше открыть проблему в репозитории timescaledb GitHub.

Вы можете проверить свою версию, подключившись к psql и запустив dx

Комментарии:

1. Привет @TDF, он показывает 1.7.4 после запуска dx Кстати, весь экземпляр запускается из docker: docker run -d —name timescaledb -p 5432:5432 -e LANG=C timescale/ timescaledb:1.7.4-pg12