Home All Groups Group Topic Archive Search About

Unexpected Execution Plan

Author
7 Jul 2005 3:38 PM
Richard Speiss
I am getting strange results when I join two tables together.  Actually, the
results are fine but the time to get them are what is causing my concern.

My test SQL is the following:

SELECT A.NEWCOUNT, B.ACOST
FROM IPPCDTL A
INNER JOIN IPINVDTL B
ON A.IPINVDTLGUID = B.IPINVDTLGUID
WHERE A.ORIGONHAND <> B.NEWCOUNT

Table IPPCDTL has 150,000 records
Table IPINVDTL has 1,500,000 records

Looking at the execution plan through Query Analyzer it looks like the
following is happening.

- It is scanning the index for IPPCDTL and returning only 140 rows out of
the 150,000 as per my condition (Cost: 5%)
- In parallel is is scanning the index for IPINVDTL and returning 1,500,000
rows (Cost: 71%)
- It then creates a hash/inner join that matches up the two scans and
returns 140 rows (Cost: 24%)

I was surprised by this because I would have thought that SQL Server would
reduce the first table to the 140 records and then join the second table to
those 140, thus only having to read 140 rows out of the IPINVDTL index
instead of all them.  I'm not sure why it is reading every single index
entry in IPINVDTL.

Now of course I could be reading the Execution Plan incorrectly but if I
query IPPCDTL alone it comes back in under a second so I wouldn't think that
joining a second table for 140 records would make the query time increase to
about 40 seconds (Note that it is even slower on my clients computer)

Can anyone offer any insights?

Many thanks

Richard Speiss

These are substantially reduced table definitions just to illustrate the
execution plan:

CREATE TABLE [dbo].[IPPCDTL] (
[IPPCDTLGUID] [uniqueidentifier] NOT NULL ,
[IPINVDTLGUID] [uniqueidentifier] NULL ,
[ORIGONHAND] [numeric](14, 4) NULL ,
[NEWCOUNT] [numeric](14, 4) NULL
) ON [PRIMARY]
GO

ALTER TABLE [dbo].[IPPCDTL] ADD
CONSTRAINT [PK_IPPCDTL] PRIMARY KEY  CLUSTERED
(
  [IPPCDTLGUID]
)  ON [PRIMARY]
GO


CREATE TABLE [dbo].[Ipinvdtl] (
[IPINVDTLGUID] [uniqueidentifier] NOT NULL ,
[ACOST] [numeric](13, 4) NULL
) ON [PRIMARY]
GO

ALTER TABLE [dbo].[Ipinvdtl] ADD
CONSTRAINT [PK_Ipinvdtl] PRIMARY KEY  CLUSTERED
(
  [IPINVDTLGUID]
)  ON [PRIMARY]
GO

Author
7 Jul 2005 7:50 PM
Brian Selzer
You'd think the query optimizer would be able to handle this one.

Try INNER LOOP JOIN, instead of INNER JOIN, that should coerce the optimizer
to use a loop join.

Or you could create an index on IPINVDTLGUID, NEWCOUNT.

Show quote
"Richard Speiss" <rspe***@mtxinc.com> wrote in message
news:epzejowgFHA.2700@TK2MSFTNGP15.phx.gbl...
> I am getting strange results when I join two tables together.  Actually,
the
> results are fine but the time to get them are what is causing my concern.
>
> My test SQL is the following:
>
> SELECT A.NEWCOUNT, B.ACOST
> FROM IPPCDTL A
> INNER JOIN IPINVDTL B
> ON A.IPINVDTLGUID = B.IPINVDTLGUID
> WHERE A.ORIGONHAND <> B.NEWCOUNT
>
> Table IPPCDTL has 150,000 records
> Table IPINVDTL has 1,500,000 records
>
> Looking at the execution plan through Query Analyzer it looks like the
> following is happening.
>
> - It is scanning the index for IPPCDTL and returning only 140 rows out of
> the 150,000 as per my condition (Cost: 5%)
> - In parallel is is scanning the index for IPINVDTL and returning
1,500,000
Show quote
> rows (Cost: 71%)
> - It then creates a hash/inner join that matches up the two scans and
> returns 140 rows (Cost: 24%)
>
> I was surprised by this because I would have thought that SQL Server would
> reduce the first table to the 140 records and then join the second table
to
> those 140, thus only having to read 140 rows out of the IPINVDTL index
> instead of all them.  I'm not sure why it is reading every single index
> entry in IPINVDTL.
>
> Now of course I could be reading the Execution Plan incorrectly but if I
> query IPPCDTL alone it comes back in under a second so I wouldn't think
that
> joining a second table for 140 records would make the query time increase
to
> about 40 seconds (Note that it is even slower on my clients computer)
>
> Can anyone offer any insights?
>
> Many thanks
>
> Richard Speiss
>
> These are substantially reduced table definitions just to illustrate the
> execution plan:
>
> CREATE TABLE [dbo].[IPPCDTL] (
>  [IPPCDTLGUID] [uniqueidentifier] NOT NULL ,
>  [IPINVDTLGUID] [uniqueidentifier] NULL ,
>  [ORIGONHAND] [numeric](14, 4) NULL ,
>  [NEWCOUNT] [numeric](14, 4) NULL
> ) ON [PRIMARY]
> GO
>
> ALTER TABLE [dbo].[IPPCDTL] ADD
>  CONSTRAINT [PK_IPPCDTL] PRIMARY KEY  CLUSTERED
>  (
>   [IPPCDTLGUID]
>  )  ON [PRIMARY]
> GO
>
>
> CREATE TABLE [dbo].[Ipinvdtl] (
>  [IPINVDTLGUID] [uniqueidentifier] NOT NULL ,
>  [ACOST] [numeric](13, 4) NULL
> ) ON [PRIMARY]
> GO
>
> ALTER TABLE [dbo].[Ipinvdtl] ADD
>  CONSTRAINT [PK_Ipinvdtl] PRIMARY KEY  CLUSTERED
>  (
>   [IPINVDTLGUID]
>  )  ON [PRIMARY]
> GO
>
>
>
Author
8 Jul 2005 1:44 PM
Richard Speiss
Hmmm ...  the INNER LOOP JOIN actually took longer but I hadn't looked into
the whole HINTs area. Thanks for the idea.  I will look further down that
road

Richard


Show quote
"Brian Selzer" <br***@selzer-software.com> wrote in message
news:%23vtET0ygFHA.3608@TK2MSFTNGP12.phx.gbl...
> You'd think the query optimizer would be able to handle this one.
>
> Try INNER LOOP JOIN, instead of INNER JOIN, that should coerce the
> optimizer
> to use a loop join.
>
> Or you could create an index on IPINVDTLGUID, NEWCOUNT.
>
> "Richard Speiss" <rspe***@mtxinc.com> wrote in message
> news:epzejowgFHA.2700@TK2MSFTNGP15.phx.gbl...
>> I am getting strange results when I join two tables together.  Actually,
> the
>> results are fine but the time to get them are what is causing my concern.
>>
>> My test SQL is the following:
>>
>> SELECT A.NEWCOUNT, B.ACOST
>> FROM IPPCDTL A
>> INNER JOIN IPINVDTL B
>> ON A.IPINVDTLGUID = B.IPINVDTLGUID
>> WHERE A.ORIGONHAND <> B.NEWCOUNT
>>
>> Table IPPCDTL has 150,000 records
>> Table IPINVDTL has 1,500,000 records
>>
>> Looking at the execution plan through Query Analyzer it looks like the
>> following is happening.
>>
>> - It is scanning the index for IPPCDTL and returning only 140 rows out of
>> the 150,000 as per my condition (Cost: 5%)
>> - In parallel is is scanning the index for IPINVDTL and returning
> 1,500,000
>> rows (Cost: 71%)
>> - It then creates a hash/inner join that matches up the two scans and
>> returns 140 rows (Cost: 24%)
>>
>> I was surprised by this because I would have thought that SQL Server
>> would
>> reduce the first table to the 140 records and then join the second table
> to
>> those 140, thus only having to read 140 rows out of the IPINVDTL index
>> instead of all them.  I'm not sure why it is reading every single index
>> entry in IPINVDTL.
>>
>> Now of course I could be reading the Execution Plan incorrectly but if I
>> query IPPCDTL alone it comes back in under a second so I wouldn't think
> that
>> joining a second table for 140 records would make the query time increase
> to
>> about 40 seconds (Note that it is even slower on my clients computer)
>>
>> Can anyone offer any insights?
>>
>> Many thanks
>>
>> Richard Speiss
>>
>> These are substantially reduced table definitions just to illustrate the
>> execution plan:
>>
>> CREATE TABLE [dbo].[IPPCDTL] (
>>  [IPPCDTLGUID] [uniqueidentifier] NOT NULL ,
>>  [IPINVDTLGUID] [uniqueidentifier] NULL ,
>>  [ORIGONHAND] [numeric](14, 4) NULL ,
>>  [NEWCOUNT] [numeric](14, 4) NULL
>> ) ON [PRIMARY]
>> GO
>>
>> ALTER TABLE [dbo].[IPPCDTL] ADD
>>  CONSTRAINT [PK_IPPCDTL] PRIMARY KEY  CLUSTERED
>>  (
>>   [IPPCDTLGUID]
>>  )  ON [PRIMARY]
>> GO
>>
>>
>> CREATE TABLE [dbo].[Ipinvdtl] (
>>  [IPINVDTLGUID] [uniqueidentifier] NOT NULL ,
>>  [ACOST] [numeric](13, 4) NULL
>> ) ON [PRIMARY]
>> GO
>>
>> ALTER TABLE [dbo].[Ipinvdtl] ADD
>>  CONSTRAINT [PK_Ipinvdtl] PRIMARY KEY  CLUSTERED
>>  (
>>   [IPINVDTLGUID]
>>  )  ON [PRIMARY]
>> GO
>>
>>
>>
>
>
Author
8 Jul 2005 3:10 PM
Brian Selzer
I just noticed that you don't have a foreign key constraint on
IPPCDTL.IPINVDTLGUID.  Add one and index the column.


Show quote
"Richard Speiss" <rspe***@mtxinc.com> wrote in message
news:OXvLdN8gFHA.2156@TK2MSFTNGP14.phx.gbl...
> Hmmm ...  the INNER LOOP JOIN actually took longer but I hadn't looked
into
> the whole HINTs area. Thanks for the idea.  I will look further down that
> road
>
> Richard
>
>
> "Brian Selzer" <br***@selzer-software.com> wrote in message
> news:%23vtET0ygFHA.3608@TK2MSFTNGP12.phx.gbl...
> > You'd think the query optimizer would be able to handle this one.
> >
> > Try INNER LOOP JOIN, instead of INNER JOIN, that should coerce the
> > optimizer
> > to use a loop join.
> >
> > Or you could create an index on IPINVDTLGUID, NEWCOUNT.
> >
> > "Richard Speiss" <rspe***@mtxinc.com> wrote in message
> > news:epzejowgFHA.2700@TK2MSFTNGP15.phx.gbl...
> >> I am getting strange results when I join two tables together.
Actually,
> > the
> >> results are fine but the time to get them are what is causing my
concern.
> >>
> >> My test SQL is the following:
> >>
> >> SELECT A.NEWCOUNT, B.ACOST
> >> FROM IPPCDTL A
> >> INNER JOIN IPINVDTL B
> >> ON A.IPINVDTLGUID = B.IPINVDTLGUID
> >> WHERE A.ORIGONHAND <> B.NEWCOUNT
> >>
> >> Table IPPCDTL has 150,000 records
> >> Table IPINVDTL has 1,500,000 records
> >>
> >> Looking at the execution plan through Query Analyzer it looks like the
> >> following is happening.
> >>
> >> - It is scanning the index for IPPCDTL and returning only 140 rows out
of
> >> the 150,000 as per my condition (Cost: 5%)
> >> - In parallel is is scanning the index for IPINVDTL and returning
> > 1,500,000
> >> rows (Cost: 71%)
> >> - It then creates a hash/inner join that matches up the two scans and
> >> returns 140 rows (Cost: 24%)
> >>
> >> I was surprised by this because I would have thought that SQL Server
> >> would
> >> reduce the first table to the 140 records and then join the second
table
> > to
> >> those 140, thus only having to read 140 rows out of the IPINVDTL index
> >> instead of all them.  I'm not sure why it is reading every single index
> >> entry in IPINVDTL.
> >>
> >> Now of course I could be reading the Execution Plan incorrectly but if
I
> >> query IPPCDTL alone it comes back in under a second so I wouldn't think
> > that
> >> joining a second table for 140 records would make the query time
increase
> > to
> >> about 40 seconds (Note that it is even slower on my clients computer)
> >>
> >> Can anyone offer any insights?
> >>
> >> Many thanks
> >>
> >> Richard Speiss
> >>
> >> These are substantially reduced table definitions just to illustrate
the
> >> execution plan:
> >>
> >> CREATE TABLE [dbo].[IPPCDTL] (
> >>  [IPPCDTLGUID] [uniqueidentifier] NOT NULL ,
> >>  [IPINVDTLGUID] [uniqueidentifier] NULL ,
> >>  [ORIGONHAND] [numeric](14, 4) NULL ,
> >>  [NEWCOUNT] [numeric](14, 4) NULL
> >> ) ON [PRIMARY]
> >> GO
> >>
> >> ALTER TABLE [dbo].[IPPCDTL] ADD
> >>  CONSTRAINT [PK_IPPCDTL] PRIMARY KEY  CLUSTERED
> >>  (
> >>   [IPPCDTLGUID]
> >>  )  ON [PRIMARY]
> >> GO
> >>
> >>
> >> CREATE TABLE [dbo].[Ipinvdtl] (
> >>  [IPINVDTLGUID] [uniqueidentifier] NOT NULL ,
> >>  [ACOST] [numeric](13, 4) NULL
> >> ) ON [PRIMARY]
> >> GO
> >>
> >> ALTER TABLE [dbo].[Ipinvdtl] ADD
> >>  CONSTRAINT [PK_Ipinvdtl] PRIMARY KEY  CLUSTERED
> >>  (
> >>   [IPINVDTLGUID]
> >>  )  ON [PRIMARY]
> >> GO
> >>
> >>
> >>
> >
> >
>
>

AddThis Social Bookmark Button