LINUX.ORG.RU

Delta Partition Перенос данных из таблицы в таблицу с одного сервера Postgres на другой Postgres

 , ,


0

1

Доброго дня дорогой форум. Это мой первый пост. Буду рад критике.

У меня есть таблица на первом сервере Postgres. Например db1.sales Я создал таблицу на втором сервере Postgres. Например db2.sales

Скажите, пожалуйста, какими средствами я могу перенести данные партиционно?

Я пробую следующий алгоритм: создание партиций в целевой таблице: Проверяю есть ли партиции в таблице. если есть получаю параметры последней партиции(записываю в переменную конечную дату последней партиции). далее нужно вырезать новую партицию из дефолтной партиции(этот момент я не до конца понимаю).

приложенный код идёт с увеличением к конечной дате. то есть август->сентябрь->октябрь и тд.

но мне ведь нужно попасть в начальную дату которая есть в таблицe.

помогите, пожалуйста. у меня нет понимания каким способ перенести данные партициями. посоветуйте литературу. буду признателен любой помощи

CREATE OR REPLACE FUNCTION bd2.f_create_date_partitions(p_table_name text, p_partition_value timestamp)
	RETURNS void
	LANGUAGE plpgsql
	VOLATILE
AS $$
	
DECLARE 
    v_cnt_partitions int; 
    v_table_name text; 
    v_partition_end_sql text; 
    v_partition_end timestamp; 
    v_interval interval; 
    v_ts_format text := 'YYYY-MM-DD HH24:MI:SS'; 
BEGIN 
    v_table_name = std7_167.f_unify_name(p_table_name); 

    -- Проверка наличия партиций в таблице 
    SELECT COUNT(*) INTO v_cnt_partitions 
    FROM pg_partitions p 
    WHERE p.schemaname || '.' || p.tablename = lower(v_table_name); 

    IF v_cnt_partitions > 1 THEN 
        LOOP 
            -- Получение параметров последней партиции 
            SELECT partitionrangeend INTO v_partition_end_sql 
            FROM ( 
                SELECT p.*, RANK() OVER (ORDER BY partitionrank DESC) rnk 
                FROM pg_partitions p 
                WHERE p.partitionrank IS NOT NULL AND p.schemaname || '.' || p.tablename = lower(v_table_name) 
            ) q 
            WHERE rnk = 1; 

            -- Конечная дата последней партиции 
            EXECUTE 'SELECT ' || v_partition_end_sql INTO v_partition_end; 
			
			raise notice 'v_partition_end_sql = [%], v_partition_end = [%]', v_partition_end_sql, v_partition_end;
            -- Если партиция уже есть для входного значения, тогда EXIT из функции 
            EXIT WHEN v_partition_end > p_partition_value; 

            v_interval = '1 month'::interval; 

            -- Вырез новой партиции из дефолтной партиции, если её ещё не существует 
            EXECUTE 'ALTER TABLE ' || v_table_name || ' SPLIT DEFAULT PARTITION 
                     START (' || v_partition_end_sql || ') END (''' || 
                     to_char(v_partition_end + v_interval, v_ts_format) || '''::timestamp)'; 
			raise notice 'Successfully altered % from % to %', v_table_name, v_partition_end_sql, to_char(v_partition_end + v_interval, v_ts_format);
        END LOOP; 
	ELSE
		raise notice 'Number of partitions = %.%Please, check quantity of partitions.% % is not > 1', v_cnt_partitions, E'\n', E'\n', v_cnt_partitions;
    END IF; 
END; 


$$
EXECUTE ON ANY;```


Последнее исправление: Oleg27135 (всего исправлений: 1)

в данный момент получается:

select bd2.f_load_delta_partitions(‘gp.sales’, ‘bd2.sales’, ‘date’, ‘2021-01-01’, ‘2022-08-26’);

v_partition_end_sql = [‘2021-08-01’::date], v_partition_end = [2021-08-01 00:00:00] v_partition_end_sql = [‘2021-09-01’::date], v_partition_end = [2021-09-01 00:00:00] v_partition_end_sql = [‘2021-10-01’::date], v_partition_end = [2021-10-01 00:00:00] v_partition_end_sql = [‘2021-11-01’::date], v_partition_end = [2021-11-01 00:00:00]

ниже более развёрнуто:

v_partition_end_sql = [‘2021-08-01’::date], v_partition_end = [2021-08-01 00:00:00] exchanged partition «other» of relation «sales2» with relation «pg_temp_2541527» dropped partition «other» for relation «sales2» CREATE TABLE will create partition «sales2_1_prt_r563113256» for table «sales2» CREATE TABLE will create partition «sales2_1_prt_other» for table «sales2» Successfully altered std7_167.sales2 from ‘2021-08-01’::date to 2021-09-01 00:00:00 v_partition_end_sql = [‘2021-09-01’::date], v_partition_end = [2021-09-01 00:00:00] exchanged partition «other» of relation «sales2» with relation «pg_temp_2541527» dropped partition «other» for relation «sales2» CREATE TABLE will create partition «sales2_1_prt_r1442547600» for table «sales2» CREATE TABLE will create partition «sales2_1_prt_other» for table «sales2» Successfully altered std7_167.sales2 from ‘2021-09-01’::date to 2021-10-01 00:00:00 Number of rows in table std7_167.sales2: 0 v_partition_end_sql = [‘2021-10-01’::date], v_partition_end = [2021-10-01 00:00:00] exchanged partition «other» of relation «sales2» with relation «pg_temp_2541527» dropped partition «other» for relation «sales2» CREATE TABLE will create partition «sales2_1_prt_r1292352003» for table «sales2» CREATE TABLE will create partition «sales2_1_prt_other» for table «sales2» Successfully altered std7_167.sales2 from ‘2021-10-01’::date to 2021-11-01 00:00:00 Number of rows in table std7_167.sales2: 0 v_partition_end_sql = [‘2021-11-01’::date], v_partition_end = [2021-11-01 00:00:00]

Oleg27135
() автор топика

Сложно понять, что вы делаете.

Если дословно понимать вопрос в заголовке - первое, что приходит в голову - логическая репликация с publish_via_partition_root = FALSE

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

Toxo2 ★★★★
()

Скажите, пожалуйста, какими средствами я могу перенести данные партиционно?

Чего то вы не договариваете. Почему просто не сдампить с сервера на сервер таблицу нужной партиции?

А литература вот https://www.postgresql.org/docs/17/ddl-partitioning.html

cobold ★★★★★
()
Последнее исправление: cobold (всего исправлений: 2)
Ответ на: комментарий от Toxo2

«первое, что приходит в голову - логическая репликация с publish_via_partition_root = FALSE»

я понимаю что есть несколько способов выполнить одну задачу. под репликацией я понимаю копирование ВСЕЙ таблицы на несколько сегментов сервера(инстансов), для ускорения обработки записанных данных(в случае с записью новых данных на реплицированные сегменты, времени занимает больше).

Изучил https://timeweb.cloud/tutorials/postgresql/logicheskaya-replikaciya-postgresql

Как я понимаю логическая репликация использует публикацию и подписку. Я пока только в create, insert умею.

не говорю что ваш способ плох. Я хочу понять почему в предложенном мне задание именно такой способ. И как сделать чтобы он работал(если конечно это вообще актуально).

Спасибо за ваш способ!!! Буду изучать и пробовать в дальнейшем.

«запчасть от некоторой системы управления секционированием таблиц уже уровня приложения в БД»

Пока что могу только гуглить, либо догадываться о том что вы пишете)))

Вы верно говорите что это запчасть))

Я могу поделиться полным кодом. Подскажите, пожалуйста, как сделать чтобы вам было удобнее посмотреть.

Файлообменник, сюда лить простыни?

остальные запчасти это: основной скрипт - f_load_delta_partitions() /// далее f_create_date_partitions()[описан выше] /// далее f_create_tmp_table() /// далее f_insert_table() /// далее f_switch_partition() /// далее DROP TABLE tmp_table

Oleg27135
() автор топика
Ответ на: комментарий от Oleg27135

могу поделиться полным кодом

Спасибо, это лишнее. В целом я представляю, что там может быть.

Имелось в виду, что такая реализация (на уровне приложения БД) пишется вручную когда совершенно точно нет никакого другого способа. Должен быть какой-то веский аргумент почему нельзя использовать встроенные механизмы СУБД.

Код красивый. Тот, кто его писал явно понимал, что делает. Только не понятно зачем.

Toxo2 ★★★★
()
Ответ на: комментарий от cobold

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

таблицы находятся на разных серверах.

я правильно понимаю что нету каталогов функций. они пишутся в каждой компании самостоятельно??

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

А литература вот

Большое спасибо)))

Oleg27135
() автор топика
Ответ на: комментарий от Toxo2

Код красивый. Тот, кто его писал явно понимал, что делает. Только не понятно зачем.

как бальзам на душу. это тестовое задание при трудоустройстве.

Oleg27135
() автор топика