SlideShare a Scribd company logo
A deeper dive
into EXPLAIN
Michael Christofides
Hi, I’m Michael
Half of the team behind pgMustard
Spent a lot of time looking into EXPLAIN
Background: product management, database tools
pgmustard.com/docs/explain
michael@pgmustard.com
michristofides
Picking up from other EXPLAIN talks
Not the basics*
1) Some of the less intuitive arithmetic
2) Some less well covered issues
* postgresql.org/docs/current/performance-tips
thoughtbot: reading EXPLAIN ANALYZE
YouTube: Josh Berkus Explaining EXPLAIN
Picking up from other EXPLAIN talks
Not the basics*
1) Arithmetic: why is this query slow?
2) Issues: what can we do about it?
* postgresql.org/docs/current/performance-tips
thoughtbot: reading EXPLAIN ANALYZE
YouTube: Josh Berkus Explaining EXPLAIN
Arithmetic: loops
Many of the stats are a per-loop average
This includes costs, rows, timings
Watch out for rounding, especially to 0 rows
Disclaimer: heavily doctored
plans ahead, inaccuracies likely.
Nested Loop
(cost=0.84..209.82 rows=16 width=11)
(actual time=0.076..0.368 rows=86 loops=1)
-> Index Only Scan using a on b
(cost=0.42..4.58 rows=9 width=4)
(actual time=0.013..0.019 rows=9 loops=1)
-> Index Scan using x on y
(cost=0.42..22.73 rows=7 width=15)
(actual time=0.012..0.030 rows=10 loops=9)
Nested Loop: 86 rows
Index Scan: 9 * 10 = 90 rows
(Rounding not too bad here)
Arithmetic: threads
Costs, rows, and timings are also per-thread
Shown as loops
Threads = workers + 1
Tip: use VERBOSE
<- the leader
Parallel Seq Scan on table
(cost=0.00..6772.21 rows=79521 width=22)
(actual time=0.090..71.866 rows=63617 loops=3)
Output: column1, column2, column3
Worker 0: actual time=0.111..66.325 rows=56225 loops=1
Worker 1: actual time=0.138..66.027 rows=58792 loops=1
Seq Scan: 63617 * 3 = 190851 rows
Leader: 190851 - 58792 - 56225
= 75834 rows
Arithmetic: buffers
Buffer stats are a total, not per-loop
They are inclusive of children
Nested Loop (... loops=1)
Buffers: shared hit=105
-> Index Only Scan using a on b (... loops=1)
Buffers: shared hit=4
-> Index Scan using x on y (... loops=9)
Buffers: shared hit=101
Nested Loop buffers:
105 - (101 + 4) = 0 blocks
Arithmetic: timings
Per-loop, per-thread
Inclusive of children
Calculating per-node (exclusive) times can get
tricky, even for tools
Nested Loop
(cost=0.84..209.82 rows=16 width=11)
(actual time=0.076..0.368 rows=86 loops=1)
-> Index Only Scan using a on b
(cost=0.42..4.58 rows=9 width=4)
(actual time=0.013..0.019 rows=9 loops=1)
-> Index Scan using x on y
(cost=0.42..22.73 rows=7 width=15)
(actual time=0.012..0.030 rows=10 loops=9)
Index Scan: 0.030 * 9 = 0.27 ms
Nested Loop: 0.368 - 0.27 - 0.019
= 0.079 ms
WITH init AS (
SELECT * FROM pg_sleep_for('100ms')
UNION ALL
SELECT * FROM pg_sleep_for('200ms')
)
(SELECT * FROM init LIMIT 1)
UNION ALL
(SELECT * FROM init);
Credit @felixge
Append (actual time=100.359..
300.688 … )
CTE init
-> Append (actual time=100.334..
300.652 … )
-> Function Scan (actual time=100.333..
100.335 … )
-> Function Scan (actual time=200.310..
200.312 … )
-> Limit (actual time=100.358..
100.359 … )
-> CTE Scan a (actual time=100.355..100.356 … )
-> CTE Scan b (actual time=0.001..
200.322 … )
Execution Time: 300.789 ms
Further reading:
flame-explain.com/docs/general/quirk-correction
Some double-counting in this case.
Arithmetic: tools can help
eg explain.depesz.com
explain.dalibo.com
flame-explain.com
pgmustard.com
<- fellow calculations nerd
<- 👋
Issues: let’s skip the basics
Seq Scans with large filters
Bad row estimates
Sorts and Hashes on disk
Issues: inefficient index scans
Looks out for lots of rows being filtered
Filters are per-loop
So again, watch out for rounding
-> Index Scan using x on y
(cost=0.42..302502.05 rows=1708602 width=125)
(actual time=172810.219..173876.540 rows=1000 loops=1)
Index Cond: (id = another_id)
Filter: (status = 1)
Rows Removed by Filter: 3125626
Index efficiency: 1000/(1000+3125626) = 0.03%
Watch out for high loops
Issues: lossy bitmap scans
When bitmap would otherwise exceed work_mem
Point to a block rather than a row (Tuple Id)
Lossy blocks are a total (ie not per-loop)
-> Bitmap Heap Scan on table
(cost=49153.29..4069724.27 rows=3105598 width=1106)
(actual time=591.928..56472.895 rows=3853272 loops=1)
Recheck Cond: (something > something_else)
Rows Removed by Index Recheck: 5905323
Heap Blocks: exact=14280 lossy=1951048
Lossy blocks: 1951048/(1951048+14280) = 99%
Extra rows read: 5.9 million
Issues: lots of data read
Requires BUFFERS
Lots of data being read for the amount returned
Can be a sign of bloat
Default block size: 8kB
-> Index Scan using x on y
(cost=0.57..2.57 rows=1 width=8)
(actual time=0.064..0.064 rows=1 loops=256753)
Index Cond: (id = another_id)
Filter: (status = 1)
Buffers: shared hit=1146405 read=110636
Caveats: width estimated, rows rounded
Data read: (1146405 + 110636) * 8kB = 10GB
Data returned: 1 * 256753 * 8 bytes = 2MB
Issues: planning time
At the end of the query plan
Can be planning related: eg joins, partitions
But other things too: eg extensions, locks
Warning: not included in auto_explain
(...)
Planning Time: 27.844 ms
Execution Time: 11.162 ms
Planning proportion:
27.844/(27.844 + 11.162) = 71%
Issues: Just In Time compilation
At the end of the query plan
Included in execution time
On by default in PostgreSQL 12 and 13
Start-up time can be a tell-tale
Planning Time: 9.138 ms
JIT:
Functions: 277
Options: Inlining true, Optimization true, Expressions true,
Deforming true
Timing: Generation 31.602 ms, Inlining 253.114 ms, Optimization
1498.268 ms, Emission 913.945 ms, Total 2696.929 ms
Execution Time: 5194.851 ms
JIT proportion:
2696.929/(9.138 + 5194.851) = 52%
Very suspicious actual start-up time
from a JIT dominated plan.
-> Seq Scan on table
(cost=0.00..3.57 rows=72 width=8)
(actual time=2262.312..2262.343 rows=54 loops=1)
Buffers: shared hit=3
Issues: triggers
At the end of the query plan
Total time across calls
Check foreign keys indexed
Before triggers vs after triggers
Planning Time: 0.227 ms
Trigger: RI_ConstraintTrigger_a_12345 on table
time=83129.491 calls=2222623
Execution Time: 87645.739 ms
Trigger proportion:
83129.491/(0.227 + 87645.739) = 95%
Summary: check the arithmetic
Watch out for loops and threads
Watch out for CTEs
Tools can help, if in doubt check two
Summary: keep rarer issues in mind
Check the end section first
Also look out for filters, rechecks, lossy
blocks, amount of data
Tools, mailing lists, and communities can help
Thank you! Any questions?
michael@pgmustard.com
michristofides
Further reading:
* flame-explain.com/docs/general/quirk-correction
* pgmustard.com/docs/explain
* wiki.postgresql.org/wiki/Slow_Query_Questions

More Related Content

PDF
Extending Flux to Support Other Databases and Data Stores | Adam Anthony | In...
PPTX
InfluxDB 1.0 - Optimizing InfluxDB by Sam Dillard
PDF
QConSF 2014 talk on Netflix Mantis, a stream processing system
PDF
Optimizing InfluxDB Performance in the Real World by Dean Sheehan, Senior Dir...
PDF
Time Series Data with InfluxDB
PDF
Wayfair Use Case: The four R's of Metrics Delivery
PDF
INFLUXQL & TICKSCRIPT
PDF
Fast Insight from Fast Data: Integrating ClickHouse and Apache Kafka
Extending Flux to Support Other Databases and Data Stores | Adam Anthony | In...
InfluxDB 1.0 - Optimizing InfluxDB by Sam Dillard
QConSF 2014 talk on Netflix Mantis, a stream processing system
Optimizing InfluxDB Performance in the Real World by Dean Sheehan, Senior Dir...
Time Series Data with InfluxDB
Wayfair Use Case: The four R's of Metrics Delivery
INFLUXQL & TICKSCRIPT
Fast Insight from Fast Data: Integrating ClickHouse and Apache Kafka

What's hot (20)

PDF
Creating and Using the Flux SQL Datasource | Katy Farmer | InfluxData
PDF
A Fast Intro to Fast Query with ClickHouse, by Robert Hodges
PDF
Taming GC Pauses for Humongous Java Heaps in Spark Graph Computing-(Eric Kacz...
PDF
Our Story With ClickHouse at seo.do
PDF
Obtaining the Perfect Smoke By Monitoring Your BBQ with InfluxDB and Telegraf
PDF
Accumulo Summit 2015: Performance Models for Apache Accumulo: The Heavy Tail ...
PPTX
Kapacitor - Real Time Data Processing Engine
PDF
On heap cache vs off-heap cache
PDF
Postgres Performance for Humans
PPTX
Supercharge your Analytics with ClickHouse, v.2. By Vadim Tkachenko
PDF
InfluxData Platform Future and Vision
PDF
[241]large scale search with polysemous codes
PDF
codecentric AG: Using Cassandra and Clojure for Data Crunching backends
PDF
Distributed Computing on PostgreSQL | PGConf EU 2017 | Marco Slot
PDF
ClickHouse Introduction by Alexander Zaitsev, Altinity CTO
PDF
Adventures in Observability: How in-house ClickHouse deployment enabled Inst...
PPTX
Hadoop Query Performance Smackdown
PDF
Data correlation using PySpark and HDFS
PDF
R and cpp
PPTX
Accumulo Summit 2015: Ferrari on a Bumpy Road: Shock Absorbers to Smooth Out ...
Creating and Using the Flux SQL Datasource | Katy Farmer | InfluxData
A Fast Intro to Fast Query with ClickHouse, by Robert Hodges
Taming GC Pauses for Humongous Java Heaps in Spark Graph Computing-(Eric Kacz...
Our Story With ClickHouse at seo.do
Obtaining the Perfect Smoke By Monitoring Your BBQ with InfluxDB and Telegraf
Accumulo Summit 2015: Performance Models for Apache Accumulo: The Heavy Tail ...
Kapacitor - Real Time Data Processing Engine
On heap cache vs off-heap cache
Postgres Performance for Humans
Supercharge your Analytics with ClickHouse, v.2. By Vadim Tkachenko
InfluxData Platform Future and Vision
[241]large scale search with polysemous codes
codecentric AG: Using Cassandra and Clojure for Data Crunching backends
Distributed Computing on PostgreSQL | PGConf EU 2017 | Marco Slot
ClickHouse Introduction by Alexander Zaitsev, Altinity CTO
Adventures in Observability: How in-house ClickHouse deployment enabled Inst...
Hadoop Query Performance Smackdown
Data correlation using PySpark and HDFS
R and cpp
Accumulo Summit 2015: Ferrari on a Bumpy Road: Shock Absorbers to Smooth Out ...
Ad

Similar to A Deeper Dive into EXPLAIN (20)

PPTX
Dive into EXPLAIN - PostgreSql
PPTX
Why learn Internals?
PDF
SQL: Query optimization in practice
PDF
Becoming a better developer with EXPLAIN
PDF
Tiling matrix-matrix multiply, code tuning
PPTX
Gpu programming with java
PDF
JDD 2016 - Tomasz Borek - DB for next project? Why, Postgres, of course
PDF
Quick Wins
PDF
Three steps to untangle data traffic jams
PDF
Golang in TiDB (GopherChina 2017)
PDF
Overview of the Hive Stinger Initiative
PDF
Writing Faster Python 3
PPTX
GALE: Geometric active learning for Search-Based Software Engineering
PDF
Java/Scala Lab: Анатолий Кметюк - Scala SubScript: Алгебра для реактивного пр...
PDF
Conf orm - explain
PPTX
AA_Unit 1_part-I.pptx
PPTX
Mathemetics module
PPTX
Performance Tuning and Optimization
PDF
PostgreSQL: Advanced indexing
PDF
Parallel Computing - Lec 4
Dive into EXPLAIN - PostgreSql
Why learn Internals?
SQL: Query optimization in practice
Becoming a better developer with EXPLAIN
Tiling matrix-matrix multiply, code tuning
Gpu programming with java
JDD 2016 - Tomasz Borek - DB for next project? Why, Postgres, of course
Quick Wins
Three steps to untangle data traffic jams
Golang in TiDB (GopherChina 2017)
Overview of the Hive Stinger Initiative
Writing Faster Python 3
GALE: Geometric active learning for Search-Based Software Engineering
Java/Scala Lab: Анатолий Кметюк - Scala SubScript: Алгебра для реактивного пр...
Conf orm - explain
AA_Unit 1_part-I.pptx
Mathemetics module
Performance Tuning and Optimization
PostgreSQL: Advanced indexing
Parallel Computing - Lec 4
Ad

More from EDB (20)

PDF
Cloud Migration Paths: Kubernetes, IaaS, or DBaaS
 
PDF
Die 10 besten PostgreSQL-Replikationsstrategien für Ihr Unternehmen
 
PDF
Migre sus bases de datos Oracle a la nube
 
PDF
EFM Office Hours - APJ - July 29, 2021
 
PDF
Benchmarking Cloud Native PostgreSQL
 
PDF
Las Variaciones de la Replicación de PostgreSQL
 
PDF
NoSQL and Spatial Database Capabilities using PostgreSQL
 
PDF
Is There Anything PgBouncer Can’t Do?
 
PDF
Data Analysis with TensorFlow in PostgreSQL
 
PDF
Practical Partitioning in Production with Postgres
 
PDF
IOT with PostgreSQL
 
PDF
A Journey from Oracle to PostgreSQL
 
PDF
Psql is awesome!
 
PDF
EDB 13 - New Enhancements for Security and Usability - APJ
 
PPTX
Comment sauvegarder correctement vos données
 
PDF
Cloud Native PostgreSQL - Italiano
 
PDF
New enhancements for security and usability in EDB 13
 
PPTX
Best Practices in Security with PostgreSQL
 
PDF
Cloud Native PostgreSQL - APJ
 
PDF
Best Practices in Security with PostgreSQL
 
Cloud Migration Paths: Kubernetes, IaaS, or DBaaS
 
Die 10 besten PostgreSQL-Replikationsstrategien für Ihr Unternehmen
 
Migre sus bases de datos Oracle a la nube
 
EFM Office Hours - APJ - July 29, 2021
 
Benchmarking Cloud Native PostgreSQL
 
Las Variaciones de la Replicación de PostgreSQL
 
NoSQL and Spatial Database Capabilities using PostgreSQL
 
Is There Anything PgBouncer Can’t Do?
 
Data Analysis with TensorFlow in PostgreSQL
 
Practical Partitioning in Production with Postgres
 
IOT with PostgreSQL
 
A Journey from Oracle to PostgreSQL
 
Psql is awesome!
 
EDB 13 - New Enhancements for Security and Usability - APJ
 
Comment sauvegarder correctement vos données
 
Cloud Native PostgreSQL - Italiano
 
New enhancements for security and usability in EDB 13
 
Best Practices in Security with PostgreSQL
 
Cloud Native PostgreSQL - APJ
 
Best Practices in Security with PostgreSQL
 

Recently uploaded (20)

PDF
Architecting across the Boundaries of two Complex Domains - Healthcare & Tech...
PDF
Profit Center Accounting in SAP S/4HANA, S4F28 Col11
PPTX
Spectroscopy.pptx food analysis technology
PDF
Building Integrated photovoltaic BIPV_UPV.pdf
PDF
Build a system with the filesystem maintained by OSTree @ COSCUP 2025
PDF
Mobile App Security Testing_ A Comprehensive Guide.pdf
PPT
Teaching material agriculture food technology
PDF
MIND Revenue Release Quarter 2 2025 Press Release
PDF
How UI/UX Design Impacts User Retention in Mobile Apps.pdf
PDF
Diabetes mellitus diagnosis method based random forest with bat algorithm
PDF
Spectral efficient network and resource selection model in 5G networks
PPTX
KOM of Painting work and Equipment Insulation REV00 update 25-dec.pptx
PPTX
Programs and apps: productivity, graphics, security and other tools
PPTX
MYSQL Presentation for SQL database connectivity
PDF
cuic standard and advanced reporting.pdf
PPTX
Detection-First SIEM: Rule Types, Dashboards, and Threat-Informed Strategy
PDF
Peak of Data & AI Encore- AI for Metadata and Smarter Workflows
PDF
Approach and Philosophy of On baking technology
PDF
The Rise and Fall of 3GPP – Time for a Sabbatical?
PPTX
ACSFv1EN-58255 AWS Academy Cloud Security Foundations.pptx
Architecting across the Boundaries of two Complex Domains - Healthcare & Tech...
Profit Center Accounting in SAP S/4HANA, S4F28 Col11
Spectroscopy.pptx food analysis technology
Building Integrated photovoltaic BIPV_UPV.pdf
Build a system with the filesystem maintained by OSTree @ COSCUP 2025
Mobile App Security Testing_ A Comprehensive Guide.pdf
Teaching material agriculture food technology
MIND Revenue Release Quarter 2 2025 Press Release
How UI/UX Design Impacts User Retention in Mobile Apps.pdf
Diabetes mellitus diagnosis method based random forest with bat algorithm
Spectral efficient network and resource selection model in 5G networks
KOM of Painting work and Equipment Insulation REV00 update 25-dec.pptx
Programs and apps: productivity, graphics, security and other tools
MYSQL Presentation for SQL database connectivity
cuic standard and advanced reporting.pdf
Detection-First SIEM: Rule Types, Dashboards, and Threat-Informed Strategy
Peak of Data & AI Encore- AI for Metadata and Smarter Workflows
Approach and Philosophy of On baking technology
The Rise and Fall of 3GPP – Time for a Sabbatical?
ACSFv1EN-58255 AWS Academy Cloud Security Foundations.pptx

A Deeper Dive into EXPLAIN

  • 1. A deeper dive into EXPLAIN Michael Christofides
  • 2. Hi, I’m Michael Half of the team behind pgMustard Spent a lot of time looking into EXPLAIN Background: product management, database tools pgmustard.com/docs/explain michael@pgmustard.com michristofides
  • 3. Picking up from other EXPLAIN talks Not the basics* 1) Some of the less intuitive arithmetic 2) Some less well covered issues * postgresql.org/docs/current/performance-tips thoughtbot: reading EXPLAIN ANALYZE YouTube: Josh Berkus Explaining EXPLAIN
  • 4. Picking up from other EXPLAIN talks Not the basics* 1) Arithmetic: why is this query slow? 2) Issues: what can we do about it? * postgresql.org/docs/current/performance-tips thoughtbot: reading EXPLAIN ANALYZE YouTube: Josh Berkus Explaining EXPLAIN
  • 5. Arithmetic: loops Many of the stats are a per-loop average This includes costs, rows, timings Watch out for rounding, especially to 0 rows
  • 6. Disclaimer: heavily doctored plans ahead, inaccuracies likely.
  • 7. Nested Loop (cost=0.84..209.82 rows=16 width=11) (actual time=0.076..0.368 rows=86 loops=1) -> Index Only Scan using a on b (cost=0.42..4.58 rows=9 width=4) (actual time=0.013..0.019 rows=9 loops=1) -> Index Scan using x on y (cost=0.42..22.73 rows=7 width=15) (actual time=0.012..0.030 rows=10 loops=9) Nested Loop: 86 rows Index Scan: 9 * 10 = 90 rows (Rounding not too bad here)
  • 8. Arithmetic: threads Costs, rows, and timings are also per-thread Shown as loops Threads = workers + 1 Tip: use VERBOSE <- the leader
  • 9. Parallel Seq Scan on table (cost=0.00..6772.21 rows=79521 width=22) (actual time=0.090..71.866 rows=63617 loops=3) Output: column1, column2, column3 Worker 0: actual time=0.111..66.325 rows=56225 loops=1 Worker 1: actual time=0.138..66.027 rows=58792 loops=1 Seq Scan: 63617 * 3 = 190851 rows Leader: 190851 - 58792 - 56225 = 75834 rows
  • 10. Arithmetic: buffers Buffer stats are a total, not per-loop They are inclusive of children
  • 11. Nested Loop (... loops=1) Buffers: shared hit=105 -> Index Only Scan using a on b (... loops=1) Buffers: shared hit=4 -> Index Scan using x on y (... loops=9) Buffers: shared hit=101 Nested Loop buffers: 105 - (101 + 4) = 0 blocks
  • 12. Arithmetic: timings Per-loop, per-thread Inclusive of children Calculating per-node (exclusive) times can get tricky, even for tools
  • 13. Nested Loop (cost=0.84..209.82 rows=16 width=11) (actual time=0.076..0.368 rows=86 loops=1) -> Index Only Scan using a on b (cost=0.42..4.58 rows=9 width=4) (actual time=0.013..0.019 rows=9 loops=1) -> Index Scan using x on y (cost=0.42..22.73 rows=7 width=15) (actual time=0.012..0.030 rows=10 loops=9) Index Scan: 0.030 * 9 = 0.27 ms Nested Loop: 0.368 - 0.27 - 0.019 = 0.079 ms
  • 14. WITH init AS ( SELECT * FROM pg_sleep_for('100ms') UNION ALL SELECT * FROM pg_sleep_for('200ms') ) (SELECT * FROM init LIMIT 1) UNION ALL (SELECT * FROM init); Credit @felixge
  • 15. Append (actual time=100.359.. 300.688 … ) CTE init -> Append (actual time=100.334.. 300.652 … ) -> Function Scan (actual time=100.333.. 100.335 … ) -> Function Scan (actual time=200.310.. 200.312 … ) -> Limit (actual time=100.358.. 100.359 … ) -> CTE Scan a (actual time=100.355..100.356 … ) -> CTE Scan b (actual time=0.001.. 200.322 … ) Execution Time: 300.789 ms Further reading: flame-explain.com/docs/general/quirk-correction Some double-counting in this case.
  • 16. Arithmetic: tools can help eg explain.depesz.com explain.dalibo.com flame-explain.com pgmustard.com <- fellow calculations nerd <- 👋
  • 17. Issues: let’s skip the basics Seq Scans with large filters Bad row estimates Sorts and Hashes on disk
  • 18. Issues: inefficient index scans Looks out for lots of rows being filtered Filters are per-loop So again, watch out for rounding
  • 19. -> Index Scan using x on y (cost=0.42..302502.05 rows=1708602 width=125) (actual time=172810.219..173876.540 rows=1000 loops=1) Index Cond: (id = another_id) Filter: (status = 1) Rows Removed by Filter: 3125626 Index efficiency: 1000/(1000+3125626) = 0.03% Watch out for high loops
  • 20. Issues: lossy bitmap scans When bitmap would otherwise exceed work_mem Point to a block rather than a row (Tuple Id) Lossy blocks are a total (ie not per-loop)
  • 21. -> Bitmap Heap Scan on table (cost=49153.29..4069724.27 rows=3105598 width=1106) (actual time=591.928..56472.895 rows=3853272 loops=1) Recheck Cond: (something > something_else) Rows Removed by Index Recheck: 5905323 Heap Blocks: exact=14280 lossy=1951048 Lossy blocks: 1951048/(1951048+14280) = 99% Extra rows read: 5.9 million
  • 22. Issues: lots of data read Requires BUFFERS Lots of data being read for the amount returned Can be a sign of bloat Default block size: 8kB
  • 23. -> Index Scan using x on y (cost=0.57..2.57 rows=1 width=8) (actual time=0.064..0.064 rows=1 loops=256753) Index Cond: (id = another_id) Filter: (status = 1) Buffers: shared hit=1146405 read=110636 Caveats: width estimated, rows rounded Data read: (1146405 + 110636) * 8kB = 10GB Data returned: 1 * 256753 * 8 bytes = 2MB
  • 24. Issues: planning time At the end of the query plan Can be planning related: eg joins, partitions But other things too: eg extensions, locks Warning: not included in auto_explain
  • 25. (...) Planning Time: 27.844 ms Execution Time: 11.162 ms Planning proportion: 27.844/(27.844 + 11.162) = 71%
  • 26. Issues: Just In Time compilation At the end of the query plan Included in execution time On by default in PostgreSQL 12 and 13 Start-up time can be a tell-tale
  • 27. Planning Time: 9.138 ms JIT: Functions: 277 Options: Inlining true, Optimization true, Expressions true, Deforming true Timing: Generation 31.602 ms, Inlining 253.114 ms, Optimization 1498.268 ms, Emission 913.945 ms, Total 2696.929 ms Execution Time: 5194.851 ms JIT proportion: 2696.929/(9.138 + 5194.851) = 52%
  • 28. Very suspicious actual start-up time from a JIT dominated plan. -> Seq Scan on table (cost=0.00..3.57 rows=72 width=8) (actual time=2262.312..2262.343 rows=54 loops=1) Buffers: shared hit=3
  • 29. Issues: triggers At the end of the query plan Total time across calls Check foreign keys indexed Before triggers vs after triggers
  • 30. Planning Time: 0.227 ms Trigger: RI_ConstraintTrigger_a_12345 on table time=83129.491 calls=2222623 Execution Time: 87645.739 ms Trigger proportion: 83129.491/(0.227 + 87645.739) = 95%
  • 31. Summary: check the arithmetic Watch out for loops and threads Watch out for CTEs Tools can help, if in doubt check two
  • 32. Summary: keep rarer issues in mind Check the end section first Also look out for filters, rechecks, lossy blocks, amount of data Tools, mailing lists, and communities can help
  • 33. Thank you! Any questions? michael@pgmustard.com michristofides Further reading: * flame-explain.com/docs/general/quirk-correction * pgmustard.com/docs/explain * wiki.postgresql.org/wiki/Slow_Query_Questions