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
() автор топика
Для того чтобы оставить комментарий войдите или зарегистрируйтесь.