Partycjnowanie tablicy w PostgreSQL
W poniższym przykładzie pokazuję, jak zdefiniować funkcję wyzwalaną, która automatycznie tworzy nowe partycje w tabeli na podstawie daty. Taka funkcja przydaje się zwłaszcza przy pracy z dużymi zbiorami danych, gdzie miesięczne partycjonowanie pozwala na łatwiejsze zarządzanie danymi i poprawę wydajności.
Poniższy kod tworzy funkcję, która będzie wywoływana przy dodawaniu nowego rekordu do głównej tabeli. Jeśli partycja dla bieżącego miesiąca nie istnieje, funkcja ją utworzy i doda do odpowiedniego schematu. Dzięki temu nie musimy ręcznie dodawać nowych tabel co miesiąc – system sam tworzy je w trakcie pracy.
CREATE OR REPLACE FUNCTION log_insert_trigger()
RETURNS TRIGGER AS $$
DECLARE l_year double precision;
DECLARE l_month double precision;
DECLARE l_year_next double precision;
DECLARE l_month_next double precision;
DECLARE s_month text;
DECLARE s_table text;
DECLARE i_tbl_count int;
BEGIN
l_year:=(EXTRACT(YEAR FROM NEW."downloadDate"));
l_month:=(EXTRACT(MONTH FROM NEW."downloadDate"));
l_year_next:=(EXTRACT(YEAR FROM (NEW."downloadDate" + interval '1 month')));
l_month_next:=(EXTRACT(MONTH FROM (NEW."downloadDate" + interval '1 month')));
IF (l_month < 10) THEN
s_month := '0' || l_month;
ELSE
s_month := l_month;
END IF;
s_table := 'log_y' || l_year || 'm' || s_month;
SELECT count(*) INTO i_tbl_count FROM pg_tables WHERE tablename = s_table AND schemaname = 'lps';
IF (i_tbl_count < 1) THEN
EXECUTE 'CREATE TABLE lps.' || s_table || ' ('
|| 'CHECK ( "downloadDate" >= DATE ''' || l_year || '-' || l_month || '-01'' '
|| 'AND "downloadDate" < DATE ''' || l_year_next || '-' || l_month_next || '-01'' )'
|| ') INHERITS (lps.log);';
END IF;
EXECUTE 'INSERT INTO lps.' || s_table || ' VALUES ($1.*)' USING NEW;
RETURN NULL;
END;
$$
LANGUAGE plpgsql;
Dzięki takiemu podejściu funkcja jest w pełni automatyczna i nie wymaga przygotowywania partycji z wyprzedzeniem.