I'm trying to identify some performance bottlenecks in my Postgres queries and ran an EXPLAIN ANALYZE on a query to get some insights. The output of the query analysis is below:
Nested Loop (cost=162.35..5361.39 rows=4385 width=33) (actual time=5.663..315.153 rows=2 loops=1)
-> Seq Scan on "User" p=u (cost=0.00..1.02 rows=1 width=8) (actual time=0.009..0.011 rows=1 loops=1)
Filter: ("ID" = 1)
Rows Removed by Filter: 1
-> Nested Loop (cost=162.35..5316.51 rows=4385 width=33) (actual time=5.646..315.130 rows=2 loops=1)
-> Nested Loop (cost=161.93..1854.59 rows=6574 width=33) (actual time=5.567..106.350 rows=44342 loops=1)
-> Seq Scan on "Op" o (cost=0.00..1.34 rows=1 width=8) (actual time=0.007..0.011 rows=1 loops=1)
Filter: ("Name" = 'write'::text)
Rows Removed by Filter: 26
-> Bitmap Heap Scan on "Account" a (cost=161.93..1768.73 rows=8453 width=33) (actual time=5.551..45.435 rows=44342 loops=1)
Recheck Cond: ("OId" = o."ID")
Filter: ("UId" = 1)
Heap Blocks: exact=1480
-> Bitmap Index Scan on "IX_Account_op_ID" (cost=0.00..159.82 rows=8453 width=0) (actual time=5.138..5.139 rows=44342 loops=1)
Index Cond: ("OId" = o."ID")
-> Index Scan using "PK_Resource_ID" on "Resources" r (cost=0.42..0.53 rows=1 width=8) (actual time=0.003..0.003 rows=0 loops=44342)
Index Cond: ("ID" = a."ResourceId")
Filter: ("Role" = ANY ('{r1,r2,r3,r4,r5}'::text[]))
Rows Removed by Filter: 1
Planning Time: 0.777 ms
Execution Time: 315.220 ms
I haven't done much query analysis with pg explain before so I'm still trying to wrap my head around everything it's telling me here. One thing I am seeing that is causing me some confusion is I can see the outer execution:
Nested Loop (cost=162.35..5361.39 rows=4385 width=33) (actual time=5.663..315.153 rows=2 loops=1)
says the actual time was 5.663...315 - ok, that makes sense since the total execution time was 315. Then, a little below that:
Nested Loop (cost=162.35..5316.51 rows=4385 width=33) (actual time=5.646..315.130 rows=2 loops=1)
Ok! This is telling me the bulk of the total execution time is going to be in this section. Under this I see:
-> Nested Loop (cost=161.93..1854.59 rows=6574 width=33) (actual time=5.567..106.350 rows=44342 loops=1)
-> Seq Scan on "Op" o (cost=0.00..1.34 rows=1 width=8) (actual time=0.007..0.011 rows=1 loops=1)
Filter: ("Name" = 'write'::text)
Rows Removed by Filter: 26
-> Bitmap Heap Scan on "Account" a (cost=161.93..1768.73 rows=8453 width=33) (actual time=5.551..45.435 rows=44342 loops=1)
Recheck Cond: ("OId" = o."ID")
Filter: ("UId" = 1)
Heap Blocks: exact=1480
Huh - so this is saying there was is a nested loop that took 106.35 ms , which looped once, and the contents of that loop were a sq scan that took .011ms and a bitmap heap scan that took 45.435ms.
All the loops have 1 loop but in both cases it looks to me like the total execution of these loops was higher than the sum of the loops contents. In the case of the inner loop it took 106ms to execute but if I add up the contents of that loop it looks like it should have only taken 45.446ms (.011ms + 45.435ms). In the case of the outer loop it took 315.13ms but again if I add up the contents it looks like it should have been 106.353ms (106.35ms + .003ms).
I'm looking at this and assuming that loops=1 means it only executed what was inside that loop once.. although the total times suggest that there was more than one execution. I'm not sure where I'm misinterpreting this. Could anyone shed some light on this for me? Any advice here would be appreciated, thanks much!