Diagnostisere hvorfor parallellitet ble deaktivert
Finn funksjonene, låsene og innstillingene som i stillhet tvinger frem seriell kjøring.
Diagnostisere hvorfor parallellitet ble deaktivert er en gratis leksjon i Ytelse og spørringsoptimalisering i PostgreSQL på CoddyKit. Dette er leksjon 4 av 4. Du kan lese valgfritt 3 leksjoner fra denne læringsstien gratis i sin helhet – deretter låser CoddyKit PRO opp alle leksjoner, samt praktisk øving med en innebygd kodeeditor og en AI-veileder som er tilgjengelig døgnet rundt. Den er en del av læringsløpet i Ytelse og spørringsoptimalisering i PostgreSQL, og fremdriften din synkroniseres mellom nettet og CoddyKit-appen. Kurset i Ytelse og spørringsoptimalisering i PostgreSQL inneholder totalt 4 leksjoner.
Når planen blir sekvensiell
De forventer en parallell sekvensiell skanning, men EXPLAIN viser en vanlig sekvensiell plan. Før De legger skylden på kostnadsmodellen til planleggeren, bør De vite at PostgreSQL har mange harde sperrer som i stillhet kan stanse all parallellitet.
- Noen er innstillinger (maksimalt antall arbeidere satt til 0 eller for høy
parallel_setup_cost). - Noen skyldes spørringsformen (parallelitetsusikre funksjoner eller skrivende CTE-er).
- Noen skyldes kjøretiden (ingen ledige arbeiderplasser eller aktive låser).
Oppgaven i denne leksjonen er å finne systematisk ut hvilken sperre som slo inn.
Første blikk: EXPLAIN ANALYZE
Begynn med å bekrefte om parallellitet i det hele tatt ble brukt. En parallell plan inneholder en Gather- (eller Gather Merge-)node over den parallellitetsbevisste skanningen. Hvis De bare ser vanlig Seq Scan, ble ingen arbeidere vurdert som gjennomførbare.
Linjene Workers Planned og Workers Launched forteller om planleggeren ønsket arbeidere, og om den faktisk fikk dem under kjøring — to helt forskjellige feil.
EXPLAIN (ANALYZE, VERBOSE, BUFFERS)
SELECT count(*)
FROM orders
WHERE amount > 100;
-- Look for:
-- Gather (cost=...)
-- Workers Planned: 2
-- Workers Launched: 2
-- -> Parallel Seq Scan on ordersPlanlagte kontra startede: to feilmåter
Skill de to symptomene nøyaktig:
- Workers Planned: 0 — planleggeren avgjorde at parallellitet var ulovlig eller ikke lønnsom. Dette er en sperre ved planlegging (innstillinger, en parallellitetsusikker spørring eller kostnad).
- Workers Planned: 2, Workers Launched: 0 — planen er parallell, men ingen arbeiderplasser var ledige under kjøringen. Dette er et problem med ressursmangel under kjøring.
Hvis De forveksler disse, kan De kaste bort flere timer. Les alltid begge linjene før De formulerer en hypotese.
Sperre 1: Innstillinger for arbeidere
Den vanligste årsaken til Workers Planned: 0 er konfigurasjonen. Kontroller først disse tre:
max_parallel_workers_per_gather— hvis verdien er 0, er parallellitet globalt deaktivert for spørringer. Dette er den vanligste årsaken.max_parallel_workers— størrelsen på arbeidsgruppen; må være > 0 og ≤max_worker_processes.max_worker_processes— den absolutte grensen for alle bakgrunnsarbeidere.
Kontroller dem samlet:
SELECT name, setting, source
FROM pg_settings
WHERE name IN (
'max_parallel_workers_per_gather',
'max_parallel_workers',
'max_worker_processes',
'max_parallel_maintenance_workers'
);Sperre 2: Tabellstørrelse og kostnadsterskler
Selv når arbeidere er aktivert, avviser planleggeren parallellitet når relasjonen ser for liten ut. To innstillinger styrer dette:
min_parallel_table_scan_size(standard 8MB) — en heap som er mindre enn dette, skannes aldri parallelt.min_parallel_index_scan_size(standard 512kB) — samme prinsipp for indeksskanninger.
I tillegg gjør parallel_setup_cost (standard 1000) og parallel_tuple_cost (standard 0.1) parallelle planer dyrere. For små resultater vinner den sekvensielle planen ganske enkelt på kostnad. Kontroller tabellens faktiske størrelse:
SELECT pg_size_pretty(pg_relation_size('orders')) AS heap_size,
(pg_relation_size('orders') / 1024.0 / 1024.0) AS heap_mb,
current_setting('min_parallel_table_scan_size') AS min_scan;Sperre 3: Parallelitetsusikre funksjoner
Én enkelt funksjon merket PARALLEL UNSAFE hvor som helst i spørringen tvinger hele planen til å kjøre serielt – uten Gather i det hele tatt. Alle funksjoner har en etikett for parallellsikkerhet:
- SAFE – kan kjøre i arbeidere.
- RESTRICTED – kan vises i planen, men bare i lederen, ikke under
Gather. - UNSAFE – deaktiverer parallell kjøring for hele setningen.
Brukerdefinerte funksjoner har som standard UNSAFE, med mindre du uttrykkelig merker dem. Alt som skriver data, bruker sekvenser eller berører midlertidige tabeller, er utrygt.
SELECT p.proname,
p.proparallel -- 's'=safe, 'r'=restricted, 'u'=unsafe
FROM pg_proc p
WHERE p.proname IN ('normalize_email', 'nextval', 'random', 'now')
ORDER BY p.proname;Kontroll av egne funksjoner
Én enkelt PARALLEL UNSAFE-funksjon hvor som helst i spørringen tvinger hele planen til å bli sekvensiell — uten Gather i det hele tatt. Alle funksjoner har en etikett for parallellsikkerhet:
- SAFE — kan kjøres hos arbeidere.
- RESTRICTED — kan forekomme i planen, men bare hos lederen, ikke under
Gather. - UNSAFE — forbyr parallellitet for hele setningen.
Brukerdefinerte funksjoner har som standard UNSAFE med mindre De merker dem uttrykkelig. Alt som skriver, bruker sekvenser eller berører midlertidige tabeller, er usikkert.
SELECT n.nspname AS schema,
p.proname AS function,
CASE p.proparallel
WHEN 's' THEN 'safe'
WHEN 'r' THEN 'restricted'
WHEN 'u' THEN 'unsafe'
END AS parallel_safety
FROM pg_proc p
JOIN pg_namespace n ON n.oid = p.pronamespace
WHERE n.nspname NOT IN ('pg_catalog', 'information_schema')
AND p.proparallel <> 's'
ORDER BY 1, 2;Korrigering av en usikker UDF-etikett
Hvis De bekrefter at en funksjon ikke har bivirkninger og aldri skriver data, kan De merke den som sikker slik at den kan kjøres under Gather. Vær ærlig: alt som kaller nextval(), endrer tabeller eller bruker ikke-uforanderlig sesjonstilstand, må fortsatt være begrenset eller usikkert.
Hvis en faktisk usikker funksjon merkes som sikker, kan det føre til feil resultater eller at arbeidere krasjer — denne etiketten er en kontrakt, ikke et hint.
-- Only if the body is truly read-only and deterministic across workers:
ALTER FUNCTION normalize_email(text) PARALLEL SAFE;
-- Verify the new label:
SELECT proname, proparallel
FROM pg_proc
WHERE proname = 'normalize_email';Sperre 4: Spørringsformer som blokkerer parallellitet
Noen konstruksjoner er i seg selv begrenset til seriell kjøring, uavhengig av innstillinger:
- Datamodifiserende setninger —
INSERT/UPDATE/DELETE(parallell DML er begrenset; parallelle skrivinger brukes vanligvis ikke). - Skrivbare / datamodifiserende CTE-er — en CTE som skriver, tvinger frem seriell kjøring.
- SELECT ... FOR UPDATE / FOR SHARE — låseklausuler begrenser parallell kjøring.
- Spørringer i en funksjon med PARALLEL UNSAFE, eller spørringer som kalles når den ytre setningen allerede er en skriveoperasjon.
- FULL OUTER JOIN historisk sett, samt korrelerte underspørringer som refererer til den ytre parallelle noden.
Hvis spørringen inneholder noe av dette, vil ingen innstilling produsere en parallell plan.
-- This SELECT can be parallel:
EXPLAIN SELECT count(*) FROM orders WHERE amount > 100;
-- This one cannot — the locking clause is parallel-restricted:
EXPLAIN SELECT * FROM orders WHERE amount > 100 FOR UPDATE;Sperre 5: Tomt for kjørearbeidere
Når De ser Workers Planned: 4, men Workers Launched: 1, hadde planleggeren rett, men arbeidspoolen var tom. Den samlede poolen for klyngen begrenses av max_parallel_workers, hentes fra max_worker_processes og deles med autovacuum og andre parallelle spørringer.
Ved samtidig belastning tar spørringene de plassene som er ledige — noen ganger ingen. Se aktive backender for å bekrefte konkurranse om ressursene:
SELECT pid, backend_type, state, wait_event_type, wait_event, query
FROM pg_stat_activity
WHERE backend_type = 'parallel worker'
OR query ILIKE '%Gather%'
ORDER BY backend_type;Sperre 6: Låser og force_parallel_mode
To siste, men lett oversette sperrer:
- Tunge låser — hvis en backend holder eller venter på en motstridende lås, kan den bli kjørt serielt. En relasjon under en
ACCESS EXCLUSIVE-lås (DDL) får heller ikke en parallell skanning mens den er blokkert. Undersøkpg_lockssammenkoblet medpg_stat_activity. - debug_parallel_query (tidligere
force_parallel_mode) — en GUC for testing. Når den settes tilon/regress, tvinger den frem en Gather selv når det ikke gir mening, noe som kan skjule den egentlige årsaken. Sørg for at den eroffved vanlig feilsøking.
SELECT name, setting
FROM pg_settings
WHERE name IN ('debug_parallel_query', 'force_parallel_mode');
-- Who is blocking a parallel scan?
SELECT l.pid, l.mode, l.granted, a.query
FROM pg_locks l
JOIN pg_stat_activity a ON a.pid = l.pid
WHERE l.relation = 'orders'::regclass
ORDER BY l.granted;Hurtigsjekk: Diagnostisere symptomet
En analytiker kjører EXPLAIN ANALYZE og ser Workers Planned: 4, men Workers Launched: 0. Alle GUC-er for arbeidere er ulike null, og tabellen er 2 GB. Hva er den mest sannsynlige årsaken?
Oppsummering: En sjekkliste for feilsøking
Finn årsaken til at parallell kjøring ble deaktivert ved å gå gjennom punktene ovenfra og ned:
- Les begge linjene. Workers Planned: 0 = planleggingshindring; Planned>0, Launched<Planned = tomt for kjørearbeidere.
- Innstillinger: kontroller
max_parallel_workers_per_gather(≠0),max_parallel_workersogmax_worker_processes. - Størrelse/kostnad: tabellen må være større enn
min_parallel_table_scan_size;parallel_setup_costmå ikke dominere for et lite resultat. - Funksjoner: let etter
proparallel <> 's'ipg_proc; korriger feilmerkede UDF-er. - Spørringsform: skriveoperasjoner, datamodifiserende CTE-er og
FOR UPDATE-låseklausuler. - Kjøring: bruk
pg_stat_activityfor ledige plasser ogpg_locksfor blokkeringer; bekreft atdebug_parallel_query = off.
Koble symptomet til riktig sperre, så er den stille serielle planen ikke lenger et mysterium.
Lær deg SQL med en AI-veileder – gratis
Skriv og kjør ekte kode i nettleseren, få umiddelbar hjelp fra en AI-veileder som er tilgjengelig døgnet rundt, og fortsett der du slapp – på nettet eller i appen.
- Kurs
- 22
- Leksjoner
- 88
Ofte stilte spørsmål
Er leksjonen «Diagnostisere hvorfor parallellitet ble deaktivert» gratis?
Ja – du kan lese valgfritt 3 av leksjonene i læringsstien Ytelse og spørringsoptimalisering i PostgreSQL, inkludert «Diagnostisere hvorfor parallellitet ble deaktivert», gratis i sin helhet her på nettet. Deretter låser CoddyKit PRO opp alle leksjoner, samt interaktiv øving med en innebygd kodeeditor og en AI-veileder som er tilgjengelig døgnet rundt. Kurset i Ytelse og spørringsoptimalisering i PostgreSQL inneholder totalt 4 leksjoner.
Hva lærer jeg i «Diagnostisere hvorfor parallellitet ble deaktivert»?
Finn funksjonene, låsene og innstillingene som i stillhet tvinger frem seriell kjøring. Du øver på Ytelse og spørringsoptimalisering i PostgreSQL med praktisk kode som du kjører direkte i nettleseren, mens en AI-veileder som er tilgjengelig døgnet rundt, svarer på spørsmålene dine mens du jobber deg gjennom leksjonen.
Trenger jeg erfaring for å begynne med Ytelse og spørringsoptimalisering i PostgreSQL?
Ingen tidligere erfaring er nødvendig. Ytelse og spørringsoptimalisering i PostgreSQL på CoddyKit er lagt opp for både nybegynnere og viderekomne, så De kan begynne her eller helt fra start og lære i Deres eget tempo. Dette er leksjon 4 av 4.
Hvor lang tid tar leksjonen «Diagnostisere hvorfor parallellitet ble deaktivert»?
De fleste CoddyKit-leksjoner tar omtrent 5–10 minutter. Hver leksjon er kort og interaktiv, slik at De gjør jevne fremskritt og kan fortsette akkurat der De slapp – både på nettet og i appen.
Kan jeg skrive og kjøre kode i denne Ytelse og spørringsoptimalisering i PostgreSQL-leksjonen?
Ja. Alle Ytelse og spørringsoptimalisering i PostgreSQL-leksjoner har en innebygd kodeeditor, slik at De kan skrive og kjøre ekte kode direkte i nettleseren og få umiddelbar tilbakemelding fra AI – uten lokal konfigurering.
Alle leksjonene i dette kurset
- Når planleggeren velger parallelle planer
- Justere antall arbeidere og kostnader ved Gather
- Parallell aggregering og hash-sammenføyninger
- Diagnostisere hvorfor parallellitet ble deaktivert