Я работаю над таблицей базы данных в базе данных postgres, размер которой превышает 1 ТБ и в которой содержится около 2 миллиардов записей. Итак, я решил разделить таблицу на основе столбца «метка времени».
- Шаг 1. Создание таблиц разделов
CREATE TABLE bigtable_y2019 (
CHECK (timestamp >= '2019-01-01' AND timestamp < '2020-01-01')
) INHERITS (bigtable);
CREATE TABLE bigtable_y2020 (
CHECK (timestamp >= '2020-01-01' AND timestamp < '2021-01-01')
) INHERITS (bigtable);
- Шаг 2. Создание индекса для ключевого столбца (отметка времени)
CREATE UNIQUE INDEX bigtable_y2019_pkey ON bigtable_y2019 USING btree (id);
CREATE INDEX bigtable_y2019_timestamp ON bigtable_y2019 (timestamp);
CREATE UNIQUE INDEX bigtable_y2020_pkey ON bigtable_y2020 USING btree (id);
CREATE INDEX bigtable_y2020_timestamp ON bigtable_y2020 (timestamp);
- Шаг 3 Создать функцию
CREATE OR REPLACE FUNCTION bigtable_insert_trigger()
RETURNS TRIGGER AS $$
BEGIN
IF (NEW.timestamp >= '2020-01-01' AND NEW.timestamp < '2021-01-01') THEN
INSERT INTO bigtable_y2020 VALUES (NEW.*);
ELSIF (NEW.timestamp >= '2019-01-01' AND NEW.timestamp < '2020-01-01') THEN
INSERT INTO bigtable_y2019 VALUES (NEW.*);
ELSE
RAISE EXCEPTION 'Date out of range. Fix the bigtable_insert_trigger() function!';
END IF;
-- My understanding was this should have prevented inserting data into master table
RETURN NULL;
END;
$$
LANGUAGE plpgsql;
- Шаг 4. Включить триггер ВКЛ ПЕРЕД ВСТАВИТЬ СОБЫТИЕ и выполнить функцию
CREATE TRIGGER insert_bigtable_trigger BEFORE INSERT ON bigtable FOR EACH ROW EXECUTE FUNCTION bigtable_insert_trigger();
- Шаг 5. Установите для enable_partition_pruning и contstraint_exclusion значение ON
SET enable_partition_pruning = ON;
SET constraint_exclusion = ON;
Эти шаги выше вставляют запись не только в дочернюю таблицу, но и в родительскую таблицу, которую я пытаюсь избежать.
Итак, я попытался создать еще один триггер для события AFTER INSERT, чтобы удалить родительская таблица. Это не лучший подход, но моя работа вокруг, чтобы увидеть, как это работает.
- Так как RETURN NULL в tripdetail_insert_trigger не избегает вставки в главную таблицу, я создал обходной путь для удаления этой записи из главной table.
CREATE OR REPLACE FUNCTION bigtable_mastertable_record_delete_trigger()
RETURNS TRIGGER AS $$
BEGIN
DELETE FROM ONLY bigtable WHERE id = NEW.id;
END;
$$
LANGUAGE plpgsql;
CREATE TRIGGER delete_bigtable_mastertable_record_trigger AFTER INSERT ON bigtable FOR EACH ROW EXECUTE FUNCTION bigtable_mastertable_record_delete_trigger();
Между родительской и дочерней таблицами есть syn c. Если запись вставляется в дочернюю таблицу, то же самое происходит и в родительской таблице, и если запись удаляется в одной из них, то запись удаляется также и в другой.
Но я пытаюсь вставить новые записи в соответствующий дочерний элемент. таблицы на основе метки времени и в конечном итоге сделать родительскую таблицу пустой, что должно основываться на принципах работы секционирования таблицы.