sql >> Database teknologi >  >> RDS >> PostgreSQL

En guide til partitionering af data i PostgreSQL

Hvad er datapartitionering?

For databaser med ekstremt store tabeller er partitionering et vidunderligt og smart trick for databasedesignere til at forbedre databaseydeevnen og gøre vedligeholdelsen meget lettere. Den maksimale tilladte tabelstørrelse i en PostgreSQL-database er 32TB, men medmindre den kører på en computer, der endnu ikke er opfundet, kan der opstå problemer med ydeevnen på en tabel med kun en hundrededel af den plads.

Partitionering opdeler en tabel i flere tabeller og udføres generelt på en måde, så applikationer, der får adgang til tabellen, ikke bemærker nogen forskel, bortset fra at være hurtigere til at få adgang til de data, den har brug for. Ved at opdele tabellen i flere tabeller er ideen at tillade udførelsen af ​​forespørgslerne for at skulle scanne meget mindre tabeller og indekser for at finde de nødvendige data. Uanset hvor effektiv en indeksstrategi er, vil scanning af et indeks for en tabel, der er 50GB, altid være meget hurtigere end et indeks, der er for en tabel på 500GB. Dette gælder også for tabelscanninger, for nogle gange er tabelscanninger bare uundgåelige.

Når du introducerer en opdelt tabel til forespørgselsplanlæggeren, er der et par ting, du skal vide og forstå om selve forespørgselsplanlæggeren. Før en forespørgsel rent faktisk udføres, vil forespørgselsplanlæggeren tage forespørgslen og planlægge den mest effektive måde, den vil få adgang til dataene på. Ved at lade dataene opdeles på tværs af forskellige tabeller, kan planlæggeren beslutte, hvilke tabeller der skal tilgås, og hvilke tabeller der skal ignoreres fuldstændigt, baseret på hvad hver tabel indeholder.

Dette gøres ved at tilføje begrænsninger til de opdelte tabeller, der definerer, hvilke data der er tilladt i hver tabel, og med et godt design kan vi få forespørgselsplanlæggeren til at scanne en lille delmængde af data i stedet for det hele.

Skal en tabel opdeles?

Partitionering kan drastisk forbedre ydeevnen på et bord, når det gøres rigtigt, men hvis det gøres forkert, eller når det ikke er nødvendigt, kan det gøre ydeevnen dårligere, endda ubrugelig.

Hvor stort er bordet?

Der er ingen reel streng regel for, hvor stor en tabel skal være, før partitionering er en mulighed, men baseret på databaseadgangstendenser vil databasebrugere og administratorer begynde at se, at ydeevnen på en specifik tabel begynder at blive forringet, efterhånden som den bliver større. Generelt bør partitionering kun overvejes, når nogen siger "Jeg kan ikke lave X, fordi bordet er for stort." For nogle værter kan 200 GB være det rigtige tidspunkt at partitionere, for andre kan det være tid til partitionering, når det rammer 1 TB.

Hvis bordet er fast besluttet på at være "for stort", er det tid til at se på adgangsmønstrene. Enten ved at kende de applikationer, der tilgår databasen, eller ved at overvåge logfiler og generere forespørgselsrapporter med noget som pgBadger, kan vi se, hvordan en tabel tilgås, og afhængigt af, hvordan den tilgås, kan vi have muligheder for en god partitioneringsstrategi.

For at lære mere om pgBadger og hvordan man bruger det, se venligst vores tidligere artikel om pgBadger.

Er bordoppustethed et problem?

Opdaterede og slettede rækker resulterer i døde tupler, der i sidste ende skal ryddes op. Støvsugning af tabeller, hvad enten det er manuelt eller automatisk, gennemgår hver række i tabellen og afgør, om den skal genvindes eller lades alene. Jo større bordet er, jo længere tid tager denne proces, og jo flere systemressourcer bruges. Selvom 90 % af en tabel er uændrede data, skal den scannes hver gang et vakuum køres. Opdeling af bordet kan hjælpe med at reducere den tabel, der skal støvsuges, til mindre, reducere mængden af ​​uforanderlige data, der skal scannes, mindre tid til støvsugning generelt og flere systemressourcer frigivet til brugeradgang frem for systemvedligeholdelse.

Hvordan slettes data, hvis overhovedet?

Hvis data slettes efter en tidsplan, f.eks. at data ældre end 4 år bliver slettet og arkiveret, kan dette resultere i hårdtslående delete-udsagn, der kan tage tid at køre, og som før nævnt, skabe døde rækker, der skal støvsuges. Hvis en god opdelingsstrategi implementeres, kan en DELETE-udsagn på flere timer med støvsugningsvedligeholdelse efterfølgende omdannes til en DROP TABLE-erklæring på et minut på en gammel månedstabel uden vakuumvedligeholdelse.

Hvordan skal bordet opdeles?

Nøglerne til adgangsmønstre er i WHERE-klausulen og JOIN-betingelserne. Hver gang en forespørgsel specificerer kolonner i WHERE- og JOIN-sætningerne, fortæller den databasen "dette er de data, jeg vil have". Ligesom at designe indekser, der målretter mod disse klausuler, er partitioneringsstrategier afhængige af at målrette disse kolonner for at adskille data og have forespørgselsadgang så få partitioner som muligt.

Eksempler:

  1. En transaktionstabel med en datokolonne, der altid bruges i en where-klausul.
  2. En kundetabel med placeringskolonner, f.eks. bopælsland, der altid bruges i where-klausuler.

De mest almindelige kolonner at fokusere på til partitionering er normalt tidsstempler, da en stor del af data normalt er historisk information og sandsynligvis vil have ret forudsigelige data spredt på tværs af forskellige tidsgrupper.

Bestem dataspredningen

Når vi har identificeret, hvilke kolonner der skal partitioneres på, bør vi tage et kig på spredningen af ​​data med det mål at skabe partitionsstørrelser, der spreder dataene så jævnt som muligt på tværs af de forskellige underordnede partitioner.

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)

I dette eksempel afkorter vi tidsstempelkolonnen til en årlig tabel, hvilket resulterer i omkring 20 millioner rækker om året. Hvis alle vores forespørgsler angiver en(e) dato(er) eller datointerval(er), og de angivne normalt dækker data inden for et enkelt år, kan dette være en god startstrategi for partitionering, da det ville resultere i en enkelt tabel pr. år , med et overskueligt antal rækker pr. tabel.

Download Whitepaper Today PostgreSQL Management &Automation med ClusterControlFå flere oplysninger om, hvad du skal vide for at implementere, overvåge, administrere og skalere PostgreSQLDownload Whitepaper

Oprettelse af en opdelt tabel

Der er et par måder at oprette partitionerede tabeller på, men vi vil hovedsageligt fokusere på den mest funktionsrige type tilgængelige, triggerbaseret partitionering. Dette kræver manuel opsætning og en smule kodning i plpgsql proceduresproget for at komme til at fungere.

Det fungerer ved at have en overordnet tabel, der i sidste ende bliver tom (eller forbliver tom, hvis det er en ny tabel), og underordnede tabeller, der ARVER den overordnede tabel. Når den overordnede tabel forespørges, søges der også efter data i de underordnede tabeller på grund af den INHERIT, der er anvendt på de underordnede tabeller. Men da underordnede tabeller kun indeholder delmængder af forældrenes data, tilføjer vi en BEGRÆNSNING på tabellen, der foretager en CHECK og verificerer, at dataene matcher, hvad der er tilladt i tabellen. Dette gør to ting:For det første afviser det data, der ikke hører til, og for det andet fortæller det forespørgselsplanlæggeren, at kun data, der matcher denne KONTROLBEGRÆNSNING, er tilladt i denne tabel, så hvis du søger efter data, der ikke matcher tabellen, skal du gider ikke engang at søge efter det.

Til sidst anvender vi en trigger til den overordnede tabel, der udfører en lagret procedure, der bestemmer, hvilken underordnet tabel der skal placeres dataene.

Opret tabel

Oprettelse af den overordnede tabel er ligesom enhver anden tabeloprettelse.

severalnines=# CREATE TABLE data_log (data_log_sid SERIAL PRIMARY KEY,
  date TIMESTAMP WITHOUT TIME ZONE DEFAULT NOW(),
  event_details VARCHAR);
CREATE TABLE

Opret underordnede tabeller

Oprettelse af underordnede tabeller ligner hinanden, men involverer nogle tilføjelser. Af organisatoriske årsager vil vi have vores underordnede tabeller til at eksistere i et separat skema. Gør dette for hver underordnet tabel, og ændr detaljerne i overensstemmelse hermed.

BEMÆRK:Navnet på sekvensen brugt i nextval() kommer fra sekvensen som forælderen oprettede. Dette er afgørende for, at alle underordnede tabeller bruger den samme sekvens.

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

Opret funktion og trigger

Til sidst opretter vi vores lagrede procedure og tilføjer triggeren til vores overordnede tabel.

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

Test det

Nu hvor det hele er skabt, lad os teste det. I denne test har jeg tilføjet flere årlige tabeller, der dækker 2013 - 2020.

Bemærk:Indsæt-svaret nedenfor er 'INSERT 0 0', hvilket tyder på, at det ikke indsatte noget. Dette vil blive behandlet senere i denne artikel.

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)

Den findes, men lad os se på forespørgselsplanlæggeren for at sikre, at rækken kom fra den korrekte underordnede tabel, og at den overordnede tabel slet ikke returnerede nogen rækker.

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)

Gode ​​nyheder, den enkelte række, vi indsatte, landede i 2018-tabellen, hvor den hører hjemme. Men som vi kan se, specificerer forespørgslen ikke en where-klausul ved hjælp af datokolonnen, så for at hente alt, lavede forespørgselsplanlæggeren og udførelsen en sekventiel scanning på hver enkelt tabel.

Lad os derefter teste ved at bruge en where-klausul.

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)

Her kan vi se, at forespørgselsplanlæggeren og udførelsen foretog en sekventiel scanning på to tabeller, den overordnede og den underordnede tabel for 2018. Der er underordnede tabeller for årene 2013 - 2020, men de andre end 2018 blev aldrig tilgået, fordi where-klausulen har et interval, der kun hører til inden for 2018. Forespørgselsplanlæggeren udelukkede alle de andre tabeller, fordi CHECK CONSTRAINT anser det for umuligt for data at eksistere i disse tabeller.

Arbejdspartitioner med strenge ORM-værktøjer eller indsat rækkevalidering

Som nævnt før returnerer eksemplet vi byggede en 'INSERT 0 0', selvom vi indsatte en række. Hvis de programmer, der indsætter data i disse opdelte tabeller, er afhængige af at verificere, at de indsatte rækker er korrekte, vil disse mislykkes. Der er en rettelse, men det tilføjer endnu et lag af kompleksitet til den partitionerede tabel, så den kan ignoreres, hvis dette scenarie ikke er et problem for de programmer, der bruger den partitionerede tabel.

Brug af en visning i stedet for den overordnede tabel.

Løsningen til dette problem er at oprette en visning, der forespørger på den overordnede tabel, og dirigere INSERT-sætninger til visningen. Det lyder måske skørt at indsætte i en visning, men det er her, triggeren på visningen kommer ind.

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

Forespørgsel i denne visning vil ligne at forespørge i hovedtabellen, og WHERE-sætninger samt JOINS vil fungere som forventet.

Se specifik funktion og trigger

I stedet for at bruge den funktion og trigger, vi definerede før, vil de begge være lidt forskellige. Ændringer med fed skrift.

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();

"INSTEAD OF"-definitionen overtager insert-kommandoen på visningen (som alligevel ikke ville fungere), og udfører funktionen i stedet for. Den funktion, vi definerede, har et meget specifikt krav om at lave en 'RETURN NY;' efter indsættelsen i de underordnede tabeller er fuldført. Uden dette (eller at gøre det som vi gjorde før med 'RETURN NULL') vil resultere i 'INSERT 0 0' i stedet for 'INSERT 0 1', som vi ville forvente.

Eksempel:

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)

Programmer, der tester for indsat 'rowcount' for at være korrekt, vil finde denne rettelse til at fungere som forventet. I dette eksempel tilføjede vi _view til vores visning og lagrede procedure, men hvis tabellen ønskes partitioneret uden at nogen brugere ved det/applikationsændring, så vil vi omdøbe den overordnede tabel til data_log_parent, og kalde visningen af ​​den gamle overordnet tabels navn.

Opdatering af en række og ændring af den opdelte kolonneværdi

En ting, du skal være opmærksom på, er, at hvis du udfører en opdatering af dataene i den opdelte tabel og ændrer værdien af ​​kolonnen til noget, der ikke er tilladt af begrænsningen, vil det resultere i en fejl. Hvis denne type opdatering aldrig vil ske, så kan den ignoreres, men hvis det er en mulighed, bør der skrives en ny trigger for UPDATE-processer, som effektivt vil slette rækken fra den gamle underordnede partition og indsætte en ny i ny underordnet målpartition.

Oprettelse af fremtidige partitioner

Oprettelse af fremtidige partitioner kan gøres på et par forskellige måder, hver med deres fordele og ulemper.

Fremtidig partitionsskaber

Et eksternt program kan skrives op for at oprette fremtidige partitioner X gang før de er nødvendige. I et partitioneringseksempel partitioneret på en dato, kunne den næste nødvendige partition at oprette (i vores tilfælde 2019) indstilles til at blive oprettet engang i december. Dette kan være et manuelt script, der køres af databaseadministratoren, eller indstillet til at få cron til at køre det, når det er nødvendigt. Årlige partitioner ville betyde, at den kører en gang om året, men daglige partitioner er almindelige, og et dagligt cron-job giver en gladere DBA.

Automatisk partitionsoprettelse

Med kraften i plpgsql kan vi fange fejl, hvis vi forsøger at indsætte data i en underordnet partition, der ikke eksisterer, og straks oprette den nødvendige partition, og derefter prøve at indsætte igen. Denne mulighed fungerer godt undtagen i det tilfælde, hvor mange forskellige klienter, der indsætter lignende data på samme tid, kan forårsage en race-tilstand, hvor en klient opretter bordet, mens en anden forsøger at oprette den samme tabel og får en fejl om, at den allerede eksisterer. Smart og avanceret plpgsql-programmering kan løse dette, men hvorvidt det er indsatsen værd eller ej, er til debat. Hvis denne løbstilstand ikke vil ske på grund af indsatsmønstrene, så er der intet at bekymre sig om.

Slet partitioner

Hvis regler for dataopbevaring dikterer, at data slettes efter et vist tidsrum, bliver dette lettere med opdelte tabeller, hvis de opdeles på en datokolonne. Hvis vi skal slette data, der er 10 år gamle, kan det være så simpelt som:

severalnines=# DROP TABLE part.data_log_2007;
DROP TABLE

Dette er meget hurtigere og mere effektivt end en "DELETE"-erklæring, da det ikke resulterer i nogen døde tupler at rydde op med et vakuum.

Bemærk:Hvis du fjerner tabeller fra partitionsopsætningen, skal koden i triggerfunktionerne også ændres til ikke at lede datoen til den tabte tabel.

Ting at vide før partitionering

Opdelingstabeller kan tilbyde en drastisk forbedring af ydeevnen, men det kan også gøre det værre. Før du skubber til produktionsservere, bør partitioneringsstrategien testes grundigt for datakonsistens, ydeevnehastighed, alt. Opdeling af et bord har nogle få bevægelige dele, de bør alle testes for at sikre, at der ikke er nogen problemer.

Når det kommer til at bestemme antallet af partitioner, anbefales det stærkt at holde antallet af underordnede borde under 1000 tabeller og endda lavere, hvis det er muligt. Når antallet af underordnede tabel kommer over ~1000, begynder ydeevnen at tage et dyk, da selve forespørgselsplanlæggeren ender med at tage meget længere tid bare at lave forespørgselsplanen. Det er ikke uhørt, at en forespørgselsplan tager mange sekunder, mens selve udførelsen kun tager et par millisekunder. Hvis du betjener tusindvis af forespørgsler i minuttet, kan flere sekunder bringe applikationer i stå.

Plpgsql-udløser lagrede procedurer kan også blive komplicerede, og hvis de er for komplicerede, sænker de også ydeevnen. Den lagrede procedure udføres én gang for hver række, der er indsat i tabellen. Hvis det ender med at udføre for meget behandling for hver række, kan indsatser blive for langsomme. Ydeevnetest vil sikre, at det stadig er inden for et acceptabelt område.

Bliv kreativ

Opdelingstabeller i PostgreSQL kan være så avanceret som nødvendigt. I stedet for datokolonner kan tabeller opdeles i en 'land'-kolonne med en tabel for hvert land. Opdeling kan udføres på flere kolonner, såsom både en "dato" og en "land" kolonne. Dette vil gøre den lagrede procedure, der håndterer skærene mere kompleks, men det er 100 % muligt.

Husk, at målene med partitionering er at opdele ekstremt store tabeller i mindre, og gøre det på en gennemtænkt måde, så forespørgselsplanlæggeren får adgang til dataene hurtigere, end den kunne have i den større originale tabel.

Deklarativ partitionering

I PostgreSQL 10 og senere blev en ny partitioneringsfunktion 'Declarative Partitioning' introduceret. Det er en nemmere måde at opsætte partitioner på, men har nogle begrænsninger. Hvis begrænsningerne er acceptable, vil den sandsynligvis fungere hurtigere end den manuelle partitionsopsætning, men rigelige mængder af test vil bekræfte det.

Den officielle postgresql-dokumentation har information om deklarativ partitionering, og hvordan det virker. Det er nyt i PostgreSQL 10, og med version 11 af PostgreSQL i horisonten i skrivende stund, er nogle af begrænsningerne faste, men ikke dem alle. Efterhånden som PostgreSQL udvikler sig, kan Declarative Partitioning blive en fuld erstatning for den mere komplekse partitionering, der er beskrevet i denne artikel. Indtil da kan Declarative Partitioning være et lettere alternativ, hvis ingen af ​​begrænsningerne begrænser partitioneringsbehovet.

Deklarative partitioneringsbegrænsninger

PostgreSQL-dokumentationen adresserer alle begrænsningerne med denne type partitionering i PostgreSQL 10, men en god oversigt kan findes på The Official PostgreSQL Wiki, som viser begrænsningerne i et lettere at læse format, samt noterer hvilke der er blevet rettet i den kommende PostgreSQL 11.

Spørg fællesskabet

Databaseadministratorer over hele kloden har designet avancerede og tilpassede partitioneringsstrategier i lang tid, og mange af os hænger ud i IRC og mailinglister. Hvis der er brug for hjælp til at bestemme den bedste strategi, eller bare få løst en fejl i en lagret procedure, er fællesskabet her for at hjælpe.

  • IRC
    Freenode har en meget aktiv kanal kaldet #postgres, hvor brugere hjælper hinanden med at forstå koncepter, rette fejl eller finde andre ressourcer.
  • Postlister
    PostgreSQL har en håndfuld mailinglister, der kan tilsluttes. Længere form spørgsmål / spørgsmål kan sendes her, og kan nå mange flere mennesker end IRC på et givet tidspunkt. Listerne kan findes på PostgreSQL-webstedet, og listerne pgsql-general eller pgsql-admin er gode ressourcer.

  1. Logisk replikationspartitionering med PostgreSQL 13

  2. MySQL tidszoner

  3. Simulering af MySQL's ORDER BY FIELD() i Postgresql

  4. MariaDB-strengfunktioner (fuld liste)