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

PostgreSQL:Seks ikke-så-lette stykker

PostgreSQL kommer med et fremragende sæt funktioner, uovertruffen i open source-RDBMS-området. Det er for det meste let at lære og bruge, især for applikationsudviklere. Nogle dele er dog simpelthen ikke nemme. De kræver arbejde for at konfigurere og blive rigtigt, og de er typisk også missionskritiske.

Forbindelsesstyring

PostgreSQL lancerer en ny proces, kaldet en backend-proces , for at håndtere hver forbindelse. Dette er i modsætning til moderne eventloop/threadpool-baserede forbindelseshåndteringsarkitekturer, der findes i anden sammenlignelig serversoftware. At skabe en fuld proces tager mere tid og ressourcer og viser øgede forespørgselsforsinkelser i applikationer, hvor forbindelser åbnes og lukkes med høj hastighed.

I de fleste implementeringer er det nødvendigt at samle forbindelser på et eller andet niveau. På et applikationsniveau kan dette være at bruge dit programmeringssprog/biblioteksfunktioner. For eksempel kan sql/DB.SetMaxIdleConn bruges til at øge genbrug af forbindelse fra en enkelt Go-applikation.

Ofte bliver du dog nødt til at bruge en tredjepartsforbindelsespooling eller belastningsbalanceringsløsning. Forbindelsespoolere opretholder en pulje af inaktive forbindelser til opstrøms Postgres-serveren, som tildeles og proxes til indgående klientforbindelser. De parser typisk den SQL, der sendes af klienter for at genkende transaktionsgrænser og datamodificerende DML'er for at implementere funktioner som forbindelsespooling på transaktionsniveau og læse replikaer.

PgBouncer er en populær, letvægts pooler med enkelt binær forbindelse og køres ofte sammen med PostgreSQL i det samme system.

PgPool er mere alsidig end PgBouncer. Det kan også udføre belastningsbalancering og replikering for eksempel.

Forbindelsespooling bringer dog sit eget sæt hovedpine. For det første er det en ekstra bevægelig del, der er vedligeholdt i din installation. Opsætning af opautentificering er også en smerte, hvis du har klienter, der bruger forskellige legitimationsoplysninger eller godkendelsesmekanismer. Nogle funktioner på forbindelsesniveau som LISTEN/NOTIFY, forberedte erklæringer, midlertidige tabeller og lignende kan kræve ekstra konfiguration eller ændringer på klientsiden for at fungere.

Nul nedetidsopgraderinger

Opgradering af PostgreSQL mellem mindre versioner (13.x -> 13.y) involverer installation af den nye pakke og genstart af serverprocessen. Selvom genstart af serverprocessen nødvendigvis vil forstyrre alle tilsluttede klienter, er det stadig et rimeligt spørgsmål, da nedetiden er bundet til varigheden af ​​en servicegenstart.

Opgradering mellem større (12.x -> 13.y) versioner er dog en meget større sag. Jo flere data der er, jo mere smertefuld er processen typisk.

Den enkleste metode, der kun virker for små mængder data (f.eks. snesevis af GB), er at dumpe dataene fra den gamle version og gendanne dem til en server i ny version. En anden mulighed er at bruge pg_upgrade, som kræver en orkestreret dans involverer binære filer af begge versioner af Postgres.

I begge tilfælde ville databaserne være nede i et betydeligt stykke tid.

Ideelt set burde det være muligt at replikere til en ny versionsserver og promovere den nye versionsserver som den primære. Det er dog ikke muligt at udføre streaming-replikering til en standby-server med en anden hovedversion. Logisk replikering, selvom den ser velegnet ud til jobbet, har visse ting, der skal omgås for at sikre fuldstændig replikering.

De fleste HA-løsninger til Postgres er afhængige af streaming-replikering, og du kan derfor ikke opgradere noder i en klynge én ad gangen.

Den nuværende nyeste teknik ville være at bruge logisk replikering, mens man omgås begrænsningerne ved logisk replikering og muligvis involverer begrænsning af funktioner, som applikationer kan bruge (som DDL'er) under opgraderingsfasen.

Høj tilgængelighed

PostgreSQL kommer med alle de funktioner på lavt niveau, der kræves for at bygge en HA-løsning:replikering med feedback, kaskadereplikering, synkronreplikering, standbys, hot standbys, standby promotion og så videre. Det giver dog faktisk ikke en HA-løsning ud af kassen. Der er ingen rammer eller værktøjer til at overvåge helbred og automatisk failover til en standby. Der er ingen forestilling om en multi-node HA-klynge.

Du bliver nødt til at konfigurere og køre en tredjepartsløsning til at skabe Postgres-implementeringer med høj tilgængelighed. Aktuelle favoritter er pg_auto_failover og Patroni. Mens Patroni er afhængig af en eksisterende meget tilgængelig konfigurationsbutik som ZooKeeper eller etcd, kan pg_auto_failover klare sig uden en.

Det tager tid og kræfter at evaluere, implementere og teste en af ​​disse i produktionen. Overvågnings-, alarmerings- og ops-playbooks skal konfigureres og vedligeholdes.

Bloat Management

PostgreSQL's MVCC-arkitektur betyder, at ingen data nogensinde overskrives - ændring af en række resulterer kun i, at en ny version af rækken bliver skrevet ud til disk. Sletning af en række betyder kun at registrere, at rækken er usynlig for fremtidige transaktioner. Når en rækkeversion er utilgængelig fra igangværende eller fremtidige transaktioner, er den ikke længere til nogen nytte og kaldes "bloat". Processen med affaldsindsamling af denne oppustning kaldes "vakuum".

Bloat er usynligt for applikationer og bliver udelukkende DBA's hovedpine. For opdateringstunge tabeller er overvågning og styring af bloat et ikke-trivielt problem. Autovakuumprocessen hjælper meget, men dens tærskler skal muligvis justeres til en global eller per- bordniveau for at sikre, at bordstørrelserne ikke bliver uoverskuelige store.

Indekser påvirkes også af oppustethed, og autovakuum hjælper ikke her. Sletning af rækker og opdatering af indekserede kolonner fører til døde indtastninger i indekser. Opdateringstunge arbejdsbelastninger med opdateringer til indekserede kolonner kan føre til konstant voksende og ineffektive indekser. Der er ikke noget, der svarer til vakuum for indekser. Den eneste løsning er at genopbygge hele indekset ved at bruge REINDEX eller bruge VACUUM FULL på bordet.

Bortset fra en enkelt værdi pr. tabel (pg_stat_all_tables.n_dead_tup), tilbyder Postgres intet i vejen for at estimere bloat i en tabel, og slet intet for indekser. Den mest praktiske måde er stadig at udføre en skræmmende forespørgsel fra check_postgres.

pgmetrics inkorporerer forespørgslen fra check_postgres og kan producere output i JSON- og CSV-format, der inkluderer størrelse og bloat-oplysninger for alle tabeller og indekser; som kan føres ind i overvågnings- eller automatiseringsværktøjer.

pg_repack er et populært alternativ til VACUUM FULL – det kan udføre det samme arbejde, men uden låse. Hvis du er tvunget til at gøre VACUUM FULL regelmæssigt, er det et værktøj, du skal undersøge.

zheap er den nye lagermaskine til Postgres, der har været under udvikling i årevis, og som lover at reducere oppustethed gennem opdateringer på stedet.

Forespørgselsplanstyring

Core PostgreSQL tilbyder kun to rudimentære værktøjer i dette rum:

  • pg_stat_statements udvidelse til forespørgselsanalyse – dette giver totalen og gennemsnittet af forespørgselsplanlægning og eksekveringstider, disk- og hukommelsesbrug
  • auto_explain udvidelse, som kan udskrive forespørgselsudførelsesplaner i Postgres-logdestinationen

Mens statistikken leveret af pg_stat_statements er lige nok til at klare sig, ved at bruge auto_explain at tvinge planer ind i logfiler og derefter udtrække dem, ikke mere end et hack, især sammenlignet med kommercielle konkurrenter til Postgres, som tilbyder planhistorik, basislinjer og administrationsfunktioner.

Den aktuelle state of the art med Postgres er at mine logfilen til forespørgselsplaner og gemme dem andre steder. Men måske er det mest handicappede problem ikke at være i stand til at associere forespørgselsplanen med den tilsvarende analyse fra pg_stat_statements. Måden pgDash gør dette på er at parse både SQL-forespørgselsteksterne fra pg_stat_statements og auto_explain output, justere for manglingen udført af pg_stat_statements og prøve at matche de to. Det kræver en fuld PostgreSQL-dialekt SQL-parser.

Baselining, indstilling af politikker for planvalg osv. er bare ikke mulige i kerne PostgreSQL i øjeblikket.

Der er et par udvidelser derude, som grundlæggende er forbedrede versioner af pg_stat_statements, men de ekstra trin involveret i at bruge en tredjepartsudvidelse gør det til en udfordring for de fleste mennesker, især hvis de bruger en administreret Postgres-udbyder.

Tuning

PostgreSQL har et væld af tuning muligheder, startende fra under-configured-by-defaultshared_buffers-indstillingen. Nogle er nemme at forstå og indstille, såsom antallet af parallelle arbejdere til forskellige operationer (max_worker_processes, max_parallel_* osv.). Andre områder er lidt obskure (wal_compression, random_page_cost osv.), men generelt gavnlige. De mest irriterende er dog dem, der har brug for kvantificerbare oplysninger om arbejdsbyrden.

For eksempel, hvis work_mem er for lav, kan forespørgsler bruge midlertidige diskfiler; hvis for høj, og der er nok samtidige forespørgsler, kan Postgres backendprocesser blive OOM-dræbt. Så hvordan finder du ud af, hvilket tal du skal indstille det til?

Praktisk, især med OLTP-arbejdsbelastninger og web-applikations-arbejdsbelastninger, er det umuligt at forudsige, hvad det maksimale hukommelsesbehov for forespørgsler ville være. Dit bedste bud er at indstille den til en rimelig værdi og derefter overvåge forespørgsler for at se, om nogen af ​​dem kunne have haft gavn af en højere værdi af work_mem.

Og hvordan gør man det? Du skal hente udvidelsen auto_explain for at logge forespørgselsudførelsesplanerne for hver forespørgsel, udtræk dem fra Postgres' logfiler, undersøg hver forespørgselsplan for at se, om den bruger disk-baserede eksterne fletninger eller en bitmap-heap-scanning med tabsgivende heap-blokke.

Ikke umuligt, bare svært.


  1. Dvalesekvens på oracle, @GeneratedValue(strategi =GenerationType.AUTO)

  2. pyodbc - meget langsom bulk indsættelseshastighed

  3. ingen sqljdbc_auth i java.library.path

  4. SÆT ANTAL PÅ brug