sql >> Databasteknik >  >> RDS >> PostgreSQL

Vad förklarar PostgreSQL exakt för mig?

Den del jag alltid funnit förvirrande är startkostnaden kontra totalkostnaden. Jag Googlar det här varje gång jag glömmer det, vilket för mig tillbaka hit, vilket inte förklarar skillnaden, vilket är anledningen till att jag skriver det här svaret. Detta är vad jag har hämtat från Postgres EXPLAIN dokumentation, förklarad som jag förstår det.

Här är ett exempel från en applikation som hanterar ett forum:

EXPLAIN SELECT * FROM post LIMIT 50;

Limit  (cost=0.00..3.39 rows=50 width=422)
  ->  Seq Scan on post  (cost=0.00..15629.12 rows=230412 width=422)

Här är den grafiska förklaringen från PgAdmin:

(När du använder PgAdmin kan du peka med musen på en komponent för att läsa kostnadsinformationen.)

Kostnaden representeras som en tupel, t.ex. kostnaden för LIMIT är cost=0.00..3.39 och kostnaden för att sekventiellt skanna post är cost=0.00..15629.12 . Den första siffran i tuppeln är startkostnaden och den andra siffran är totalkostnaden . Eftersom jag använde EXPLAIN och inte EXPLAIN ANALYZE , dessa kostnader är uppskattningar, inte faktiska åtgärder.

  • Startkostnad är ett knepigt koncept. Det representerar inte bara hur lång tid det tar innan den komponenten startar . Det representerar hur lång tid det tar mellan när komponenten börjar köras (läser in data) och när komponenten matar ut sin första rad .
  • Total kostnad är hela exekveringstiden för komponenten, från det att den börjar läsa in data tills den slutar skriva sin utdata.

Som en komplikation inkluderar varje "förälder"-nods kostnader kostnaderna för sina undernoder. I textrepresentationen representeras trädet med indrag, t.ex. LIMIT är en överordnad nod och Seq Scan är dess barn. I PgAdmin-representationen pekar pilarna från barn till förälder – riktningen för dataflödet – vilket kan vara kontraintuitivt om du är bekant med grafteori.

Dokumentationen säger att kostnaderna inkluderar alla underordnade noder, men lägg märke till att den totala kostnaden för föräldern 3.39 är mycket mindre än den totala kostnaden för det underordnade 15629.12 . Den totala kostnaden är inte inklusive eftersom en komponent som LIMIT behöver inte bearbeta hela inmatningen. Se EXPLAIN SELECT * FROM tenk1 WHERE unique1 < 100 AND unique2 > 9000 LIMIT 2; exempel i Postgres EXPLAIN dokumentation.

I exemplet ovan är starttiden noll för båda komponenterna, eftersom ingen av komponenterna behöver göra någon bearbetning innan den börjar skriva rader:en sekventiell skanning läser den första raden i tabellen och skickar ut den. LIMIT läser sin första rad och sänder den sedan.

När skulle en komponent behöva göra mycket bearbetning innan den kan börja mata ut några rader? Det finns många möjliga orsaker, men låt oss titta på ett tydligt exempel. Här är samma fråga som tidigare men som nu innehåller en ORDER BY klausul:

EXPLAIN SELECT * FROM post ORDER BY body LIMIT 50;

Limit  (cost=23283.24..23283.37 rows=50 width=422)
  ->  Sort  (cost=23283.24..23859.27 rows=230412 width=422)
        Sort Key: body
        ->  Seq Scan on post  (cost=0.00..15629.12 rows=230412 width=422)

Och grafiskt:

Återigen, den sekventiella skanningen på post har ingen startkostnad:den börjar mata ut rader omedelbart. Men sorten har en betydande startkostnad 23283.24 eftersom den måste sortera hela tabellen innan den kan mata ut en enda rad . Den totala kostnaden för sorteringen 23859.27 är bara något högre än startkostnaden, vilket återspeglar det faktum att när hela datauppsättningen har sorterats kan den sorterade datan skickas ut mycket snabbt.

Observera att starttiden för LIMIT 23283.24 är exakt lika med starttiden av denna typ. Detta beror inte på att LIMIT själv har en hög starttid. Den har faktiskt noll starttid i sig, men EXPLAIN rullar upp alla underordnade kostnader för varje förälder, så LIMIT starttiden inkluderar summan av starttiderna för dess underordnade.

Denna sammanställning av kostnader kan göra det svårt att förstå utförandekostnaden för varje enskild komponent. Till exempel vår LIMIT har noll starttid, men det är inte uppenbart vid första anblicken. Av denna anledning länkade flera andra personer till explain.depesz.com, ett verktyg skapat av Hubert Lubaczewski (a.k.a. depesz) som hjälper till att förstå EXPLAIN genom att — bland annat — dra bort barnkostnader från föräldrakostnader. Han nämner några andra komplexiteter i ett kort blogginlägg om sitt verktyg.



  1. Hur man undkommer enstaka citat i MySQL

  2. Skapa en tillfällig tabell baserad på en annan tabell i SQL Server

  3. Hur man VÄLJER FRÅN lagrad procedur

  4. Installera Oracle SQL Developer 19.1 på Mac OS med JDK 8