Гость
Форумы / PostgreSQL [игнор отключен] [закрыт для гостей] / Ошибка при создании секционированной таблицы в постгресе / 22 сообщений из 22, страница 1 из 1
23.03.2020, 17:58
    #39940324
kirill demidov
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Ошибка при создании секционированной таблицы в постгресе
Всем привет!

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

Родительская таблица:
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
CREATE TABLE dwh.fact_measures_raw (
	id serial NOT NULL,
	equipment_id varchar NULL,
	parameter_id varchar NULL,
	value float8 NULL,
	ts_original int8 NULL,
	ts_timestamp timestamp NULL,
	created_at timestamp NULL DEFAULT now(),
	updated_at timestamp NULL DEFAULT now()
);
CREATE INDEX idx_ts_timestamp ON dwh.fact_measures_raw USING btree (ts_timestamp);



Текст функции, которая создает динамически новые секционные таблицы, и текст триггера перед INSERT:
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
CREATE OR REPLACE FUNCTION dwh.fact_raw_insert_function()
 RETURNS trigger
 LANGUAGE plpgsql
AS $function$
declare
	partition_date text;

partition_name text;

start_of_hour text;

end_of_next_hour text;


begin partition_date := to_char(NEW.ts_timestamp, 'YYYY-MM-DD-HH');

partition_name := 'dwh.raw_data_' || partition_date;

start_of_hour := to_char((NEW.ts_timestamp), 'YYYY-MM-DD HH:DD:SS') || '-01';

end_of_next_hour := to_char((NEW.ts_timestamp + interval '1 hour'), 'YYYY-MM-DD HH:DD:SS') || '-01';

if not exists (
select
	1
from
	information_schema.tables
where
	table_name = partition_name) then raise notice 'A partition has been created %',
partition_name;

execute format(E'CREATE TABLE %I (CHECK ( date_trunc(\'hour\', ts_timestamp) >= ''%s'' AND date_trunc(\'hour\', ts_timestamp) < ''%s'')) 
INHERITS (dwh.fact_measures_raw)',
partition_name,
start_of_hour,
end_of_next_hour);


 end if;

execute format('INSERT INTO %I (equipment_id,parameter_id,value,ts_original,ts_timestamp) VALUES($1,$2,$3,$4,$5)',
partition_name)
	using NEW.equipment_id,new.parameter_id,new.value,new.ts_original,NEW.ts_timestamp;

return null;

end $function$;

CREATE TRIGGER fact_raw_insert
    BEFORE INSERT ON dwh.fact_measures_raw
    FOR EACH ROW EXECUTE PROCEDURE dwh.fact_raw_insert_function();




При выполнении записи новых строк я получаю вот такую ошибку и уже голову сломал в чем проблема:


SQL Error [23514]: ERROR: new row for relation "dwh.raw_data_2020-03-23-04" violates check constraint "dwh.raw_data_2020-03-23-04_ts_timestamp_check"
Detail: Failing row contains (1218483, 4161341a-ad79-4021-b6fa-f6754f34f5cb, frequency, 49.8486557006835938, 1584974047062000, 2020-03-23 16:34:07, 2020-03-23 16:54:30.598366, 2020-03-23 16:54:30.598366).
Where: SQL statement "INSERT INTO "dwh.raw_data_2020-03-23-04" (equipment_id,parameter_id,value,ts_original,ts_timestamp) VALUES($1,$2,$3,$4,$5)"
PL/pgSQL function dwh.fact_raw_insert_function() line 38 at EXECUTE
SQL statement "insert into dwh.fact_measures_raw (equipment_id,
parameter_id,
value,
ts_original,
ts_timestamp)
select id, column_name, cast(column_value as float8),cast(ts as bigint),
to_timestamp( NULLIF(ts, '')::bigint/1000000)
from dwh.vw_stg_raw
where column_value is not null
and column_name not in ('ts','created_at')
and created_at < date_insert"
PL/pgSQL function dwh.insert_fact_measures_raw() line 6 at SQL statement


Что я делаю не так?

Спасибо!
...
Рейтинг: 0 / 0
23.03.2020, 18:50
    #39940350
Melkij
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Ошибка при создании секционированной таблицы в постгресе
kirill demidov,

CHECK ( date_trunc(\'hour\', ts_timestamp)
где ts_timestamp = 2020-03-23 16:34:07
но new row for relation "dwh.raw_data_2020-03-23-04"
Почему? Странная разница в 12 часов не побуждает проверить вполне определённую штуку?

https://www.postgresql.org/docs/current/functions-formatting.html
HH hour of day (01-12)

А вообще не надо создавать партиции из триггера.
...
Рейтинг: 0 / 0
24.03.2020, 07:15
    #39940422
kirill demidov
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Ошибка при создании секционированной таблицы в постгресе
Melkij,

Спасибо за замечание!

А как бы вы создавали динамические секции?
...
Рейтинг: 0 / 0
24.03.2020, 08:20
    #39940435
kirill demidov
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Ошибка при создании секционированной таблицы в постгресе
Melkij
kirill demidov,

CHECK ( date_trunc(\'hour\', ts_timestamp)
где ts_timestamp = 2020-03-23 16:34:07
но new row for relation "dwh.raw_data_2020-03-23-04"
Почему? Странная разница в 12 часов не побуждает проверить вполне определённую штуку?

https://www.postgresql.org/docs/current/functions-formatting.html
HH hour of day (01-12)


А вообще не надо создавать партиции из триггера.


Я изменил функцию:
Код: plsql
1.
2.
3.
4.
5.
6.
7.
begin partition_date := to_char(NEW.ts_timestamp, 'YYYY-MM-DD-HH24');

partition_name := 'dwh.raw_data_' || partition_date;

start_of_hour := to_char((NEW.ts_timestamp), 'YYYY-MM-DD HH24:DD:SS') || '-01';

end_of_next_hour := to_char((NEW.ts_timestamp + interval '1 hour'), 'YYYY-MM-DD HH24:DD:SS') || '-01';



но продолжаю получать ту же ошибку:


SQL Error [23514]: ERROR: new row for relation "dwh.raw_data_2020-03-24-07" violates check constraint "dwh.raw_data_2020-03-24-07_ts_timestamp_check"
Detail: Failing row contains (25631259, 4161341a-ad79-4021-b6fa-f6754f34f5cb, frequency, 50.6228485107421875, 1585026909342000, 2020-03-24 07:15:09, 2020-03-24 07:15:21.33603, 2020-03-24 07:15:21.33603).
Where: SQL statement "INSERT INTO "dwh.raw_data_2020-03-24-07" (equipment_id,parameter_id,value,ts_original,ts_timestamp) VALUES($1,$2,$3,$4,$5)"
PL/pgSQL function dwh.fact_raw_insert_function() line 38 at EXECUTE
SQL statement "insert into dwh.fact_measures_raw (equipment_id,
parameter_id,
value,
ts_original,
ts_timestamp)
select id, column_name, cast(column_value as float8),cast(ts as bigint),
to_timestamp( NULLIF(ts, '')::bigint/1000000)
from dwh.vw_stg_raw
where column_value is not null
and column_name not in ('ts','created_at')
and created_at < date_insert"
PL/pgSQL function dwh.insert_fact_measures_raw() line 6 at SQL statement


Может у меня еще где-то есть проблема?
У меня такое ощущение что проблема в части создания новой таблицы-секции, но я не понимаю, блин, как это дебагнуть. Я просто пришел из мира SQL Server и только начинаю свои первые шаги в постгресе...
...
Рейтинг: 0 / 0
24.03.2020, 10:53
    #39940465
Melkij
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Ошибка при создании секционированной таблицы в постгресе
kirill demidov
А как бы вы создавали динамические секции?

Никак.
Какие разделы нужны известно заранее.

kirill demidov
start_of_hour := to_char((NEW.ts_timestamp), 'YYYY-MM-DD HH24:DD:SS') || '-01';

И что же тут может пойти не так...
Посмотрите какой check constraint создали и почему оно violates для заданного timestamp. Опять же весьма очевидно.
...
Рейтинг: 0 / 0
24.03.2020, 11:15
    #39940474
Павел Лузанов
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Ошибка при создании секционированной таблицы в постгресе
kirill demidov,

Посмотрите на timescaledb .
То что вам нужно оно умеет делать.
Хотя в долгосрочной перспективе у меня есть сомнения.
...
Рейтинг: 0 / 0
24.03.2020, 11:37
    #39940486
kirill demidov
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Ошибка при создании секционированной таблицы в постгресе
Melkij,

Заранее почасовые секции для таблицы с более чем миллионом транзакций в час на ближайший год сделать проблематично - "Это же так очевидно!"

У таблицы нет одного констрейнта - я ведь показал скрипт создания таблицы - других объектов нет.
...
Рейтинг: 0 / 0
24.03.2020, 11:54
    #39940490
Melkij
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Ошибка при создании секционированной таблицы в постгресе
kirill demidov
Melkij,

Заранее почасовые секции для таблицы с более чем миллионом транзакций в час на ближайший год сделать проблематично - "Это же так очевидно!"

Миллион в час - это не много.
Тысячи партиций - это много. Слишком много для OLTP.

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

kirill demidov
У таблицы нет одного констрейнта - я ведь показал скрипт создания таблицы - других объектов нет.

CREATE TABLE %I (CHECK ( - вы писали?
Вот таблица. На ней constraint. Почему это вдруг "нет одного констрейнта" когда он есть?
...
Рейтинг: 0 / 0
24.03.2020, 15:41
    #39940614
kirill demidov
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Ошибка при создании секционированной таблицы в постгресе
Melkij,
спасибо - буду проверять где проблема в процедуре и почему не работает инсерт
...
Рейтинг: 0 / 0
25.03.2020, 23:00
    #39941127
kirill demidov
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Ошибка при создании секционированной таблицы в постгресе
Поменял весь концепт секционирования!

Благодаря совету Melkij, ушел от принципа триггеров и наследования и использую функцию Partition By в момент создания таблицы

Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
CREATE TABLE dwh.fact_measures_raw (
	id serial NOT NULL,
	equipment_id varchar NULL,
	parameter_id varchar NULL,
	value float8 NULL,
	ts_original int8 NULL,
	ts_timestamp timestamp NULL,
	created_at timestamp NULL DEFAULT now(),
	updated_at timestamp NULL DEFAULT now()
) partition by range (ts_timestamp);


и динамическое создание секций еженедельно (кронтаб )с помощью процедуры:
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
CREATE OR REPLACE PROCEDURE dwh.fact_raw_measures_partitions()
 LANGUAGE plpgsql
AS $procedure$
declare
	partition_date text;
	partition_name text;
	start_date text;
	end_date text;
	i int;
	tble_name text;
	indx_name text;
begin
	i :=0;
	
	loop 
		exit when i>6 ;
		i:=i+1;
		
		partition_date := to_char((current_timestamp +  (i || ' day')::interval), 'YYYY_MM_DD');
		partition_name :=  'dwh.fact_measures_raw_' || partition_date;
		start_date := to_char((current_timestamp+ (i || ' day')::interval), 'YYYY-MM-DD');
		end_date := to_char((current_timestamp+ (i+1 || ' day')::interval), 'YYYY-MM-DD');
		tble_name = 'fact_measures_raw_'|| partition_date;
		indx_name = 'idx_ts_timestamp' || partition_date;

		if not exists (select 1 from information_schema.tables where table_name= tble_name ) then
		EXECUTE format('CREATE TABLE %s partition of dwh.fact_measures_raw for values from (%L) to (%L)',
				partition_name, start_date, end_date);
		execute format('CREATE INDEX %s ON %s USING btree (ts_timestamp);',indx_name,partition_name);

		end if;

	end loop ;
end;
$procedure$
;



Melkij спасибо за совет!

Тему можно закрывать
...
Рейтинг: 0 / 0
24.04.2020, 15:33
    #39951048
MacArrow
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Ошибка при создании секционированной таблицы в постгресе
Уважаемые, доброго времени суток!
Помогите старому ораклисту, у которого кривая судьбы завернула в сторону PG, понять, что не так синтаксисом!

Пытаюсь создать секционированную таблицу, сделал всё по доке (вроде бы), более того, используемый инструмент сгенерил тот же самый скрипт что и написал сам:

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
CREATE TABLE dm_schema.test_create_section_table (
	col_serial serial NOT NULL,
	col_ineger integer NOT NULL,
	col_varchar varchar(10) NULL,
	col_numeric numeric NULL,
	col_timestamp timestamp NULL,
	col_date date NOT NULL
)
PARTITION BY range (col_date)
TABLESPACE tabsp_data
;



Выдаёт ошибку:
Код: sql
1.
ERROR: cannot specify default tablespace for partitioned relations



Подскажите, что не так? Перелопатил Гугл, что-нибудь вразумительного не нашёл...
Версия 12.2
...
Рейтинг: 0 / 0
24.04.2020, 15:51
    #39951058
Melkij
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Ошибка при создании секционированной таблицы в постгресе
MacArrow,

голова партицированной таблицы не может указывать tablespace. tablespace могут быть определены для разделов с данными.
...
Рейтинг: 0 / 0
24.04.2020, 16:13
    #39951077
MacArrow
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Ошибка при создании секционированной таблицы в постгресе
Melkij
MacArrow,

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


О! Спасибо! Отработало!
Где-то в Гугле вычитал, что наоборот, нужно явное указание ТС... Вот и купился!
...
Рейтинг: 0 / 0
27.04.2020, 22:13
    #39952125
MacArrow
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Ошибка при создании секционированной таблицы в постгресе
Melkij,

потребовалось другое решение... но возникли трудности с реализацией.
Подскажите пожалуйста, как обойти ошибку? Или же как это правильно реализовать в PG?
Версия 12.2

Таблица с секциями по методу "список" и по полю типа "дата":
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
CREATE TABLE dm_schema.test_create_section_table (
	col_serial serial NOT NULL,
	col_ineger integer NOT NULL,
	col_varchar varchar(10) NULL,
	col_numeric numeric NULL,
	col_timestamp timestamp NULL,
	col_date date NULL,
	od_dt date NOT NULL
)
PARTITION BY LIST (od_dt);


Но при создании секции выдаёт ошибку:
Код: plsql
1.
CREATE TABLE dm_schema.test_create_section_table_2020_04_02 partition of test_create_section_table for values in ('od_dt');


Ошибка:
Код: plaintext
ERROR: invalid input syntax for type date: "od_dt"

В общем, вопрос: как избавиться/обойти?
...
Рейтинг: 0 / 0
27.04.2020, 23:02
    #39952142
Melkij
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Ошибка при создании секционированной таблицы в постгресе
MacArrow,

а что вы сделать хотите? Показанный partition разумеется некорректный.
...
Рейтинг: 0 / 0
28.04.2020, 09:48
    #39952235
MacArrow
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Ошибка при создании секционированной таблицы в постгресе
Melkij,

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

Всё верно я интерпретирую? И обходов никаких не может быть?
...
Рейтинг: 0 / 0
28.04.2020, 10:52
    #39952259
Melkij
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Ошибка при создании секционированной таблицы в постгресе
MacArrow
И решение тут "стандартное" - для "списка" в худшем случае должен быть тип "текст" (видимо).

Чего вдруг? Ошибку вы получаете именно потому что указанная строка 'od_dt' не есть дата. Укажите литерал даты.

MacArrow
но к сожалению, при "дате" диапазон не может быть в 1 день

Отчего же? range partition подразумевает условие from >= value < to
...
Рейтинг: 0 / 0
28.04.2020, 11:11
    #39952268
MacArrow
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Ошибка при создании секционированной таблицы в постгресе
Melkij,

Спасибо Вам за терпение и вразумительные ответы.

MelkijОтчего же? range partition подразумевает условие from >= value < to

При создании секции (условно: " from '01.01.2020' to '01.01.2020'"), выдало ошибку, что не может быть диапазон с одинаковыми границами... ЧЯДНТ?
...
Рейтинг: 0 / 0
28.04.2020, 11:28
    #39952274
Lonepsycho
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Ошибка при создании секционированной таблицы в постгресе
MacArrow
Melkij,

Спасибо Вам за терпение и вразумительные ответы.

MelkijОтчего же? range partition подразумевает условие from >= value < to


При создании секции (условно: " from '01.01.2020' to '01.01.2020'"), выдало ошибку, что не может быть диапазон с одинаковыми границами... ЧЯДНТ?

не читаете то что вам Melkij написал

MelkijОтчего же? range partition подразумевает условие from >= value < to
...
Рейтинг: 0 / 0
28.04.2020, 11:35
    #39952276
MacArrow
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Ошибка при создании секционированной таблицы в постгресе
Lonepsycho,

А по существу?
Это как раз был его ответ на мой вопрос о том, что нельзя создать диапазон в 1 день (в условном примере).
...
Рейтинг: 0 / 0
28.04.2020, 11:47
    #39952281
Melkij
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Ошибка при создании секционированной таблицы в постгресе
for values from '01.01.2020' to '01.01.2020' означает условие:

'01.01.2020' >= value and value < '01.01.2020' and value is not null

Что в принципе невозможно ни для какого значения. Всегда пустая таблица.

Партиция для данных первого января записывается как for values from ('2020-01-01') to ('2020-01-02'). До второго января, не включая его.
...
Рейтинг: 0 / 0
28.04.2020, 11:57
    #39952287
MacArrow
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Ошибка при создании секционированной таблицы в постгресе
Melkij,

Огромнейшее спасибо!
...
Рейтинг: 0 / 0
Форумы / PostgreSQL [игнор отключен] [закрыт для гостей] / Ошибка при создании секционированной таблицы в постгресе / 22 сообщений из 22, страница 1 из 1
Целевая тема:
Создать новую тему:
Автор:
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]