Записи обновления PostgreSQL в пакетах

#python #sql #python-3.x #postgresql #psql

Вопрос:

Мне нужно обновить один столбец в таблице с огромным набором данных в базе данных PostgreSQL.

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

Один из методов, который я попытался сделать, заключается в следующем в блоке postgres, который не удался, так как я не могу использовать row_number() в предложении where.

 DO LANGUAGE plpgsql $ DECLARE   row_count_ integer;   offset_ integer := 0;  batch_size_ integer := 100000;  limit_ integer := offset_   batch_size_;   total_rows_ integer;  BEGIN   WHILE offset_ lt; total_rows_ LOOP  limit_ := offset_   batch_size_;    UPDATE table1   SET column1 = 'Value'   WHERE row_number() over() gt;= offset_ AND row_number() over() lt; limit_;  GET DIAGNOSTICS row_count_ = row_count;  RAISE INFO '% rows updated from % to %', row_count_, offset_, limit_;    offset_ := offset_   batch_size_;  END LOOP;  EXCEPTION WHEN OTHERS THEN    RAISE NOTICE 'Transaction is rolling back, % : %', SQLSTATE, SQLERRM;  ROLLBACK;   END $;  

Я даже могу сделать это с помощью скрипта python, но мне нужно сделать это как можно быстрее. Я просмотрел много статей, в которых используется подзапрос select, который, на мой взгляд, слишком дорог из-за объединения.

Не мог бы кто-нибудь, пожалуйста, помочь мне с лучшим способом достижения этой цели?

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

1. Если каждая строка обновляется с одинаковым значением, вы можете просто добавить столбец с этим значением по умолчанию. Это будет почти мгновенно в версии 11 или выше. (И до 11-обновите как минимум до 11.)

Ответ №1:

Если действие длится несколько дней, UPDATE имеет смысл выполнять его пакетами. Возможно, вам захочется выполнить явный VACUUM анализ таблицы между пакетами, чтобы избежать раздувания таблицы.

Что касается вашей основной проблемы, я бы сказал, что самым простым решением было бы выполнить пакетирование по значениям первичного ключа, то есть выполнить такие инструкции, как:

 UPDATE tab SET col = newval WHERE id lt;= 100000  AND /* additional criteria*/;  VACUUM tab;  UPDATE tab SET col = newval WHERE id gt; 100000 AND id lt;= 200000  AND /* additional criteria*/;  ...  

Продолжайте повторять это, пока не достигнете максимума id .