Verze 10 PostgreSQL přidala deklarativní rozdělení tabulek feature.Ve verzi 11 (aktuálně ve verzi beta) to můžete zkombinovat se zahraničními datawrappery , poskytující mechanismus pro nativní sdílení vašich tabulek na více serverech PostgreSQL.
Deklarativní rozdělení
Zvažte tabulku, která ukládá denní minimální a maximální teploty ve městech pro každý den:
CREATE TABLE temperatures (
at date,
city text,
mintemp integer,
maxtemp integer
);
Specifikace tabulky záměrně postrádá omezení sloupců a primární klíč, aby byly věci jednoduché – přidáme je později.
Je velmi běžné zjistit, že v mnoha aplikacích se častěji přistupuje k nejnovějším datům. Myslete na aktuální finanční rok, tento měsíc, poslední hodinu a tak dále. Jak naše tabulka „teplot“ roste, dává smysl přesunout stará data do jiné tabulky se stejnou strukturou. Můžeme například udělat toto:
CREATE TABLE temperatures_2017 (LIKE temperatures);
INSERT INTO temperatures_2017 SELECT * FROM temperatures WHERE
extract(year from at) = 2017;
DELETE FROM temperatures WHERE extract(year from at) = 2017;
přesunout všechny záznamy z roku 2017 do jiné tabulky. Tím zůstane hlavní tabulka „teplot“ menší a rychlejší, aby aplikace mohla pracovat. Jako bonus, pokud nyní potřebujete smazat stará data, můžete tak učinit bez zpomalení vkládání příchozích dat do hlavní/aktuální tabulky, protože stará data žijí v jiné tabulce.
Ale mít více různých tabulek znamená, že kód aplikace se nyní musí změnit. Pokud má získat přístup ke starším datům, řekněme získat roční minimální a maximální teploty města, musí nyní zjistit, jaké tabulky jsou ve schématu, dotazovat se na každou z nich a zkombinovat výsledky z každé tabulky. Můžeme to udělat bez změny kódu aplikace?
Dělení to umožňuje. V PostgreSQL 10 můžete vytvořit tabulku „teplot“ takto:
CREATE TABLE temperatures (
at date,
city text,
mintemp integer,
maxtemp integer
)
PARTITION BY RANGE (at);
To dělá z „teplot“ hlavní tabulku oddílů a říká PostgreSQL, že vytvoříme více rozdělených tabulek s nepřekrývajícími se daty, každou s jinou sadou hodnot „at“. Samotná hlavní tabulka neobsahuje žádná data, ale lze se na ni dotazovat a vkládat do aplikace – což nezná podřízené oddíly obsahující aktuální data.
A zde jsou naše oddíly:
CREATE TABLE temperatures_2017
PARTITION OF temperatures
FOR VALUES FROM ('2017-01-01') TO ('2018-01-01');
CREATE TABLE temperatures_2018
PARTITION OF temperatures
FOR VALUES FROM ('2018-01-01') TO ('2019-01-01');
Nyní máme dvě tabulky, jednu, která bude ukládat data za rok 2017 a další za rok 2018. Všimněte si, že hodnota „od“ je včetně, ale hodnota „do“ nikoli. Pojďme si to vyzkoušet:
temp=# INSERT INTO temperatures (at, city, mintemp, maxtemp)
temp-# VALUES ('2018-08-03', 'London', 63, 90);
INSERT 0 1
temp=# INSERT INTO temperatures (at, city, mintemp, maxtemp)
temp-# VALUES ('2017-08-03', 'London', 59, 70);
INSERT 0 1
temp=# SELECT * FROM temperatures;
at | city | mintemp | maxtemp
------------+--------+---------+---------
2017-08-03 | London | 59 | 70
2018-08-03 | London | 63 | 90
(2 rows)
temp=# SELECT * FROM temperatures_2017;
at | city | mintemp | maxtemp
------------+--------+---------+---------
2017-08-03 | London | 59 | 70
(1 row)
temp=# SELECT * FROM temperatures_2018;
at | city | mintemp | maxtemp
------------+--------+---------+---------
2018-08-03 | London | 63 | 90
(1 row)
„Aplikace“ je schopna vkládat a vybírat z hlavní tabulky, ale PostgreSQL směruje aktuální data do příslušných podřízených tabulek. (Oh andBTW, ty teploty jsou skutečné!)
Indexy a omezení
Indexy a omezení tabulek a sloupců jsou ve skutečnosti definovány na úrovni tabulky rozdělení, protože tam jsou skutečná data. Při vytváření tabulky oddílů můžete nastavit:
CREATE TABLE temperatures_2017
PARTITION OF temperatures (
mintemp NOT NULL,
maxtemp NOT NULL,
CHECK (mintemp <= maxtemp),
PRIMARY KEY (at, city)
)
FOR VALUES FROM ('2017-01-01') TO ('2018-01-01');
PostgreSQL 11 vám umožňuje definovat indexy na nadřazené tabulce a vytvoří indexy na existujících a budoucích tabulkách oddílů. Přečtěte si více zde.
Foreign Data Wrapper
Funkce zalamování cizích dat v Postgresu již nějakou dobu existuje. PostgreSQL vám umožňuje přistupovat k datům uloženým na jiných serverech a systémech pomocí tohoto mechanismu. To, co nás zajímá, je „postgres_fdw“, což je to, co nám umožní přístup k jednomu serveru Postgres z jiného.
„postgres_fdw“ je rozšíření přítomné ve standardní distribuci, které lze nainstalovat pomocí běžného příkazu CREATE EXTENSION:
CREATE EXTENSION postgres_fdw;
Předpokládejme, že máte další PostgreSQL server „box2“ s databází nazvanou „box2db“. Za tímto účelem můžete vytvořit „zahraniční server“:
CREATE SERVER box2 FOREIGN DATA WRAPPER postgres_fdw
OPTIONS (host 'box2', dbname 'box2db');
Pojďme také namapovat našeho uživatele „alice“ (uživatel, pod kterým jste přihlášeni) na uživatele box2 „box2alice“. To umožňuje, aby „alice“ byla „box2alice“ při přístupu ke vzdáleným tabulkám:
CREATE USER MAPPING FOR alice SERVER box2
OPTIONS (user 'box2alice');
Nyní máte přístup k tabulkám (také pohledům, matviews atd.) na box2. Nejprve vytvořte tabulku na box2 a poté „cizí stůl“ na vašem serveru. Cizí tabulka neuchovává žádná aktuální data, ale slouží jako proxy pro přístup k tableon box2.
-- on box2
CREATE TABLE foo (a int);
-- on your server
IMPORT FOREIGN SCHEMA public LIMIT TO (foo)
FROM SERVER box2 INTO public;
Cizí tabulka na vašem serveru se může účastnit transakcí stejně jako normální tabulky. Aplikace nemusí vědět, že tabulky, se kterými interagují, jsou místní nebo cizí – i když pokud vaše aplikace spouští SELECT, který může stáhnout spoustu řádků z cizí tabulky, může to zpomalit. V Postgres 10 byla provedena vylepšení pro potlačení spojení a agregovat na vzdálený server.
Kombinace dělení a FDW
A teď ta zábavná část:nastavení oddílů na vzdálených serverech.
Nejprve vytvořte tabulku fyzických oddílů na box2:
-- on box2
CREATE TABLE temperatures_2016 (
at date,
city text,
mintemp integer,
maxtemp integer
);
A poté vytvořte oddíl na vašem serveru jako cizí tabulku:
CREATE FOREIGN TABLE temperatures_2016
PARTITION OF temperatures
FOR VALUES FROM ('2016-01-01') TO ('2017-01-01')
SERVER box2;
Nyní můžete vkládat a dotazovat se ze svého vlastního serveru:
temp=# INSERT INTO temperatures (at, city, mintemp, maxtemp)
temp-# VALUES ('2016-08-03', 'London', 63, 73);
INSERT 0 1
temp=# SELECT * FROM temperatures ORDER BY at;
at | city | mintemp | maxtemp
------------+--------+---------+---------
2016-08-03 | London | 63 | 73
2017-08-03 | London | 59 | 70
2018-08-03 | London | 63 | 90
(3 rows)
temp=# SELECT * FROM temperatures_2016;
at | city | mintemp | maxtemp
------------+--------+---------+---------
2016-08-03 | London | 63 | 73
(1 row)
Tady to máš! Možnost vkládat řádky do vzdáleného oddílu je novinkou ve verzi 11. S touto funkcí nyní můžete mít svá data logicky (oddíly) a fyzicky (FDW) shardovat.
Správa dat
Příkazy jako VACUUM a ANALYZE fungují tak, jak byste očekávali s hlavními tabulkami oddílů – všechny místní podřízené tabulky podléhají funkcím VACUUM a ANALYZE. Oddíly lze odpojit, s daty lze manipulovat bez omezení oddílu a poté je znovu připojit. Samotné podřízené tabulky oddílů lze rozdělit.
Přesouvání dat (“reharding”) lze provádět pomocí běžných příkazů SQL (vložení, smazání, kopírování atd.). Lze vytvořit místní indexy a spouštěče.
Přidání redundance do vašich fragmentů lze snadno dosáhnout pomocí logické nebo streamingové replikace.