Co je dělení dat?
U databází s extrémně velkými tabulkami je dělení skvělým a lstivým trikem pro návrháře databází, jak zlepšit výkon databáze a podstatně zjednodušit údržbu. Maximální povolená velikost tabulky v databázi PostgreSQL je 32 TB, ale pokud nebude spuštěna na dosud nevynalezeném počítači z budoucnosti, mohou nastat problémy s výkonem u tabulky s pouhou setinou tohoto prostoru.
Rozdělení rozděluje tabulku na více tabulek a obecně se provádí tak, že aplikace přistupující k tabulce nezaznamenají žádný rozdíl, kromě rychlejšího přístupu k datům, která potřebuje. Rozdělením tabulky do více tabulek je myšlenkou umožnit provádění dotazů tak, aby bylo nutné skenovat mnohem menší tabulky a indexy, aby se nalezla potřebná data. Bez ohledu na to, jak efektivní je strategie indexování, bude skenování indexu pro tabulku, která má 50 GB, vždy mnohem rychlejší než index, který je pro tabulku s 500 GB. To platí i pro skenování tabulek, protože někdy je skenování tabulek prostě nevyhnutelné.
Při zavádění dělené tabulky do plánovače dotazů je potřeba vědět a pochopit několik věcí o samotném plánovači dotazů. Před skutečným provedením jakéhokoli dotazu plánovač dotazů provede dotaz a naplánuje nejefektivnější způsob přístupu k datům. Díky rozdělení dat do různých tabulek se plánovač může rozhodnout, ke kterým tabulkám bude přistupovat a které tabulky zcela ignorovat, na základě toho, co každá tabulka obsahuje.
Toho se dosáhne přidáním omezení do rozdělených tabulek, která definují, jaká data jsou v každé tabulce povolena, a s dobrým návrhem můžeme nechat plánovač dotazů skenovat malou podmnožinu dat, nikoli celou věc.
Měl by být stůl rozdělen na oddíly?
Dělení oddílů může drasticky zlepšit výkon na stole, pokud je provedeno správně, ale pokud je provedeno špatně nebo když není potřeba, může výkon zhoršit, dokonce i nepoužitelný.
Jak velký je stůl?
Neexistuje žádné skutečné pevné pravidlo pro to, jak velká musí být tabulka, než bude možnost rozdělení na oddíly, ale na základě trendů v přístupu k databázi začnou uživatelé a správci databází vidět, jak se výkon na konkrétní tabulce začíná snižovat, jak se zvětšuje. Obecně by se o rozdělení mělo uvažovat pouze tehdy, když někdo řekne:„Nemohu udělat X, protože tabulka je příliš velká.“ Pro některé hostitele může být 200 GB správný čas na rozdělení, pro jiné může být čas na rozdělení, když dosáhne 1 TB.
Pokud se zjistí, že tabulka je „příliš velká“, je čas podívat se na vzory přístupu. Buď tím, že známe aplikace, které přistupují k databázi, nebo sledováním protokolů a generováním sestav dotazů pomocí něčeho jako pgBadger, můžeme vidět, jak se přistupuje k tabulce, a podle toho, jak se k ní přistupuje, můžeme mít možnosti pro dobrou strategii dělení.
Chcete-li se dozvědět více o pgBadger a jak jej používat, přečtěte si náš předchozí článek o pgBadger.
Je problém s nadýmáním stolu?
Aktualizované a odstraněné řádky mají za následek mrtvé n-tice, které je nakonec potřeba vyčistit. Vysávání stolů, ať už ručně nebo automaticky, prochází každý řádek v tabulce a určuje, zda má být znovu získán nebo ponechán sám. Čím větší je tabulka, tím déle tento proces trvá a tím více systémových prostředků se využívá. I když 90 % tabulky tvoří neměnná data, musí být naskenována při každém spuštění vakua. Rozdělení tabulky může pomoci zredukovat stůl, který potřebuje vysávat, na menší, snížit množství neměnných dat, která je třeba skenovat, celkově zkrátit dobu vysávání a uvolnit více systémových zdrojů pro přístup uživatelů, nikoli pro údržbu systému.
Jak se data smažou, pokud vůbec?
Pokud jsou data mazána podle plánu, řekněme, že jsou smazána a archivována data starší než 4 roky, mohlo by to mít za následek těžké zásahy do příkazů delete, jejichž spuštění může nějakou dobu trvat, a jak již bylo zmíněno dříve, vytváření mrtvých řádků, které je třeba vysát. Pokud je implementována dobrá strategie dělení, vícehodinový příkaz DELETE s následnou údržbou vysávání by se mohl změnit na minutový příkaz DROP TABLE na starém měsíčním stole s nulovou údržbou vakua.
Jak by měl být stůl rozdělen?
Klíče pro přístupové vzory jsou v klauzuli WHERE a podmínkách JOIN. Kdykoli dotaz specifikuje sloupce v klauzulích WHERE a JOIN, říká databázi „toto jsou data, která chci“. Podobně jako při navrhování indexů, které se zaměřují na tyto klauzule, strategie dělení spoléhají na zacílení na tyto sloupce, aby se oddělila data a aby dotaz měl přístup k co nejmenšímu počtu oddílů.
Příklady:
- Tabulka transakcí se sloupcem data, který se vždy používá v klauzuli where.
- Tabulka zákazníků se sloupci umístění, jako je země bydliště, která se vždy používá v klauzulích where.
Nejběžnějšími sloupci, na které je třeba se zaměřit při dělení na oddíly, jsou obvykle časová razítka, protože obvykle velkou část dat tvoří historické informace a pravděpodobně budou mít poměrně předvídatelná data rozložená do různých časových seskupení.
Určete rozložení dat
Jakmile zjistíme, na kterých sloupcích se mají oddíly dělit, měli bychom se podívat na rozložení dat s cílem vytvořit velikosti oddílů, které rozloží data co nejrovnoměrněji mezi různé podřízené oddíly.
severalnines=# SELECT DATE_TRUNC('year', view_date)::DATE, COUNT(*) FROM website_views GROUP BY 1 ORDER BY 1;
date_trunc | count
------------+----------
2013-01-01 | 11625147
2014-01-01 | 20819125
2015-01-01 | 20277739
2016-01-01 | 20584545
2017-01-01 | 20777354
2018-01-01 | 491002
(6 rows)
V tomto příkladu zkrátíme sloupec časového razítka na roční tabulku, což má za následek přibližně 20 milionů řádků za rok. Pokud všechny naše dotazy specifikují datum (data) nebo rozsah dat a ty uvedené obvykle pokrývají data v rámci jednoho roku, může to být skvělá počáteční strategie pro rozdělení, protože by to vedlo k jedné tabulce za rok. , se zvládnutelným počtem řádků na tabulku.
Stáhněte si Whitepaper Today Správa a automatizace PostgreSQL s ClusterControlZjistěte, co potřebujete vědět k nasazení, monitorování, správě a škálování PostgreSQLStáhněte si WhitepaperVytvoření dělené tabulky
Existuje několik způsobů, jak vytvořit dělené tabulky, my se však zaměříme hlavně na nejbohatší dostupný typ, dělení založené na spouštěčech. Aby to fungovalo, vyžaduje to ruční nastavení a trochu kódování v procedurálním jazyce plpgsql.
Funguje tak, že má nadřazenou tabulku, která se nakonec vyprázdní (nebo zůstane prázdná, pokud se jedná o novou tabulku), a podřízené tabulky, které ZDĚDÍ nadřazenou tabulku. Při dotazu na nadřazenou tabulku jsou také vyhledána data v podřízených tabulkách kvůli INHERIT aplikovanému na podřízené tabulky. Protože však podřízené tabulky obsahují pouze podmnožiny nadřazených dat, přidáme do tabulky OMEZENÍ, které provede KONTROLU a ověří, že data odpovídají tomu, co je v tabulce povoleno. To dělá dvě věci:Za prvé odmítne data, která nepatří, a za druhé sdělí plánovači dotazů, že v této tabulce jsou povolena pouze data odpovídající tomuto CHECK CONSTRAINT, takže pokud hledáte data, která neodpovídají tabulce, ani se neobtěžujte to hledat.
Nakonec aplikujeme spouštěč na nadřazenou tabulku, která provede uloženou proceduru, která rozhodne, do které podřízené tabulky vloží data.
Vytvořit tabulku
Vytvoření nadřazené tabulky je jako vytváření jakékoli jiné tabulky.
severalnines=# CREATE TABLE data_log (data_log_sid SERIAL PRIMARY KEY,
date TIMESTAMP WITHOUT TIME ZONE DEFAULT NOW(),
event_details VARCHAR);
CREATE TABLE
Vytvoření podřízených tabulek
Vytváření podřízených tabulek je podobné, ale zahrnuje některé doplňky. Z organizačních důvodů budou naše podřízené tabulky existovat v samostatném schématu. Udělejte to pro každou podřízenou tabulku a podle toho změňte podrobnosti.
POZNÁMKA:Název sekvence použité v nextval() pochází ze sekvence, kterou vytvořil rodič. To je zásadní pro to, aby všechny podřízené tabulky používaly stejnou sekvenci.
severalnines=# CREATE SCHEMA part;
CREATE SCHEMA
severalnines=# CREATE TABLE part.data_log_2018 (data_log_sid integer DEFAULT nextval('public.data_log_data_log_sid_seq'::regclass),
date TIMESTAMP WITHOUT TIME ZONE DEFAULT NOW(),
event_details VARCHAR)
INHERITS (public.data_log);
CREATE TABLE
severalnines=# ALTER TABLE ONLY part.data_log_2018
ADD CONSTRAINT data_log_2018_pkey PRIMARY KEY (data_log_sid);
ALTER TABLE
severalnines=# ALTER TABLE part.data_log_2018 ADD CONSTRAINT data_log_2018_date CHECK (date >= '2018-01-01' AND date < '2019-01-01');
ALTER TABLE
Vytvořit funkci a spouštěč
Nakonec vytvoříme naši uloženou proceduru a přidáme spouštěč do naší nadřazené tabulky.
severalnines=# CREATE OR REPLACE FUNCTION
public.insert_trigger_table()
RETURNS trigger
LANGUAGE plpgsql
AS $function$
BEGIN
IF NEW.date >= '2018-01-01' AND NEW.date < '2019-01-01' THEN
INSERT INTO part.data_log_2018 VALUES (NEW.*);
RETURN NULL;
ELSIF NEW.date >= '2019-01-01' AND NEW.date < '2020-01-01' THEN
INSERT INTO part.data_log_2019 VALUES (NEW.*);
RETURN NULL;
END IF;
END;
$function$;
CREATE FUNCTION
severalnines=# CREATE TRIGGER insert_trigger BEFORE INSERT ON data_log FOR EACH ROW EXECUTE PROCEDURE insert_trigger_table();
CREATE TRIGGER
Otestujte to
Nyní, když je vše vytvořeno, pojďme to otestovat. V tomto testu jsem přidal další roční tabulky pokrývající roky 2013–2020.
Poznámka:Odpověď na vložení níže je „INSERT 0 0“, což by naznačovalo, že se nic nevložilo. Tomu se budeme věnovat později v tomto článku.
severalnines=# INSERT INTO data_log (date, event_details) VALUES ('2018-08-20 15:22:14', 'First insert');
INSERT 0 0
severalnines=# SELECT * FROM data_log WHERE date >= '2018-08-01' AND date < '2018-09-01';
data_log_sid | date | event_details
--------------+----------------------------+---------------
1 | 2018-08-17 23:01:38.324056 | First insert
(1 row)
Existuje, ale podívejme se na plánovač dotazů, abychom se ujistili, že řádek pochází ze správné podřízené tabulky a nadřazená tabulka nevrátila vůbec žádné řádky.
severalnines=# EXPLAIN ANALYZE SELECT * FROM data_log;
QUERY PLAN
------------------------------------------------------------------------------------------------------------------
Append (cost=0.00..130.12 rows=5813 width=44) (actual time=0.016..0.019 rows=1 loops=1)
-> Seq Scan on data_log (cost=0.00..1.00 rows=1 width=44) (actual time=0.007..0.007 rows=0 loops=1)
-> Seq Scan on data_log_2015 (cost=0.00..21.30 rows=1130 width=44) (actual time=0.001..0.001 rows=0 loops=1)
-> Seq Scan on data_log_2013 (cost=0.00..17.80 rows=780 width=44) (actual time=0.001..0.001 rows=0 loops=1)
-> Seq Scan on data_log_2014 (cost=0.00..17.80 rows=780 width=44) (actual time=0.001..0.001 rows=0 loops=1)
-> Seq Scan on data_log_2016 (cost=0.00..17.80 rows=780 width=44) (actual time=0.001..0.001 rows=0 loops=1)
-> Seq Scan on data_log_2017 (cost=0.00..17.80 rows=780 width=44) (actual time=0.001..0.001 rows=0 loops=1)
-> Seq Scan on data_log_2018 (cost=0.00..1.02 rows=2 width=44) (actual time=0.005..0.005 rows=1 loops=1)
-> Seq Scan on data_log_2019 (cost=0.00..17.80 rows=780 width=44) (actual time=0.001..0.001 rows=0 loops=1)
-> Seq Scan on data_log_2020 (cost=0.00..17.80 rows=780 width=44) (actual time=0.001..0.001 rows=0 loops=1)
Planning time: 0.373 ms
Execution time: 0.069 ms
(12 rows)
Dobrá zpráva, jeden řádek, který jsme vložili, přistál v tabulce 2018, kam patří. Ale jak vidíme, dotaz neurčuje klauzuli where pomocí sloupce data, takže aby bylo možné vše načíst, plánovač dotazů a provádění provedlo sekvenční skenování každé jednotlivé tabulky.
Dále otestujeme pomocí klauzule where.
severalnines=# EXPLAIN ANALYZE SELECT * FROM data_log WHERE date >= '2018-08-01' AND date < '2018-09-01';
QUERY PLAN
------------------------------------------------------------------------------------------------------------------------------------------------
Append (cost=0.00..2.03 rows=2 width=44) (actual time=0.013..0.014 rows=1 loops=1)
-> Seq Scan on data_log (cost=0.00..1.00 rows=1 width=44) (actual time=0.007..0.007 rows=0 loops=1)
Filter: ((date >= '2018-08-01 00:00:00'::timestamp without time zone) AND (date < '2018-09-01 00:00:00'::timestamp without time zone))
-> Seq Scan on data_log_2018 (cost=0.00..1.03 rows=1 width=44) (actual time=0.006..0.006 rows=1 loops=1)
Filter: ((date >= '2018-08-01 00:00:00'::timestamp without time zone) AND (date < '2018-09-01 00:00:00'::timestamp without time zone))
Planning time: 0.591 ms
Execution time: 0.041 ms
(7 rows)
Zde můžeme vidět, že plánovač dotazů a provádění provedlo sekvenční skenování dvou tabulek, nadřazené a podřízené tabulky pro rok 2018. Existují podřízené tabulky pro roky 2013 - 2020, ale jiné než 2018 nebyly nikdy zpřístupněny, protože klauzule where má rozsah patřící pouze do roku 2018. Plánovač dotazů vyloučil všechny ostatní tabulky, protože CHECK CONSTRAINT považuje za nemožné, aby data v těchto tabulkách existovala.
Pracovní oddíly s přísnými nástroji ORM nebo ověřením vložených řádků
Jak bylo zmíněno dříve, příklad, který jsme vytvořili, vrací „INSERT 0 0“, i když jsme vložili řádek. Pokud aplikace vkládající data do těchto dělených tabulek spoléhají na ověření správnosti vložených řádků, tyto selžou. Existuje oprava, ale přidává další vrstvu složitosti do dělené tabulky, takže ji lze ignorovat, pokud tento scénář není problémem pro aplikace používající dělenou tabulku.
Použití pohledu místo nadřazené tabulky.
Opravou tohoto problému je vytvoření zobrazení, které se dotazuje nadřazené tabulky, a přímé příkazy INSERT do zobrazení. Vkládání do pohledu může znít bláznivě, ale právě zde nastává spoušť pohledu.
severalnines=# CREATE VIEW data_log_view AS
SELECT data_log.data_log_sid,
data_log.date,
data_log.event_details
FROM data_log;
CREATE VIEW
severalnines=# ALTER VIEW data_log_view ALTER COLUMN data_log_sid SET default nextval('data_log_data_log_sid_seq'::regclass);
ALTER VIEW
Dotazování tohoto pohledu bude vypadat stejně jako dotaz na hlavní tabulku a klauzule WHERE i JOINS budou fungovat podle očekávání.
Zobrazit konkrétní funkci a spouštěč
Namísto použití funkce a triggeru, které jsme definovali dříve, budou oba mírně odlišné. Změny tučně.
CREATE OR REPLACE FUNCTION public.insert_trigger_view()
RETURNS trigger
LANGUAGE plpgsql
AS $function$
BEGIN
IF NEW.date >= '2018-01-01' AND NEW.date < '2019-01-01' THEN
INSERT INTO part.data_log_2018 VALUES (NEW.*);
RETURN NEW;
ELSIF NEW.date >= '2019-01-01' AND NEW.date < '2020-01-01' THEN
INSERT INTO part.data_log_2019 VALUES (NEW.*);
RETURN NEW;
END IF;
END;
$function$;
severalnines=# CREATE TRIGGER insert_trigger INSTEAD OF INSERT ON data_log_view FOR EACH ROW EXECUTE PROCEDURE insert_trigger_view();
Definice „INSTEAD OF“ převezme příkaz insert na pohledu (který by stejně nefungoval) a místo toho spustí funkci. Funkce, kterou jsme definovali, má velmi specifický požadavek na provedení ‚RETURN NEW;‘ po dokončení vkládání do podřízených tabulek. Bez toho (nebo to uděláme jako předtím s ‚RETURN NULL‘) bude výsledek ‚INSERT 0 0‘ místo ‚INSERT 0 1‘, jak bychom očekávali.
Příklad:
severalnines=# INSERT INTO data_log_view (date, event_details) VALUES ('2018-08-20 18:12:48', 'First insert on the view');
INSERT 0 1
severalnines=# EXPLAIN ANALYZE SELECT * FROM data_log_view WHERE date >= '2018-08-01' AND date < '2018-09-01';
QUERY PLAN
------------------------------------------------------------------------------------------------------------------------------------------------
Append (cost=0.00..2.03 rows=2 width=44) (actual time=0.015..0.017 rows=2 loops=1)
-> Seq Scan on data_log (cost=0.00..1.00 rows=1 width=44) (actual time=0.009..0.009 rows=0 loops=1)
Filter: ((date >= '2018-08-01 00:00:00'::timestamp without time zone) AND (date < '2018-09-01 00:00:00'::timestamp without time zone))
-> Seq Scan on data_log_2018 (cost=0.00..1.03 rows=1 width=44) (actual time=0.006..0.007 rows=2 loops=1)
Filter: ((date >= '2018-08-01 00:00:00'::timestamp without time zone) AND (date < '2018-09-01 00:00:00'::timestamp without time zone))
Planning time: 0.633 ms
Execution time: 0.048 ms
(7 rows)
severalnines=# SELECT * FROM data_log_view WHERE date >= '2018-08-01' AND date < '2018-09-01';
data_log_sid | date | event_details
--------------+---------------------+--------------------------
1 | 2018-08-20 15:22:14 | First insert
2 | 2018-08-20 18:12:48 | First insert on the view
(2 rows)
Aplikace testující správnost vloženého ‚rowcount‘ zjistí, že tato oprava bude fungovat podle očekávání. V tomto příkladu jsme k našemu pohledu a uložené proceduře přidali _view, ale pokud má být tabulka rozdělena na oddíly, aniž by o tom uživatelé věděli/změnila se aplikace, pak bychom přejmenovali nadřazenou tabulku na data_log_parent a zavolali pohled starým název nadřazené tabulky.
Aktualizace řádku a změna hodnoty rozděleného sloupce
Jedna věc, kterou je třeba si uvědomit, je, že pokud provedete aktualizaci dat v dělené tabulce a změníte hodnotu sloupce na něco, co omezení nepovoluje, dojde k chybě. Pokud k tomuto typu aktualizace nikdy nedojde, lze jej ignorovat, ale pokud je to možné, měl by být napsán nový spouštěč pro procesy UPDATE, který účinně odstraní řádek ze starého podřízeného oddílu a vloží nový do oddílu nový cílový podřízený oddíl.
Vytváření budoucích oddílů
Vytváření budoucích oddílů lze provést několika různými způsoby, z nichž každý má své výhody a nevýhody.
Future Partition Creator
Externí program může být napsán pro vytvoření budoucích oddílů X-krát předtím, než budou potřeba. V příkladu rozdělení na oddíly k datu lze další potřebný oddíl k vytvoření (v našem případě 2019) nastavit tak, aby byl vytvořen někdy v prosinci. Může to být ruční skript spouštěný správcem databáze nebo nastavený tak, aby jej v případě potřeby spouštěl cron. Roční oddíly by znamenaly, že se to spouští jednou za rok, ale denní oddíly jsou běžné a každodenní úloha cron dělá šťastnější DBA.
Automatic Partition Creator
S výkonem plpgsql můžeme zachytit chyby při pokusu o vložení dat do podřízeného oddílu, který neexistuje, a za běhu vytvořit potřebný oddíl a pak zkusit vložení znovu. Tato možnost funguje dobře s výjimkou případu, kdy mnoho různých klientů vkládajících podobná data současně, může způsobit spor, kdy jeden klient vytvoří tabulku, zatímco jiný se pokusí vytvořit stejnou tabulku a dostane chybu, že již existuje. Chytré a pokročilé programování plpgsql to může opravit, ale zda to stojí za vynaložené úsilí nebo ne, je předmětem debaty. Pokud k tomuto závodnímu stavu kvůli vzorům vložek nedojde, není se čeho obávat.
Zrušení oddílů
Pokud pravidla uchovávání dat nařizují, aby se data po určité době smazala, je to snazší u dělených tabulek, pokud jsou rozděleny podle sloupce data. Pokud máme smazat data stará 10 let, mohlo by to být tak jednoduché:
severalnines=# DROP TABLE part.data_log_2007;
DROP TABLE
To je mnohem rychlejší a efektivnější než příkaz „DELETE“, protože to nevede k žádným mrtvým n-ticím, které by bylo možné vyčistit vysavačem.
Poznámka:Pokud odstraňujete tabulky z nastavení oddílu, kód ve spouštěcích funkcích by měl být také změněn tak, aby nesměřoval datum na zrušenou tabulku.
Co je třeba vědět před rozdělením
Rozdělovací tabulky mohou nabídnout drastické zlepšení výkonu, ale také jej zhoršit. Před odesláním na produkční servery by měla být strategie dělení rozsáhle otestována z hlediska konzistence dat, rychlosti výkonu, všeho. Rozdělení stolu má několik pohyblivých částí, všechny by měly být otestovány, abyste se ujistili, že v nich nejsou žádné problémy.
Pokud jde o rozhodování o počtu oddílů, důrazně se doporučuje udržovat počet podřízených tabulek pod 1000 tabulek, a pokud možno ještě nižší. Jakmile se počet podřízených tabulek dostane nad ~1000, výkon začne prudce klesat, protože samotnému plánovači dotazů trvá vytvoření plánu dotazů mnohem déle. Není neslýchané, že plán dotazů trvá mnoho sekund, zatímco skutečné provedení trvá jen několik milisekund. Pokud obsluhujete tisíce dotazů za minutu, několik sekund může aplikace zastavit.
Uložené procedury spouštěče plpgsql se také mohou zkomplikovat, a pokud jsou příliš komplikované, také zpomalit výkon. Uložená procedura se provede jednou pro každý řádek vložený do tabulky. Pokud to skončí příliš velkým zpracováním každého řádku, vkládání může být příliš pomalé. Testování výkonu zajistí, že je stále v přijatelném rozsahu.
Buďte kreativní
Rozdělovací tabulky v PostgreSQL mohou být tak pokročilé, jak je potřeba. Místo sloupců s datem lze tabulky rozdělit na sloupec „země“ s tabulkou pro každou zemi. Rozdělení lze provést ve více sloupcích, jako je například sloupec „datum“ a „země“. Díky tomu bude uložená procedura manipulace s vložkami složitější, ale je to 100% možné.
Pamatujte, že cílem rozdělení je rozdělit extrémně velké tabulky na menší a udělat to dobře promyšleným způsobem, aby měl plánovač dotazů přístup k datům rychleji, než by mohl mít ve větší původní tabulce.
Deklarativní rozdělení
V PostgreSQL 10 a novějších byla představena nová funkce dělení na oddíly „Deklarativní dělení“. Je to snazší způsob, jak nastavit oddíly, má však určitá omezení. Pokud jsou omezení přijatelná, bude pravděpodobně fungovat rychleji než ruční nastavení oddílu, ale ověří to velké množství testování.
Oficiální dokumentace postgresql obsahuje informace o deklarativním rozdělování a jak funguje. Je to novinka v PostgreSQL 10 a s verzí 11 PostgreSQL na obzoru v době psaní tohoto článku jsou některá omezení opravena, ale ne všechna. Jak se PostgreSQL vyvíjí, deklarativní dělení se může stát plnou náhradou za složitější dělení popsané v tomto článku. Do té doby může být deklarativní dělení snazší alternativou, pokud žádné z omezení neomezuje potřeby dělení.
Deklarativní omezení rozdělení
Dokumentace PostgreSQL se zabývá všemi omezeními s tímto typem dělení v PostgreSQL 10, ale skvělý přehled lze nalézt na The Official PostgreSQL Wiki, kde jsou uvedena omezení ve snazším formátu a také s tím, která z nich byla opravena v nadcházející PostgreSQL 11.
Zeptejte se komunity
Správci databází po celém světě již dlouhou dobu navrhují pokročilé a vlastní rozdělovací strategie a mnoho z nás se pohybuje v IRC a e-mailových konferencích. Pokud je potřeba pomoc při rozhodování o nejlepší strategii nebo jen při vyřešení chyby v uložené proceduře, komunita je tu, aby vám pomohla.
- IRC
Freenode má velmi aktivní kanál s názvem #postgres, kde si uživatelé navzájem pomáhají porozumět konceptům, opravovat chyby nebo hledat další zdroje. - Seznamy adresátů
PostgreSQL má několik e-mailových konferencí, ke kterým se lze připojit. Sem lze posílat otázky/problémy s delším formulářem a v kteroukoli dobu mohou oslovit mnohem více lidí než IRC. Seznamy lze nalézt na webu PostgreSQL a dobrými zdroji jsou seznamy pgsql-general nebo pgsql-admin.