Postgresql explain
Chennai.py meetup
24th Oct 2015
@h6165
Abhishek Yadav
Active in Chennai.py since Sep 2013
Talked before in Nov 2013
Co-organizer: Chennai.rb
ரூபீ ப்ரோக்ராமர
0. Definitions
The definition
EXPLAIN show us the potential query plan along with costs
EXPLAIN helps us verify our speculations on query performance.
It also gives some insight into the algorithms Postgresql uses
EXPLAIN ANALYSE shows the query plan and costs along with executing the query.
BEGIN .. EXPLAIN ANALYSE ... ROLLBACK
Executes the query, explains it and rollsback
The syntax
EXPLAIN <query>; EXPLAIN ANALYSE <query>; BEGIN; EXPLAIN ANALYSE <query>; ROLLBACK;
The anatomy
EXPLAIN SELECT count(*) FROM comments;
QUERY PLAN
---------------------------------------------------------------------
Aggregate (cost=1382.00..1382.01 rows=1 width=0)
-> Seq Scan on comments (cost=0.00..1257.00 rows=50000 width=0)
(2 rows)
No. of rows output
The cost
The algorithm
The anatomy
- The EXPLAIN output is a tree
- It should be read bottom-up (leaf to root)
- Cost of a step is a summation of child steps
- 'rows' are the rows emitted by a step, not the rows scanned
The cost
- Quantification of the effort needed on a arbitrary scale
- The exact number doesn't mean anything. Can be used for comparisons
- Lower the better
- Is proportional to the no. of blocks read, no. of random blocks read. And to CPU operations too by a small measure
1. Explain where
Explain where: Quiz
Which query costs better - one with where filter or the one without?
(there are no indexes)
SELECT * FROM comments;
SELECT * FROM comments WHERE post_id=1;
Explain where: Quiz
EXPLAIN SELECT * FROM comments;
QUERY PLAN
----------------------------------------------------------------
Seq Scan on comments (cost=0.00..1257.00 rows=50000 width=72)
(1 row)
One with the filter is more costly. Read cost is the same, CPU cost is higher
EXPLAIN SELECT * FROM comments WHERE post_id=1;
QUERY PLAN
------------------------------------------------------------
Seq Scan on comments (cost=0.00..1382.00 rows=5 width=72)
Filter: (post_id = 1)
(2 rows)
2. Let there be index
Explain and index
CREATE INDEX ON comments (post_id);
EXPLAIN SELECT * FROM comments WHERE id=12345;
QUERY PLAN
-------------------------------------------------------------------------------
Index Scan using comments_pkey on comments (cost=0.41..8.43 rows=1 width=72)
Index Cond: (id = 12345)
(2 rows)
Adding an index on filter clause may reduce the cost.
Explain and index: Quiz
Will adding index on the gender field improve query cost ?
Is second one better than the first ?
SELECT * FROM users WHERE gender='M';
CREATE INDEX ON users (gender);
SELECT * from users WHERE gender='M';
EXPLAIN SELECT * FROM users WHERE gender='m';
QUERY PLAN
-----------------------------------------------------------
Seq Scan on users (cost=0.00..211.28 rows=4990 width=33)
Filter: ((gender)::text = 'm'::text)
(2 rows)
Low cardinality indexes are ignored!
No
CREATE INDEX ON users (gender);
EXPLAIN SELECT * FROM users WHERE gender='m';
QUERY PLAN
-----------------------------------------------------------
Seq Scan on users (cost=0.00..211.28 rows=4990 width=33)
Filter: ((gender)::text = 'm'::text)
(2 rows)
Explain and index: Quiz
- An index on a column that can yield very few possible values
- Cardinality = no of possible values / total rows
- Database may ignore index and will do a full scan if cardinality is too low
- The limit varies across databases, but is generally 10-20%
- Explain helps us check the usefulness of an index. An index always increases write costs, so this is important
Explain and index: Low cardinality
3. Explain JOIN
Explain JOIN: Quiz
SELECT posts.*, comments.*
FROM posts LEFT JOIN comments
ON posts.id = comments.post_id;
JOIN : Adding index on columns in ON clause.
Will that improve query performance?
CREATE INDEX ON comments (post_id);
CREATE INDEX ON posts (id);
EXPLAIN
SELECT posts.*, comments.*
FROM posts LEFT JOIN comments
ON posts.id = comments.post_id;
QUERY PLAN
------------------------------------------------------------------------
Hash Right Join (cost=394.50..2589.00 rows=50000 width=150)
Hash Cond: (comments.post_id = posts.id)
-> Seq Scan on comments (cost=0.00..1257.00 rows=50000 width=72)
-> Hash (cost=257.00..257.00 rows=11000 width=78)
-> Seq Scan on posts (cost=0.00..257.00 rows=11000 width=78)
(5 rows)
JOIN: Will adding indexes on columns in ON clause improve cost?
No
CREATE INDEX ON posts (id);
CREATE INDEX on comments (post_id);
EXPLAIN
SELECT posts.*, comments.*
FROM posts LEFT JOIN comments
ON posts.id = comments.post_id;
QUERY PLAN
------------------------------------------------------------------------
Hash Right Join (cost=394.50..2589.00 rows=50000 width=150)
Hash Cond: (comments.post_id = posts.id)
-> Seq Scan on comments (cost=0.00..1257.00 rows=50000 width=72)
-> Hash (cost=257.00..257.00 rows=11000 width=78)
-> Seq Scan on posts (cost=0.00..257.00 rows=11000 width=78)
(5 rows)
Explain JOIN: Quiz
JOIN: Will adding indexes on columns in ON clause improve cost?
Explain JOIN: Quiz
Does not use any index in any step.
Performs Seq Scan on all 11000 posts rows and 50000 comments.
The final Join step is also high in cost (initial as well as overall)
QUERY PLAN
------------------------------------------------------------------------
Hash Right Join (cost=394.50..2589.00 rows=50000 width=150)
Hash Cond: (comments.post_id = posts.id)
-> Seq Scan on comments (cost=0.00..1257.00 rows=50000 width=72)
-> Hash (cost=257.00..257.00 rows=11000 width=78)
-> Seq Scan on posts (cost=0.00..257.00 rows=11000 width=78)
(5 rows)
JOIN: Will adding indexes on columns in ON clause improve cost?
Explain JOIN: Quiz
- JOIN algorithms are not capable of using any indexes on the ON columns
- The best way to optimize JOINS is by adding filters on at least one table
EXPLAIN
SELECT posts.*, comments.*
FROM posts LEFT JOIN comments
ON posts.id = comments.post_id
WHERE posts.id < 20;
QUERY PLAN
-----------------------------------------------------------------------------------------
Nested Loop Left Join (cost=4.42..492.32 rows=95 width=150)
-> Index Scan using posts_id_idx on posts (cost=0.29..8.65 rows=21 width=78)
Index Cond: (id < 20)
-> Bitmap Heap Scan on comments (cost=4.14..22.98 rows=5 width=72)
Recheck Cond: (posts.id = post_id)
-> Bitmap Index Scan on comments_post_id_idx (cost=0.00..4.14 rows=5 width=0)
Index Cond: (posts.id = post_id)
4. Explain ORDER BY
SELECT * from comments ORDER BY updated_at LIMIT 10;
Can ORDER BY speed up using an index
CREATE INDEX ON comments (created_at);
SELECT * from comments ORDER BY created_at LIMIT 10;
Will the second be better than first?
Explain Order By: Quiz
Can ORDER BY take advantage of an index
EXPLAIN
SELECT * from comments ORDER BY updated_at LIMIT 10;
QUERY PLAN
----------------------------------------------------------------------------
Limit (cost=2337.48..2337.51 rows=10 width=72)
-> Sort (cost=2337.48..2462.48 rows=50000 width=72)
Sort Key: updated_at
-> Seq Scan on comments (cost=0.00..1257.00 rows=50000 width=72)
(4 rows)
Yes
Explain Order By: Quiz
EXPLAIN
SELECT * from comments ORDER BY created_at LIMIT 10;
QUERY PLAN
--------------------------------------------------------------------------
Limit (cost=0.29..1.16 rows=10 width=72)
-> Index Scan using comments_created_at_idx on comments
(cost=0.29..4332.16 rows=50000 width=72)
(2 rows)
/Explain
@h6165
Abhishek Yadav
Active in Chennai.py since Sep 2013
Talked before in Nov 2013
Co-organizer: Chennai.rb
ரூபீ ப்ரோக்ராமர
Postgresql explain
By Abhishek Yadav
Postgresql explain
- 1,633