Diagnosticeren waarom parallellisme is uitgeschakeld
Identificeer de functies, locks en instellingen die ongemerkt seriële uitvoering afdwingen.
Diagnosticeren waarom parallellisme is uitgeschakeld is een gratis Prestaties en queryoptimalisatie in PostgreSQL-les op CoddyKit. Dit is les 4 van 4. Je kunt 3 lessen uit dit leerpad gratis volledig lezen — daarna ontgrendelt CoddyKit PRO alle lessen, plus praktische oefeningen met een ingebouwde code-editor en een AI-tutor die 24/7 beschikbaar is. Deze les maakt deel uit van het leertraject Prestaties en queryoptimalisatie in PostgreSQL. Je voortgang wordt gesynchroniseerd op het web en in de CoddyKit-app. De cursus Prestaties en queryoptimalisatie in PostgreSQL bevat in totaal 4 lessen.
Wanneer het plan serieel wordt
Je verwacht een parallelle sequentiële scan, maar EXPLAIN toont een gewoon serieel plan. Voordat je het kostenmodel van de planner de schuld geeft, moet je weten dat PostgreSQL veel harde blokkades heeft die parallellisme volledig en stilzwijgend kunnen uitschakelen.
- Sommige zijn instellingen (het maximale aantal workers staat op 0 of de lage
parallel_setup_costis nog steeds te hoog). - Sommige hebben te maken met de queryvorm (parallelonveilige functies en CTE's die schrijven).
- Sommige ontstaan tijdens de runtime (geen vrije workerplaatsen of vastgehouden vergrendelingen).
Onze taak in deze les is systematisch vaststellen welke blokkade actief werd.
Eerste blik: EXPLAIN ANALYZE
Begin door te controleren of parallellisme überhaupt is gebruikt. Een parallel plan bevat een knooppunt Gather (of Gather Merge) boven de scan die rekening houdt met parallellisme. Als je alleen een gewone Seq Scan ziet, werden geen workers als geschikt beschouwd.
De regels Workers Planned en Workers Launched laten zien of de planner workers wenste en of hij ze tijdens de uitvoering daadwerkelijk kreeg — twee heel verschillende problemen.
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 ordersGepland tegenover gestart: twee foutmodi
Maak nauwkeurig onderscheid tussen de twee symptomen:
- Workers Planned: 0 — de planner besloot dat parallellisme niet was toegestaan of niet de moeite waard was. Dit is een blokkade tijdens het plannen (instellingen, een parallelonveilige query of kosten).
- Workers Planned: 2, Workers Launched: 0 — het plan is parallel, maar tijdens de uitvoering waren er geen vrije workerplaatsen. Dit is een probleem door uitputting tijdens de runtime.
Als je deze twee verwart, verspil je uren. Lees altijd beide regels voordat je een hypothese opstelt.
Blokkade 1: de workerinstellingen
De meest voorkomende oorzaak van Workers Planned: 0 is de configuratie. Controleer eerst deze drie instellingen:
max_parallel_workers_per_gather— als deze op 0 staat, is parallellisme wereldwijd uitgeschakeld voor queries. Dit is de belangrijkste oorzaak.max_parallel_workers— de grootte van de pool; deze moet > 0 zijn en ≤max_worker_processes.max_worker_processes— de absolute limiet voor alle achtergrondworkers.
Bekijk ze in één keer:
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'
);Blokkade 2: tabelgrootte en kostendrempels
Zelfs als workers zijn ingeschakeld, weigert de planner parallellisme wanneer de relatie te klein lijkt. Twee instellingen bepalen dit:
min_parallel_table_scan_size(standaard 8 MB) — een heap die kleiner is dan dit wordt nooit parallel gescand.min_parallel_index_scan_size(standaard 512 kB) — hetzelfde principe voor indexscans.
Daarnaast benadelen parallel_setup_cost (standaard 1000) en parallel_tuple_cost (standaard 0,1) parallelle plannen; bij kleine resultaten wint het seriële plan eenvoudigweg op basis van de kosten. Controleer de werkelijke grootte van de tabel:
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;Blokkade 3: parallelonveilige functies
Eén enkele PARALLEL UNSAFE-functie waar dan ook in de query dwingt het hele plan serieel te worden — er is helemaal geen Gather. Elke functie heeft een label voor parallelle veiligheid:
- SAFE — mag in workers worden uitgevoerd.
- RESTRICTED — mag in het plan voorkomen, maar alleen in de leider, niet onder
Gather. - UNSAFE — verbiedt parallellisme voor de hele instructie.
Door gebruikers gedefinieerde functies hebben standaard de status UNSAFE, tenzij je ze expliciet markeert. Alles wat schrijft, reeksen gebruikt of tijdelijke tabellen aanraakt, is onveilig.
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;Je eigen functies controleren
Zoek UDF's die parallellisme stilzwijgend uitschakelen door elke functie die je beheert en die als onveilig of beperkt is gemarkeerd, op te sommen. Een functie die logisch zuiver is maar standaard de status UNSAFE heeft, is vaak een onzichtbare oorzaak.
Als de functie echt alleen-lezen is en geen bijwerkingen heeft, declareer je deze opnieuw als PARALLEL SAFE om de planner niet langer te blokkeren.
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;Een onveilig UDF-label corrigeren
Als je hebt bevestigd dat een functie geen bijwerkingen heeft en nooit schrijft, markeer je deze als veilig, zodat hij onder Gather kan worden uitgevoerd. Wees eerlijk: alles wat nextval() aanroept, tabellen wijzigt of niet-immutable sessiestatus gebruikt, moet beperkt of onveilig blijven.
Een werkelijk onveilige functie als veilig markeren leidt tot onjuiste resultaten of crashes van workers — dit label is een contract, geen 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';Blokkade 4: queryvormen die parallellisme blokkeren
Sommige constructies zijn ongeacht de instellingen inherent beperkt tot seriële uitvoering:
- Statements die gegevens wijzigen —
INSERT/UPDATE/DELETE(parallelle DML is beperkt; parallel schrijven wordt over het algemeen niet gebruikt). - Schrijfbare CTE's / CTE's die gegevens wijzigen — een CTE die schrijft, dwingt seriële uitvoering af.
- SELECT ... FOR UPDATE / FOR SHARE — vergrendelingsclausules zijn beperkt tot seriële uitvoering.
- Query's binnen een functie met PARALLEL UNSAFE, of query's die worden aangeroepen terwijl het buitenste statement al een schrijfactie is.
- FULL OUTER JOIN van oudsher, en gecorreleerde subquery's die verwijzen naar het bovenliggende parallelle knooppunt.
Als je query een van deze constructies bevat, kan geen enkele instelling een parallel plan opleveren.
-- 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;Poort 5: uitputting van runtime-workers
Wanneer je Workers Planned: 4 maar Workers Launched: 1 ziet, had de planner gelijk, maar was de pool leeg. De pool voor het hele cluster wordt begrensd door max_parallel_workers, gebruikt workers uit max_worker_processes en wordt gedeeld met autovacuum en andere parallelle query's.
Bij gelijktijdige uitvoering pakken query's de resterende slots — soms nul. Bekijk actieve backends om concurrentie te bevestigen:
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;Poort 6: vergrendelingen en force_parallel_mode
Twee laatste, gemakkelijk te missen poorten:
- Zware vergrendelingen — als een backend een conflicterende vergrendeling vasthoudt of erop wacht, kan deze seriële uitvoering afdwingen; ook krijgt een relation waarvoor een
ACCESS EXCLUSIVE-vergrendeling geldt (DDL) geen parallelle scan zolang deze wordt geblokkeerd. Controleerpg_locksin combinatie metpg_stat_activity. - debug_parallel_query (voorheen
force_parallel_mode) — een GUC voor tests. Als je deze instelt opon/regress, wordt een Gather afgedwongen, zelfs wanneer dat nergens op slaat, waardoor een echte diagnose kan worden vertroebeld. Controleer of deze bij normaal onderzoek opoffstaat.
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;Snelle controle: het symptoom diagnosticeren
Een analist voert EXPLAIN ANALYZE uit en ziet Workers Planned: 4 maar Workers Launched: 0. Alle worker-GUC's zijn niet nul en de tabel is 2 GB groot. Wat is de meest waarschijnlijke oorzaak?
Samenvatting: een checklist voor de diagnose
Om te bepalen waarom parallelle uitvoering is uitgeschakeld, werk je van boven naar beneden:
- Lees beide regels. Workers Planned: 0 = planningspoort; Planned>0, Launched<Planned = uitputting tijdens runtime.
- Instellingen: controleer
max_parallel_workers_per_gather(≠0),max_parallel_workersenmax_worker_processes. - Grootte/kosten: de tabel is groter dan
min_parallel_table_scan_size;parallel_setup_costdomineert geen klein resultaat. - Functies: zoek naar
proparallel <> 's'inpg_proc; corrigeer verkeerd gelabelde UDF's. - Queryvorm: schrijfacties, CTE's die gegevens wijzigen en
FOR UPDATE-vergrendelingsclausules. - Runtime: gebruik
pg_stat_activityvoor vrije slots enpg_locksvoor blokkeerders; bevestig datdebug_parallel_query = offstaat.
Koppel het symptoom aan de juiste poort, en het stille seriële plan is geen mysterie meer.
Leer SQL met een AI-tutor — gratis
Schrijf echte code en voer die uit in je browser, krijg direct hulp van een AI-tutor die 24/7 beschikbaar is en ga verder waar je gebleven bent op het web of in de app.
- Cursussen
- 22
- Lessen
- 88
Veelgestelde vragen
Is de les “Diagnosticeren waarom parallellisme is uitgeschakeld” gratis?
Ja — je kunt hier op het web alle 3 lessen van het leerpad Prestaties en queryoptimalisatie in PostgreSQL, waaronder “Diagnosticeren waarom parallellisme is uitgeschakeld”, gratis volledig lezen. Daarna ontgrendelt CoddyKit PRO alle lessen, plus interactieve oefeningen met een ingebouwde code-editor en een AI-tutor die 24/7 beschikbaar is. De cursus Prestaties en queryoptimalisatie in PostgreSQL bevat in totaal 4 lessen.
Wat leer ik in “Diagnosticeren waarom parallellisme is uitgeschakeld”?
Identificeer de functies, locks en instellingen die ongemerkt seriële uitvoering afdwingen. Je oefent met Prestaties en queryoptimalisatie in PostgreSQL door code rechtstreeks in de browser uit te voeren. Een AI-begeleider die 24/7 beschikbaar is beantwoordt je vragen terwijl je de les doorwerkt.
Heb ik ervaring nodig om met Prestaties en queryoptimalisatie in PostgreSQL te beginnen?
Ervaring vooraf is niet nodig. Prestaties en queryoptimalisatie in PostgreSQL op CoddyKit is opgebouwd voor beginners tot gevorderden, zodat je hier of bij het begin kunt starten en in je eigen tempo kunt leren. Dit is les 4 van 4.
Hoe lang duurt de les “Diagnosticeren waarom parallellisme is uitgeschakeld”?
De meeste lessen van CoddyKit duren ongeveer 5–10 minuten. Elke les is kort en interactief, zodat je gestaag vooruitgaat en op het web en in de app precies verdergaat waar je was gebleven.
Kan ik code schrijven en uitvoeren in deze les over Prestaties en queryoptimalisatie in PostgreSQL?
Ja. Elke les over Prestaties en queryoptimalisatie in PostgreSQL bevat een ingebouwde code-editor, zodat je rechtstreeks in je browser echte code kunt schrijven en uitvoeren en direct feedback van AI krijgt — lokale installatie is niet nodig.
Alle lessen in deze cursus
- Wanneer de planner parallelle plannen kiest
- Worker-aantallen en gather-kosten afstemmen
- Parallelle aggregatie en hash joins
- Diagnosticeren waarom parallellisme is uitgeschakeld