Diagnostisera varför parallellism inaktiverades
Identifiera funktioner, lås och inställningar som i tysthet tvingar fram seriell körning.
Diagnostisera varför parallellism inaktiverades är en gratis lektion i Prestandaoptimering och frågeoptimering i PostgreSQL på CoddyKit. Detta är lektion 4 av 4. Du kan läsa vilka 3 lektioner som helst i den här lärvägen kostnadsfritt i sin helhet – därefter låser CoddyKit PRO upp alla lektioner, plus praktisk övning med en inbyggd kodredigerare och en AI-lärare dygnet runt. Den ingår i lärvägen för Prestandaoptimering och frågeoptimering i PostgreSQL, och Era framsteg synkroniseras mellan webben och CoddyKit-appen. Kursen i Prestandaoptimering och frågeoptimering i PostgreSQL innehåller totalt 4 lektioner.
När planen blir seriell
Du förväntar dig en parallell sekventiell genomsökning, men EXPLAIN visar en vanlig seriell plan. Innan du skyller på planerarens kostnadsmodell bör du känna till att PostgreSQL har många hårda spärrar som helt kan stoppa parallellism utan att det märks tydligt.
- Vissa är inställningar (maximalt antal workerprocesser är satt till 0 eller ett lågt
parallel_setup_costär fortfarande för högt). - Vissa beror på frågans form (parallellosäkra funktioner eller skrivande CTE:er).
- Vissa beror på körningen (inga lediga workerplatser eller kvarhållna lås).
Vår uppgift i den här lektionen är att systematiskt hitta vilken spärr som aktiverades.
Första titt: EXPLAIN ANALYZE
Börja med att kontrollera om parallellism över huvud taget förekommer. En parallell plan innehåller en nod av typen Gather (eller Gather Merge) ovanför den parallellmedvetna genomsökningen. Om du bara ser en vanlig Seq Scan bedömdes inga workerprocesser ens vara möjliga.
Raderna Workers Planned och Workers Launched visar om planeraren ville ha workerprocesser och om den faktiskt fick några vid körningen — två helt olika fel.
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 ordersPlanerade jämfört med startade: två fellägen
Skilj noggrant mellan de två symptomen:
- Workers Planned: 0 — planeraren beslutade att parallellism var otillåten eller inte lönade sig. Detta är en spärr vid planeringen (inställningar, en parallellosäker fråga eller kostnad).
- Workers Planned: 2, Workers Launched: 0 — planen är parallell, men inga workerplatser var lediga vid körningen. Detta är ett problem med resursbrist under körningen.
Om du blandar ihop dessa slösar du timmar. Läs alltid båda raderna innan du formulerar en hypotes.
Spärr 1: inställningar för workerprocesser
Den vanligaste orsaken till Workers Planned: 0 är konfigurationen. Kontrollera först dessa tre:
max_parallel_workers_per_gather— om värdet är 0 är parallellism globalt avstängd för frågor. Detta är den vanligaste orsaken.max_parallel_workers— storleken på poolen; måste vara > 0 och ≤max_worker_processes.max_worker_processes— den absoluta gränsen för alla bakgrundsworkerprocesser.
Inspektera dem på en gång:
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'
);Spärr 2: trösklar för tabellstorlek och kostnad
Även när arbetsprocesser är aktiverade avstår frågeplaneraren från parallellism när relationen verkar vara för liten. Två inställningar styr detta:
min_parallel_table_scan_size(standardvärde 8 MB) – en heap som är mindre än detta genomsöks aldrig parallellt.min_parallel_index_scan_size(standardvärde 512 kB) – samma princip gäller för indexskanningar.
Dessutom gör parallel_setup_cost (standardvärde 1000) och parallel_tuple_cost (standardvärde 0.1) parallella planer dyrare. För små resultatuppsättningar vinner den seriella planen helt enkelt kostnadsmässigt. Kontrollera tabellens faktiska storlek:
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;Spärr 3: parallellosäkra funktioner
Även när workerprocesser är aktiverade avvisar planeraren parallellism när relationen verkar vara för liten. Två inställningar styr detta:
min_parallel_table_scan_size(standardvärde 8MB) — en heap som är mindre än detta genomsöks aldrig parallellt.min_parallel_index_scan_size(standardvärde 512kB) — samma princip gäller för indexgenomsökningar.
Dessutom straffar parallel_setup_cost (standardvärde 1000) och parallel_tuple_cost (standardvärde 0.1) parallella planer; för små resultat vinner den seriella planen helt enkelt på kostnad. Kontrollera tabellens verkliga storlek:
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;Granska dina egna funktioner
För att hitta UDF:er som i tysthet inaktiverar parallellism kan du lista alla funktioner du äger som är märkta som osäkra eller begränsade. En funktion som logiskt sett är ren men som har standardetiketten UNSAFE är en vanlig och osynlig orsak.
Om funktionen verkligen är skrivskyddad och saknar sidoeffekter kan du deklarera om den som PARALLEL SAFE för att låta planeraren använda parallellism.
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;Korrigera en osäker UDF-etikett
Om du bekräftar att en funktion saknar sidoeffekter och aldrig skriver kan du märka den som säker, så att den kan köras under Gather. Var ärlig: allt som anropar nextval(), ändrar tabeller eller använder icke-immutabelt sessionstillstånd måste förbli begränsat eller osäkert.
Om du märker en genuint osäker funktion som säker kan det leda till felaktiga resultat eller krascher i workerprocesser — etiketten är ett kontrakt, inte ett tips.
-- 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';Spärr 4: frågeformer som blockerar parallellism
Vissa konstruktioner är alltid begränsade till seriell körning, oavsett inställningar:
- Dataändrande satser —
INSERT/UPDATE/DELETE(parallell DML är begränsad; parallella skrivningar används i allmänhet inte). - Skrivbara/dataändrande CTE:er — en CTE som skriver tvingar fram seriell körning.
- SELECT ... FOR UPDATE / FOR SHARE — låsningsklausuler är begränsade till seriell körning.
- Frågor inuti en funktion med PARALLEL UNSAFE, eller frågor som anropas när den yttre satsen redan är en skrivning.
- FULL OUTER JOIN historiskt sett, samt korrelerade underfrågor som refererar till den yttre parallella noden.
Om frågan innehåller något av detta kan ingen inställning skapa 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;Grind 5: Slut på körningsarbetare
När du ser Workers Planned: 4 men Workers Launched: 1 hade planeraren rätt, men poolen var tom. Den klusteromfattande poolen begränsas av max_parallel_workers, hämtas från max_worker_processes och delas med autovacuum och andra parallella frågor.
Vid samtidig belastning tar frågor de platser som finns kvar — ibland inga alls. Övervaka aktiva backends för att bekräfta konkurrens om resurser:
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;Grind 6: Lås och force_parallel_mode
Två sista, lättförbisedda grindar:
- Tunga lås — om en backend håller ett motstridigt lås eller väntar på ett sådant kan körningen bli seriell. Även en relation som omfattas av ett
ACCESS EXCLUSIVE-lås (DDL) får ingen parallell skanning medan den är blockerad. Inspekterapg_lockssammanfogad medpg_stat_activity. - debug_parallel_query (tidigare
force_parallel_mode) — en GUC för testning. Om den sätts tillon/regresstvingas en Gather fram även när det saknar mening, vilket kan dölja den verkliga orsaken. Kontrollera att den äroffvid normal felsökning.
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;Snabbkontroll: Diagnostisera symptomet
En analytiker kör EXPLAIN ANALYZE och ser Workers Planned: 4 men Workers Launched: 0. Alla worker-GUC:er är skilda från noll och tabellen är 2 GB. Vad är den mest sannolika orsaken?
Sammanfattning: En checklista för diagnos
Gå uppifrån och ned för att hitta varför parallellism har inaktiverats:
- Läs båda raderna. Workers Planned: 0 = planeringsgrind; Planned>0, Launched<Planned = slut på workers under körning.
- Inställningar: kontrollera
max_parallel_workers_per_gather(≠0),max_parallel_workersochmax_worker_processes. - Storlek/kostnad: tabellen ska vara större än
min_parallel_table_scan_size;parallel_setup_costfår inte dominera för ett litet resultat. - Funktioner: leta efter
proparallel <> 's'ipg_proc; korrigera felmärkta UDF:er. - Frågeform: skrivningar, dataändrande CTE:er och låsningsklausuler med
FOR UPDATE. - Körning: använd
pg_stat_activityför lediga platser ochpg_locksför blockerare; bekräfta attdebug_parallel_query = off.
Matcha symptomet mot rätt grind, så slutar den tysta seriella planen att vara ett mysterium.
Lär dig SQL med en AI-lärare – gratis
Skriv och kör riktig kod i webbläsaren, få omedelbar hjälp av en AI-lärare dygnet runt och fortsätt där du slutade – på webben eller i appen.
- Kurser
- 22
- Lektioner
- 88
Vanliga frågor
Är lektionen ”Diagnostisera varför parallellism inaktiverades” gratis?
Ja – du kan läsa vilka 3 lektioner som helst i lärvägen Prestandaoptimering och frågeoptimering i PostgreSQL, inklusive ”Diagnostisera varför parallellism inaktiverades”, kostnadsfritt i sin helhet här på webben. Därefter låser CoddyKit PRO upp alla lektioner, plus interaktiv övning med en inbyggd kodredigerare och en AI-lärare dygnet runt. Kursen i Prestandaoptimering och frågeoptimering i PostgreSQL innehåller totalt 4 lektioner.
Vad lär jag mig i ”Diagnostisera varför parallellism inaktiverades”?
Identifiera funktioner, lås och inställningar som i tysthet tvingar fram seriell körning. Ni övar på Prestandaoptimering och frågeoptimering i PostgreSQL med praktisk kod som körs direkt i webbläsaren, medan en AI-handledare som är tillgänglig dygnet runt svarar på Era frågor under lektionen.
Behöver jag någon erfarenhet för att börja lära mig Prestandaoptimering och frågeoptimering i PostgreSQL?
Du behöver inga förkunskaper. Utbildningen i Prestandaoptimering och frågeoptimering i PostgreSQL på CoddyKit är upplagd för allt från nybörjare till avancerade elever, så att du kan börja här eller från början och gå fram i din egen takt. Detta är lektion 4 av 4.
Hur lång tid tar lektionen ”Diagnostisera varför parallellism inaktiverades”?
De flesta CoddyKit-lektioner tar cirka 5–10 minuter. Varje lektion är kort och interaktiv, så att du gör stadiga framsteg och kan fortsätta precis där du slutade – på webben eller i appen.
Kan jag skriva och köra kod i den här Prestandaoptimering och frågeoptimering i PostgreSQL-lektionen?
Ja. Varje Prestandaoptimering och frågeoptimering i PostgreSQL-lektion innehåller en inbyggd kodredigerare, så att du kan skriva och köra riktig kod direkt i webbläsaren och få omedelbar AI-feedback – utan lokal installation.
Alla lektioner i den här kursen
- När planeraren väljer parallella planer
- Finjustera arbetarantal och Gather-kostnader
- Parallell aggregering och hash-joiner
- Diagnostisera varför parallellism inaktiverades