Postgres plpgsql Увеличивает скорость ВСТАВКИ В… оператор из CTE, используя КОПИРОВАНИЕ ( В || ИЗ)

#database #postgresql #plpgsql #common-table-expression #postgresql-9.5

Вопрос:

Я пытаюсь переместить миллионы записей из одной таблицы в другую таблицу (архив). Я могу удалить все FK и индексы перед выполнением этой ВСТАВКИ. В принципе, я использую a LOOP и создаю CTE внутри, который позже использую в INSERT INTO... своей архивной таблице. Это работает, потому что каждый раз, когда я повторяю, я получаю новые данные в своем CTE, т. Е.

 do
$
declare
begin
  loop
   exit when rec_count = 0;
   
   WITH some_cte AS (
       select * 
       from some_table st
       where not exists (select 1 from some_archive_table sat where sat.id = st.id)
       limit 10000
   ),
   INSERT INTO some_archive_table (select * from some_cte);

   get diagnostics rec_count = row_count;
 end loop;
end;
$
 

Я видел, как в stackoverflow люди рекомендовали эту COPY команду, но, похоже, мне нужно читать из файла или stdin, и я не могу читать из таблицы и копировать в таблицу.

Будет ли на самом деле быстрее выводить данные в формате CSV, а затем считывать их обратно из CSV в таблицу?

Я пытался сделать это сейчас , но получал ошибку

 ERROR: must be superuser or a member of the pg_write_server_files role to COPY to a file
HINT: Anyone can COPY to stdout or from stdin. psql's copy command also works for anyone.
 

Стоит ли пытаться исправить эту проблему с доступом, или я могу вывести ее в STDOUT/STDIN, или я не увижу улучшений с КОПИРОВАНИЕМ против ВСТАВКИ? Я хотел бы получить любую возможную помощь!

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

1. У вас есть уникальный индекс на sat.id? Если да, вы могли бы просто использовать insert on conflict (id) do nothing и избавиться от этого where not exists состояния — скорее всего, это было бы быстрее

2. Кроме того, почему CTE ? Вы могли бы просто включить select * from some_table st ... запрос в качестве SELECT части INSERT INTO some_archive_table ...

3. Вам также необходимо добавить rec_count integer; в DECLARE .