Thread: Index Scan taking long time

Index Scan taking long time

From
Bryce Ewing
Date:
Hi,

I have been trying to fix a performance issue that we have which I have
tracked down to index scans being done on a particular table (or set of
tables):

The following query:
explain analyze select *
FROM inbound.event_20090526 e
LEFT OUTER JOIN inbound.internal_host i ON (e.mta_host_id = i.id)
LEFT OUTER JOIN inbound.internal_host iaa ON (e.aamta_host_id = iaa.id)
LEFT OUTER JOIN inbound.event_status es ON (e.event_status_id = es.id)
LEFT OUTER JOIN inbound.threat t ON (e.threat_id = t.id), inbound.domain
d, inbound.event_type et
WHERE e.domain_id = d.id
AND e.event_type_id = et.id
AND d.name IN (
    'testdomain.com'
);


Does this:

QUERY
PLAN


--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 Nested Loop Left Join  (cost=0.00..10887.03 rows=8 width=2021) (actual
time=50.352..14378.603 rows=3453 loops=1)
   ->  Nested Loop Left Join  (cost=0.00..10882.23 rows=8 width=1985)
(actual time=50.346..14372.820 rows=3453 loops=1)
         ->  Nested Loop Left Join  (cost=0.00..10877.43 rows=8
width=1949) (actual time=50.336..14358.101 rows=3453 loops=1)
               ->  Nested Loop Left Join  (cost=0.00..10872.63 rows=8
width=1801) (actual time=50.321..14344.603 rows=3453 loops=1)
                     ->  Nested Loop  (cost=0.00..10867.83 rows=8
width=1764) (actual time=50.315..14336.979 rows=3453 loops=1)
                           ->  Nested Loop  (cost=0.00..10863.03 rows=8
width=1728) (actual time=50.288..14308.368 rows=3453 loops=1)
                                 ->  Index Scan using domain_name_idx on
domain d  (cost=0.00..6.63 rows=1 width=452) (actual time=0.049..0.080
rows=1 loops=1)
                                       Index Cond: ((name)::text =
'testdomain.com'::text)
                                 ->  Index Scan using
event_20090526_domain_idx on event_20090526 e  (cost=0.00..10694.13
rows=3606 width=1276) (actual time=50.233..14305.211 rows=3453 loops=1)
                                       Index Cond: (e.domain_id = d.id)
                           ->  Index Scan using event_type_pkey on
event_type et  (cost=0.00..0.56 rows=1 width=36) (actual
time=0.006..0.006 rows=1 loops=3453)
                                 Index Cond: (et.id = e.event_type_id)
                     ->  Index Scan using threat_pkey on threat t
(cost=0.00..0.56 rows=1 width=37) (actual time=0.000..0.000 rows=0
loops=3453)
                           Index Cond: (e.threat_id = t.id)
               ->  Index Scan using event_status_pkey on event_status
es  (cost=0.00..0.56 rows=1 width=148) (actual time=0.002..0.002 rows=1
loops=3453)
                     Index Cond: (e.event_status_id = es.id)
         ->  Index Scan using internal_host_pkey on internal_host iaa
(cost=0.00..0.56 rows=1 width=36) (actual time=0.002..0.003 rows=1
loops=3453)
               Index Cond: (e.aamta_host_id = iaa.id)
   ->  Index Scan using internal_host_pkey on internal_host i
(cost=0.00..0.56 rows=1 width=36) (actual time=0.000..0.000 rows=0
loops=3453)
         Index Cond: (e.mta_host_id = i.id)
 Total runtime: 14380.000 ms

If the same query is done straight away again we get:

QUERY
PLAN


---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 Nested Loop Left Join  (cost=0.00..10887.03 rows=8 width=2021) (actual
time=0.165..67.388 rows=3453 loops=1)
   ->  Nested Loop Left Join  (cost=0.00..10882.23 rows=8 width=1985)
(actual time=0.162..61.973 rows=3453 loops=1)
         ->  Nested Loop Left Join  (cost=0.00..10877.43 rows=8
width=1949) (actual time=0.156..49.756 rows=3453 loops=1)
               ->  Nested Loop Left Join  (cost=0.00..10872.63 rows=8
width=1801) (actual time=0.148..37.522 rows=3453 loops=1)
                     ->  Nested Loop  (cost=0.00..10867.83 rows=8
width=1764) (actual time=0.146..31.920 rows=3453 loops=1)
                           ->  Nested Loop  (cost=0.00..10863.03 rows=8
width=1728) (actual time=0.129..10.325 rows=3453 loops=1)
                                 ->  Index Scan using domain_name_idx on
domain d  (cost=0.00..6.63 rows=1 width=452) (actual time=0.099..0.139
rows=1 loops=1)
                                       Index Cond: ((name)::text =
'rhe.com.au'::text)
                                 ->  Index Scan using
event_20090526_domain_idx on event_20090526 e  (cost=0.00..10694.13
rows=3606 width=1276) (actual time=0.027..7.510 rows=3453 loops=1)
                                       Index Cond: (e.domain_id = d.id)
                           ->  Index Scan using event_type_pkey on
event_type et  (cost=0.00..0.56 rows=1 width=36) (actual
time=0.004..0.005 rows=1 loops=3453)
                                 Index Cond: (et.id = e.event_type_id)
                     ->  Index Scan using threat_pkey on threat t
(cost=0.00..0.56 rows=1 width=37) (actual time=0.000..0.000 rows=0
loops=3453)
                           Index Cond: (e.threat_id = t.id)
               ->  Index Scan using event_status_pkey on event_status
es  (cost=0.00..0.56 rows=1 width=148) (actual time=0.002..0.002 rows=1
loops=3453)
                     Index Cond: (e.event_status_id = es.id)
         ->  Index Scan using internal_host_pkey on internal_host iaa
(cost=0.00..0.56 rows=1 width=36) (actual time=0.002..0.002 rows=1
loops=3453)
               Index Cond: (e.aamta_host_id = iaa.id)
   ->  Index Scan using internal_host_pkey on internal_host i
(cost=0.00..0.56 rows=1 width=36) (actual time=0.000..0.000 rows=0
loops=3453)
         Index Cond: (e.mta_host_id = i.id)
 Total runtime: 68.475 ms

Which suggests to me that it takes the remainder of the 14300ms in the
first query to read the event_20090526_domain_idx index in from disk.

The table has 2 million records in it, and the index has a physical size
on disk of 44MB.  The box this is running on is rather powerful having 8
cores, 16GB ram, and stripped disks.

What I am wondering is is there any reason why this would be taking so
long?  Or what can be done to fix this / track down the issue more?

Cheers
Bryce

Re: Index Scan taking long time

From
Scott Marlowe
Date:
On Tue, Jun 16, 2009 at 9:30 PM, Bryce Ewing<bryce@smx.co.nz> wrote:
> Hi,
>
> I have been trying to fix a performance issue that we have which I have
> tracked down to index scans being done on a particular table (or set of
> tables):
>
> The following query:
> explain analyze select *
> FROM inbound.event_20090526 e
> LEFT OUTER JOIN inbound.internal_host i ON (e.mta_host_id = i.id)
> LEFT OUTER JOIN inbound.internal_host iaa ON (e.aamta_host_id = iaa.id)
> LEFT OUTER JOIN inbound.event_status es ON (e.event_status_id = es.id)
> LEFT OUTER JOIN inbound.threat t ON (e.threat_id = t.id), inbound.domain d,
> inbound.event_type et
> WHERE e.domain_id = d.id
> AND e.event_type_id = et.id
> AND d.name IN (
>   'testdomain.com'
> );

Without looking at the explain just yet, it seems to me that you are
constraining the order of joins to insist that the left joins be done
first, then the regular joins second, because of your mix of explicit
and implicit join syntax.  The query planner is constrained to run
explicit joins first, then implicit if I remember correctly.  So,
making it all explicit might help.  Might not.  But it's a thought

Re: Index Scan taking long time

From
Tom Lane
Date:
Scott Marlowe <scott.marlowe@gmail.com> writes:
> Without looking at the explain just yet, it seems to me that you are
> constraining the order of joins to insist that the left joins be done
> first, then the regular joins second, because of your mix of explicit
> and implicit join syntax.  The query planner is constrained to run
> explicit joins first, then implicit if I remember correctly.

That isn't true as of recent releases (8.2 and up, I think).  It is true
that there are semantic constraints that prevent certain combinations
of inner and outer joins from being rearranged ... but if that applies
here, it would also prevent manual rearrangement, unless the OP decides
that this query doesn't express quite what he meant.

            regards, tom lane

Re: Index Scan taking long time

From
Bryce Ewing
Date:
The nested loops (which are due to the joins) don't seem to be part of
the problem at all.  The main time that is taken (actual time that is)
is in this part:
    Index Scan using event_20090526_domain_idx on event_20090526 e
    (cost=0.00..10694.13 rows=3606 width=1276) (actual
time=50.233..14305.211 rows=3453 loops=1)
        Index Cond: (e.domain_id = d.id)

Which is the leaf node in the query plan, the total time for the query
being: Total runtime: 14380.000 ms

And as I said once that query is run once it then does the same query
plan and has this output for the same leaf node above:
    Index Scan using event_20090526_domain_idx on event_20090526 e
    (cost=0.00..10694.13 rows=3606 width=1276) (actual time=0.027..7.510
rows=3453 loops=1)
        Index Cond: (e.domain_id = d.id)

So it seems to me that once the index is in memory everything is fine
with the world, but the loading of the index into memory is horrendous.


Tom Lane wrote:
> Scott Marlowe <scott.marlowe@gmail.com> writes:
>
>> Without looking at the explain just yet, it seems to me that you are
>> constraining the order of joins to insist that the left joins be done
>> first, then the regular joins second, because of your mix of explicit
>> and implicit join syntax.  The query planner is constrained to run
>> explicit joins first, then implicit if I remember correctly.
>>
>
> That isn't true as of recent releases (8.2 and up, I think).  It is true
> that there are semantic constraints that prevent certain combinations
> of inner and outer joins from being rearranged ... but if that applies
> here, it would also prevent manual rearrangement, unless the OP decides
> that this query doesn't express quite what he meant.
>
>             regards, tom lane
>

--

*Bryce Ewing *| Platform Architect
*DDI:* +64 9 950 2195 *Fax:* +64 9 302 0518
*Mobile:* +64 21 432 293 *Freephone:* 0800 SMX SMX (769 769)
Level 11, 290 Queen Street, Auckland, New Zealand | SMX Ltd | smx.co.nz
<http://smx.co.nz>
SMX | Business Email Specialists
The information contained in this email and any attachments is
confidential. If you are not
the intended recipient then you must not use, disseminate, distribute or
copy any information
contained in this email or any attachments. If you have received this
email in error or you
are not the originally intended recipient please contact SMX immediately
and destroy this email.


Re: Index Scan taking long time

From
Tom Lane
Date:
Bryce Ewing <bryce@smx.co.nz> writes:
> So it seems to me that once the index is in memory everything is fine
> with the world, but the loading of the index into memory is horrendous.

So it would seem.  What's the disk hardware on this machine?

It's possible that part of the problem is table bloat, leading to the
indexscan having to fetch many more pages than it would if the table
were more compact.

            regards, tom lane

Re: Index Scan taking long time

From
Bryce Ewing
Date:
Hi Tom,

We have managed to improve significantly on the speed of this query.
The way that we did this was through clustering the table based on the
domain index which significantly reduced the page reads that were
required in order to perform the query.

Also to find this we turned on log_statement_stats to see what it was doing.

This was on a table of roughly 600MB where the domains were randomly
dispersed.

Cheers
Bryce

Tom Lane wrote:
> Bryce Ewing <bryce@smx.co.nz> writes:
>
>> So it seems to me that once the index is in memory everything is fine
>> with the world, but the loading of the index into memory is horrendous.
>>
>
> So it would seem.  What's the disk hardware on this machine?
>
> It's possible that part of the problem is table bloat, leading to the
> indexscan having to fetch many more pages than it would if the table
> were more compact.
>
>             regards, tom lane
>
>