Het deel dat ik altijd verwarrend vond, zijn de opstartkosten versus de totale kosten. Ik Google dit elke keer als ik het vergeet, wat me hier terugbrengt, wat het verschil niet verklaart, daarom schrijf ik dit antwoord. Dit is wat ik heb afgeleid uit de Postgres EXPLAIN
documentatie, uitgelegd zoals ik het begrijp.
Hier is een voorbeeld van een applicatie die een forum beheert:
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)
Hier is de grafische uitleg van PgAdmin:
(Als u PgAdmin gebruikt, kunt u met uw muis naar een onderdeel gaan om de kostendetails te lezen.)
De kosten worden weergegeven als een tupel, b.v. de kosten van de LIMIT
is cost=0.00..3.39
en de kosten van het achtereenvolgens scannen van post
is cost=0.00..15629.12
. Het eerste getal in de tuple zijn de opstartkosten en het tweede getal is de totale kosten . Omdat ik EXPLAIN
heb gebruikt en niet EXPLAIN ANALYZE
, deze kosten zijn schattingen, geen werkelijke maatregelen.
- Opstartkosten is een lastig begrip. Het vertegenwoordigt niet alleen de hoeveelheid tijd voordat dat onderdeel start . Het vertegenwoordigt de hoeveelheid tijd tussen het moment waarop de component wordt uitgevoerd (gegevens inlezen) en wanneer de component de eerste rij uitvoert .
- Totale kosten is de volledige uitvoeringstijd van het onderdeel, vanaf het moment dat het begint met het inlezen van gegevens tot het moment waarop het klaar is met het schrijven van de uitvoer.
Als een complicatie omvatten de kosten van elk "ouder" knooppunt de kosten van zijn onderliggende knooppunten. In de tekstweergave wordt de boom weergegeven door inspringing, b.v. LIMIT
is een bovenliggende node en Seq Scan
is zijn kind. In de PgAdmin-weergave wijzen de pijlen van kind naar ouder - de richting van de gegevensstroom - wat contra-intuïtief kan zijn als u bekend bent met grafentheorie.
De documentatie zegt dat de kosten inclusief alle onderliggende nodes zijn, maar merk op dat de totale kosten van de bovenliggende 3.39
is veel kleiner dan de totale kosten van zijn kind 15629.12
. De totale kosten zijn niet inclusief omdat een onderdeel zoals LIMIT
hoeft niet de volledige invoer te verwerken. Zie de EXPLAIN SELECT * FROM tenk1 WHERE unique1 < 100 AND unique2 > 9000 LIMIT 2;
voorbeeld in Postgres EXPLAIN
documentatie.
In het bovenstaande voorbeeld is de opstarttijd voor beide componenten nul, omdat geen van beide componenten enige verwerking hoeft uit te voeren voordat het rijen begint te schrijven:een sequentiële scan leest de eerste rij van de tabel en verzendt deze. De LIMIT
leest de eerste rij en zendt deze vervolgens uit.
Wanneer zou een component veel verwerking moeten doen voordat het rijen kan gaan uitvoeren? Er zijn veel mogelijke redenen, maar laten we een duidelijk voorbeeld bekijken. Hier is dezelfde zoekopdracht van vroeger, maar nu met een ORDER BY
clausule:
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)
En grafisch:
Nogmaals, de sequentiële scan op post
heeft geen opstartkosten:het begint onmiddellijk met het uitvoeren van rijen. Maar de soort heeft aanzienlijke opstartkosten 23283.24
omdat het de hele tabel moet sorteren voordat het zelfs maar een enkele rij kan uitvoeren . De totale kosten van de soort 23859.27
is slechts iets hoger dan de opstartkosten, wat het feit weerspiegelt dat zodra de hele dataset is gesorteerd, de gesorteerde gegevens zeer snel kunnen worden verzonden.
Merk op dat de opstarttijd van de LIMIT
23283.24
is exact gelijk aan de opstarttijd van de soort. Dit is niet omdat LIMIT
zelf heeft een hoge opstarttijd. Het heeft eigenlijk geen opstarttijd op zich, maar EXPLAIN
rolt alle kindkosten voor elke ouder bij elkaar, dus de LIMIT
opstarttijd omvat de som van de opstarttijden van zijn kinderen.
Deze opeenstapeling van kosten kan het moeilijk maken om de uitvoeringskosten van elk afzonderlijk onderdeel te begrijpen. Bijvoorbeeld onze LIMIT
heeft nul opstarttijd, maar dat is op het eerste gezicht niet duidelijk. Om deze reden hebben verschillende andere mensen gelinkt naar explain.depesz.com, een tool gemaakt door Hubert Lubaczewski (ook bekend als depesz) die helpt bij het begrijpen van EXPLAIN
door onder meer de kinderkosten af te trekken van de ouderkosten. Hij noemt enkele andere complexiteiten in een korte blogpost over zijn tool.