У меня есть (плохо спроектированная) таблица базы данных (postgres), которую я пытаюсь очистить. Размер таблицы составляет около 270 ГБ, строки 38 КБ (+ - 70 МБ на строку -> столбцы содержат содержимое файла).
Параллельно с изменением дизайна, чтобы больше не содержать файлы, я хочу удалить 80% данных, чтобы уменьшить использование диска. Поэтому я попытался выполнить следующий запрос:
DELETE FROM table_name.dynamic_data
WHERE table_name.env = 'AE'
, который должен охватывать + - 25% данных. Этот запрос завершается без какого-либо предупреждения или иногда сообщает, что файл журнала заполнен: PANI C: не удалось записать в файл "pg_xlog / xlogtemp.32455": на устройстве не осталось места
Я пытался
DELETE FROM table_name
WHERE ctid IN (
SELECT ctid
FROM table_name
WHERE table_name.env = 'AE'
LIMIT 1000)
, который работает, но невероятно медленно (200-250 мс на удаленную строку) и время ожидания, если я go превышает 1000 много.
Чтобы найти узкое место в запросе, я выполнил запрос выше с explain (analyze,buffers,timing)
для уменьшенной версии этого запроса (с LIMIT 1 вместо LIMIT 1000), что привело к следующему объяснению:
QUERY PLAN
Delete on dynamic_data (cost=0.38..4410.47 rows=1 width=36) (actual time=338.913..338.913 rows=0 loops=1)
Buffers: shared hit=7972 read=988 dirtied=975
I/O Timings: read=312.160
-> Nested Loop (cost=0.38..4410.47 rows=1 width=36) (actual time=3.919..13.700 rows=1 loops=1)
Join Filter: (dynamic_data.ctid = "ANY_subquery".ctid)
Rows Removed by Join Filter: 35938
Buffers: shared hit=4013
-> Unique (cost=0.38..0.39 rows=1 width=36) (actual time=2.786..2.788 rows=1 loops=1)
Buffers: shared hit=479
-> Sort (cost=0.38..0.39 rows=1 width=36) (actual time=2.786..2.787 rows=1 loops=1)
Sort Key: "ANY_subquery".ctid
Sort Method: quicksort Memory: 25kB
Buffers: shared hit=479
-> Subquery Scan on "ANY_subquery" (cost=0.00..0.37 rows=1 width=36) (actual time=2.753..2.753 rows=1 loops=1)
Buffers: shared hit=474
-> Limit (cost=0.00..0.36 rows=1 width=6) (actual time=2.735..2.735 rows=1 loops=1)
Buffers: shared hit=474
-> Seq Scan on dynamic_data dynamic_data_1 (cost=0.00..4020.71 rows=11093 width=6) (actual time=2.735..2.735 rows=1 loops=1)
Filter: (env = 'AE'::text)
Rows Removed by Filter: 5614
Buffers: shared hit=474
-> Seq Scan on dynamic_data (cost=0.00..3923.37 rows=38937 width=6) (actual time=0.005..8.130 rows=35939 loops=1)
Buffers: shared hit=3534
Planning time: 0.354 ms
Execution time: 338.969 ms
Мой основной вывод из плана запроса заключается в том, что время ввода-вывода занимает 312/338 = 92% времени:
actual time=338.913..338.913 rows=0 loops=1)
Buffers: shared hit=7972 read=988 dirtied=975
I/O Timings: read=312.160
Я не могу найти ничего о том, как улучшить производительность ввода-вывода этого запроса без изменения конфигурации базы данных. Это просто неудачный эффект больших строк таблицы / базы данных? Или я что-то упустил? Как ускорить эту операцию удаления?
Без какого-либо разрешения я по умолчанию использую скрипт для удаления 1 строки за раз с отдельными запросами. Это далеко от идеала, поэтому я надеюсь, что у вас есть предложения.
Обратите внимание, что я не администрирую базу данных и не уполномочен вносить какие-либо изменения в ее конфигурацию, а также вряд ли администратор базы данных изменит конфигурацию чтобы справиться с моей плохо спроектированной установкой.