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

Kører PostgreSQL langsomt? Tips og tricks til at komme til kilden

Som en PostgreSQL-databaseadministrator er der de daglige forventninger til at tjekke sikkerhedskopier, anvende DDL-ændringer, sikre sig, at logfilerne ikke har nogen spilbruds-FEJL'er og besvare paniske opkald fra udviklere, hvis rapporter kører dobbelt så længe som normalt, og de har et møde om ti minutter.

Selv med en god forståelse af sundheden for administrerede databaser, vil der altid dukke nye sager og nye problemer op i forhold til ydeevne og hvordan databasen "føles". Uanset om det er en panisk e-mail eller en åben billet til "databasen føles langsom", kan denne almindelige opgave generelt følges med et par trin for at kontrollere, om der er et problem med PostgreSQL, og hvad problemet kan være.

Dette er på ingen måde en udtømmende vejledning, og trinene skal heller ikke udføres i nogen bestemt rækkefølge. Men det er snarere et sæt indledende skridt, der kan tages for at hjælpe med at finde de almindelige lovovertrædere hurtigt, samt få ny indsigt i, hvad problemet kan være. En udvikler ved måske, hvordan applikationen fungerer og reagerer, men databaseadministratoren ved, hvordan databasen agerer og reagerer på applikationen, og sammen kan problemet findes.

BEMÆRK: De forespørgsler, der skal udføres, skal udføres som en superbruger, såsom 'postgres' eller enhver databasebruger, der har givet superbrugertilladelserne. Begrænsede brugere vil enten blive afvist eller få data udeladt.

Trin 0 - Informationsindsamling

Få så meget information som muligt fra den, der siger, at databasen virker langsom; specifikke forespørgsler, applikationer, der er tilsluttet, tidsrammer for langsom ydeevne osv. Jo flere oplysninger de giver, jo lettere bliver det at finde problemet.

Trin 1 - Tjek pg_stat_activity

Anmodningen kan komme i mange forskellige former, men hvis "langsomhed" er det generelle problem, er kontrol af pg_stat_activity det første skridt til at forstå, hvad der foregår. Visningen pg_stat_activity (dokumentation for hver kolonne i denne visning kan findes her) indeholder en række for hver serverproces/forbindelse til databasen fra en klient. Der er en håndfuld nyttige oplysninger i denne visning, som kan hjælpe.

BEMÆRK: pg_stat_activity har været kendt for at ændre struktur over tid og forfine de data, den præsenterer. Forståelse af selve kolonnerne vil hjælpe med at bygge forespørgsler dynamisk efter behov i fremtiden.

Bemærkelsesværdige kolonner i pg_stat_activity er:

  1. forespørgsel:en tekstkolonne, der viser den forespørgsel, der i øjeblikket udføres, venter på at blive udført eller sidst blev udført (afhængigt af tilstanden). Dette kan hjælpe med at identificere, hvilke forespørgsler en udvikler muligvis rapporterer, der kører langsomt.
  2. client_addr:IP-adressen, som denne forbindelse og forespørgsel stammer fra. Hvis den er tom (eller Null), stammer den fra localhost.
  3. backend_start, xact_start, query_start:Disse tre giver et tidsstempel for, hvornår hver startede. Backend_start repræsenterer hvornår forbindelsen til databasen blev etableret, xact_start er når den aktuelle transaktion startede, og query_start er når den aktuelle (eller sidste) forespørgsel startede.
  4. tilstand:Tilstanden for forbindelsen til databasen. Aktiv betyder, at den i øjeblikket udfører en forespørgsel, 'tomgang' betyder, at den venter på yderligere input fra klienten, 'tom i transaktion' betyder, at den venter på yderligere input fra klienten, mens den holder en åben transaktion. (Der er andre, men deres sandsynlighed er sjælden. Se dokumentationen for mere information).
  5. datname:Navnet på den database, som forbindelsen i øjeblikket er forbundet til. I flere databaseklynger kan dette hjælpe med at isolere problematiske forbindelser.
  6. wait_event_type og wait_event:Disse kolonner vil være nul, når en forespørgsel ikke venter, men hvis den venter, vil de indeholde oplysninger om, hvorfor forespørgslen venter, og udforskning af pg_locks kan identificere, hvad den venter på. (PostgreSQL 9.5 og tidligere har kun en boolesk kolonne kaldet 'waiting', sand hvis venter, falsk hvis ikke.

1.1. Venter/blokerer forespørgslen?

Hvis der er en specifik forespørgsel eller forespørgsler, der er "langsomme" eller "hængte", skal du kontrollere, om de venter på, at en anden forespørgsel fuldføres. På grund af relationslåsning kan andre forespørgsler låse en tabel og ikke lade andre forespørgsler få adgang til eller ændre data, før den forespørgsel eller transaktion er udført.

PostgreSQL 9.5 og tidligere:

SELECT * FROM pg_stat_activity WHERE waiting = TRUE;

PostgreSQL 9.6:

SELECT * FROM pg_stat_activity WHERE wait_event IS NOT NULL;

PostgreSQL 10 og nyere (?):

SELECT * FROM pg_stat_activity WHERE wait_event IS NOT NULL AND backend_type = 'client backend';

Resultaterne af denne forespørgsel vil vise alle forbindelser, der i øjeblikket venter på en anden forbindelse for at frigive låse på en relation, der er nødvendig.

Hvis forespørgslen er blokeret af en anden forbindelse, er der nogle måder at finde ud af, hvad de er. I PostgreSQL 9.6 og nyere tillader funktionen pg_blocking_pids() input af et proces-id, der bliver blokeret, og det vil returnere en række proces-id'er, der er ansvarlige for at blokere det.

PostgreSQL 9.6 og nyere:

SELECT * FROM pg_stat_activity 
WHERE pid IN (SELECT pg_blocking_pids(<pid of blocked query>));

PostgreSQL 9.5 og tidligere:

SELECT blocked_locks.pid     AS blocked_pid,
         blocked_activity.usename  AS blocked_user,
         blocking_locks.pid     AS blocking_pid,
         blocking_activity.usename AS blocking_user,
         blocked_activity.query    AS blocked_statement,
         blocking_activity.query   AS current_statement_in_blocking_process
   FROM  pg_catalog.pg_locks         blocked_locks
    JOIN pg_catalog.pg_stat_activity blocked_activity  ON blocked_activity.pid = blocked_locks.pid
    JOIN pg_catalog.pg_locks         blocking_locks 
        ON blocking_locks.locktype = blocked_locks.locktype
        AND blocking_locks.DATABASE IS NOT DISTINCT FROM blocked_locks.DATABASE
        AND blocking_locks.relation IS NOT DISTINCT FROM blocked_locks.relation
        AND blocking_locks.page IS NOT DISTINCT FROM blocked_locks.page
        AND blocking_locks.tuple IS NOT DISTINCT FROM blocked_locks.tuple
        AND blocking_locks.virtualxid IS NOT DISTINCT FROM blocked_locks.virtualxid
        AND blocking_locks.transactionid IS NOT DISTINCT FROM blocked_locks.transactionid
        AND blocking_locks.classid IS NOT DISTINCT FROM blocked_locks.classid
        AND blocking_locks.objid IS NOT DISTINCT FROM blocked_locks.objid
        AND blocking_locks.objsubid IS NOT DISTINCT FROM blocked_locks.objsubid
        AND blocking_locks.pid != blocked_locks.pid
    JOIN pg_catalog.pg_stat_activity blocking_activity ON blocking_activity.pid = blocking_locks.pid
   WHERE NOT blocked_locks.GRANTED;

(Tilgængelig fra PostgreSQL Wiki).

Disse forespørgsler vil pege på det, der blokerer et specifikt PID, der er angivet. Med det kan der træffes en beslutning om at afbryde blokeringsforespørgslen eller forbindelsen eller lade den køre.

Trin 2 - Hvis forespørgslerne kører, hvorfor tager de så lang tid?

2.1. Kører planlæggeren forespørgsler effektivt?

Hvis en forespørgsel (eller et sæt af forespørgsler) har statussen "aktiv", så kører den faktisk. Hvis hele forespørgslen ikke er tilgængelig i pg_stat_activity, skal du hente den fra udviklerne eller postgresql-loggen og begynde at udforske forespørgselsplanlæggeren.

EXPLAIN SELECT * FROM postgres_stats.table_stats t JOIN hosts h ON (t.host_id = h.host_id) WHERE logged_date >= '2018-02-01' AND logged_date < '2018-02-04' AND t.india_romeo = 569;
Nested Loop  (cost=0.280..1328182.030 rows=2127135 width=335)
  ->  Index Scan using six on victor_oscar echo  (cost=0.280..8.290 rows=1 width=71)
          Index Cond: (india_romeo = 569)
  ->  Append  (cost=0.000..1306902.390 rows=2127135 width=264)
        ->  Seq Scan on india_echo romeo  (cost=0.000..0.000 rows=1 width=264)
                Filter: ((logged_date >= '2018-02-01'::timestamp with time zone) AND (logged_date < '2018-02-04'::timestamp with time zone) AND (india_romeo = 569))
        ->  Seq Scan on juliet victor_echo  (cost=0.000..437153.700 rows=711789 width=264)
                Filter: ((logged_date >= '2018-02-01'::timestamp with time zone) AND (logged_date < '2018-02-04'::timestamp with time zone) AND (india_romeo = 569))
        ->  Seq Scan on india_papa quebec_bravo  (cost=0.000..434936.960 rows=700197 width=264)
                Filter: ((logged_date >= '2018-02-01'::timestamp with time zone) AND (logged_date < '2018-02-04'::timestamp with time zone) AND (india_romeo = 569))
        ->  Seq Scan on two oscar  (cost=0.000..434811.720 rows=715148 width=264)
                Filter: ((logged_date >= '2018-02-01'::timestamp with time zone) AND (logged_date < '2018-02-04'::timestamp with time zone) AND (india_romeo = 569))

Dette eksempel viser en forespørgselsplan for en joinforbindelse med to tabeller, der også rammer en opdelt tabel. Vi leder efter alt, der kan få forespørgslen til at være langsom, og i dette tilfælde laver planlæggeren flere sekventielle scanninger på partitioner, hvilket tyder på, at de mangler indekser. Tilføjelse af indekser til disse tabeller for kolonnen "india_romeo" vil øjeblikkeligt forbedre denne forespørgsel.

Ting du skal kigge efter er sekventielle scanninger, indlejrede loops, dyr sortering osv. Forståelse af forespørgselsplanlæggeren er afgørende for at sikre, at forespørgsler fungerer bedst muligt, officiel dokumentation kan læses for mere information her.

2.2. Er de involverede tabeller oppustede?

Hvis forespørgslerne stadig føles langsomme, uden at forespørgselsplanlæggeren peger på noget indlysende, er det tid til at tjekke de involverede tabellers helbred. Er de for store? Er de oppustede?

SELECT n_live_tup, n_dead_tup from pg_stat_user_tables where relname = ‘mytable’;
n_live_tup  | n_dead_tup
------------+------------
      15677 |    8275431
(1 row)

Her ser vi, at der er mange gange flere døde rækker end levende rækker, hvilket betyder, at for at finde de rigtige rækker, skal motoren gennemsøge data, der ikke engang er relevante for at finde rigtige data. Et vakuum/vakuum fuldt på dette bord vil øge ydeevnen betydeligt.

Trin 3 - Tjek logfilerne

Hvis problemet stadig ikke kan findes, skal du tjekke logfilerne for eventuelle spor.

FATALE/FEJL-meddelelser:

Se efter beskeder, der kan forårsage problemer, såsom dødvande eller lange ventetider for at få en låsning.

Kontrolpunkter

Forhåbentlig er log_checkpoints sat til on, som vil skrive checkpoint information til loggene. Der er to typer kontrolpunkter, tidsindstillede og anmodede (tvungne). Hvis kontrolpunkter bliver tvunget, skal beskidte buffere i hukommelsen skrives til disken, før flere forespørgsler behandles, hvilket kan give et databasesystem en generel følelse af "langsomhed". Forøgelse af checkpoint_segments eller max_wal_size (afhængigt af databaseversionen) vil give checkpointeren mere plads at arbejde med, samt hjælpe baggrundsskriveren med at tage noget af skrivebelastningen.

Trin 4 - Hvad er værtssystemets helbred?

Hvis der ikke er spor i selve databasen, er værten måske selv overbelastet eller har problemer. Alt fra en overbelastet IO-kanal til disk, overfyldt hukommelse til at bytte eller endda et defekt drev, ingen af ​​disse problemer ville være tydelige med noget, vi så på før. Hvis vi antager, at databasen kører på et *nix-baseret operativsystem, er her et par ting, der kan hjælpe.

4.1. Systembelastning

Brug 'top' til at se på belastningsgennemsnittet for værten. Hvis antallet nærmer sig eller overstiger antallet af kerner på systemet, kan det simpelthen være for mange samtidige forbindelser, der rammer databasen, hvilket bringer den til en gennemgang for at indhente det.

load average: 3.43, 5.25, 4.85

4.2. Systemhukommelse og SWAP

Ved at bruge 'gratis' skal du kontrollere, om SWAP overhovedet er blevet brugt. Hukommelse, der flyder over til SWAP i et PostgreSQL-databasemiljø, er ekstremt dårligt for ydeevnen, og mange DBA'er vil endda fjerne SWAP fra databaseværter, da en fejl med 'uden for hukommelse' er mere at foretrække end et trægt system for mange.

Hvis SWAP bruges, vil en genstart af systemet rydde det ud, og det kan være nødvendigt at øge den samlede systemhukommelse eller omkonfigurere hukommelsesforbruget til PostgreSQL (såsom at sænke shared_buffers eller work_mem).

[[email protected] ~]$ free -m
              total        used        free      shared  buff/cache   available
Mem:           7986         225        1297          12        6462        7473
Swap:          7987        2048        5939

4.3. Diskadgang

PostgreSQL forsøger at gøre meget af sit arbejde i hukommelsen og sprede skrivning til disk for at minimere flaskehalse, men på et overbelastet system med tung skrivning er det let muligt at se tunge læsninger og skrivninger forårsage, at hele systemet bliver langsommere, når det indhenter på kravene. Hurtigere diske, flere diske og IO-kanaler er nogle måder at øge mængden af ​​arbejde, der kan udføres.

Værktøjer som 'iostat' eller 'iotop' kan hjælpe med at finde ud af, om der er en diskflaskehals, og hvor den kan komme fra.

4.4. Tjek logfilerne

Hvis alt andet fejler, eller selv hvis ikke, skal logs altid kontrolleres for at se, om systemet rapporterer noget, der ikke er rigtigt. Vi har allerede diskuteret kontrol af postgresql.logs, men systemlogfilerne kan give information om problemer såsom svigtende diske, svigtende hukommelse, netværksproblemer osv. Ethvert af disse problemer kan få databasen til at handle langsomt og uforudsigeligt, så en god forståelse af perfekt helbred kan hjælpe med at finde disse problemer.

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

Trin 5 - Noget der stadig ikke giver mening?

Selv de mest erfarne administratorer vil løbe ind i noget nyt, der ikke giver mening. Det er her, det globale PostgreSQL-fællesskab kan komme ind for at hjælpe. Ligesom trin #0, jo mere klar information der gives til fællesskabet, jo lettere kan de hjælpe.

5.1. PostgreSQL-postlister

Da PostgreSQL er udviklet og administreret af open source-fællesskabet, er der tusindvis af mennesker, der taler gennem mailinglisterne for at diskutere utallige emner, herunder funktioner, fejl og ydeevneproblemer. Mailinglisterne kan findes her, hvor pgsql-admin og pgsql-performance er de vigtigste for at søge hjælp med ydeevneproblemer.

5.2. IRC

Freenode er vært for flere PostgreSQL-kanaler med udviklere og administratorer over hele verden, og det er ikke svært at finde en hjælpsom person til at spore, hvor problemer kan komme fra. Mere information kan findes på PostgreSQL IRC-siden.


  1. 9.6 Scariest Patch Tournament

  2. Hvordan kan jeg lave en UPDATE-sætning med JOIN i SQL Server?

  3. Sorter efter ugedag fra mandag til søndag

  4. kan ikke oprette udvidelse uden superbrugerrolle