#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