#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
.