Как улучшить производительность моего запроса на удаление, если узким местом является ввод / вывод? - PullRequest
1 голос
/ 23 апреля 2020

У меня есть (плохо спроектированная) таблица базы данных (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 строки за раз с отдельными запросами. Это далеко от идеала, поэтому я надеюсь, что у вас есть предложения.

Обратите внимание, что я не администрирую базу данных и не уполномочен вносить какие-либо изменения в ее конфигурацию, а также вряд ли администратор базы данных изменит конфигурацию чтобы справиться с моей плохо спроектированной установкой.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...