Home All Groups Group Topic Archive Search About
Author
22 Jul 2005 4:26 PM
Steve Drake
All,

I have been tuning some SQL today, and i came across this problem.

I have these statements (these are done to reproduce my problem, the real
SQL is much bigger)

/* test one */
declare @parent varchar(254)
set  @parent =  '28CD626A-69B4-42C8-8576-3BF9294E6D70'
select * from fnumdetail  inner join   casedef ON CASEDEF.CASE_INTREF =
FNUMDETAIL.FND_KEY
where fnd_parent  = @parent

/* test two */
select * from fnumdetail
inner join   casedef ON CASEDEF.CASE_INTREF = FNUMDETAIL.FND_KEY
where fnd_parent  = '28CD626A-69B4-42C8-8576-3BF9294E6D70'

As you can see, they are the same the first one in generating over 200,000
reads, the second one is only doing 4 reads which is what i would expect.
Looking at a query plan, the slow one was doing a table scan, the fast one
is just using the index.

This was fixed by adding (FASTFIRSTROW), very strange, even stranger if this
is part of a union it went back to going slow, this fix for that was to make
this the first statement in the union.

Can anyone tell me why it behaves like this ?

Steve

Author
22 Jul 2005 4:49 PM
David Gugick
Steve Drake wrote:
Show quote
> All,
>
> I have been tuning some SQL today, and i came across this problem.
>
> I have these statements (these are done to reproduce my problem, the
> real SQL is much bigger)
>
> /* test one */
> declare @parent varchar(254)
> set  @parent =  '28CD626A-69B4-42C8-8576-3BF9294E6D70'
> select * from fnumdetail  inner join   casedef ON CASEDEF.CASE_INTREF
> = FNUMDETAIL.FND_KEY
> where fnd_parent  = @parent
>
> /* test two */
> select * from fnumdetail
> inner join   casedef ON CASEDEF.CASE_INTREF = FNUMDETAIL.FND_KEY
> where fnd_parent  = '28CD626A-69B4-42C8-8576-3BF9294E6D70'
>
> As you can see, they are the same the first one in generating over
> 200,000 reads, the second one is only doing 4 reads which is what i
> would expect. Looking at a query plan, the slow one was doing a table
> scan, the fast one is just using the index.
>
> This was fixed by adding (FASTFIRSTROW), very strange, even stranger
> if this is part of a union it went back to going slow, this fix for
> that was to make this the first statement in the union.
>
> Can anyone tell me why it behaves like this ?
>
> Steve

Parameter sniffing. That is, SQL Server can examine parameters sent to
stored procedures in order to optimize SQL statements. However, local
variables sometimes are not optimized. The better test is to create the
stored procedure and pass in the fnd_parent value as a parameter and use
that value unaltered in the SQL statement.

--
David Gugick
Quest Software
www.imceda.com
www.quest.com
Author
23 Jul 2005 1:30 PM
Steve Drake
I  did, this started as a SP with one Param, I then reproduced the problem
without the SP, eg entering SQL into ISQLW.


Steve


Show quote
"David Gugick" <david.gugick-nospam@quest.com> wrote in message
news:emtPR1tjFHA.572@TK2MSFTNGP15.phx.gbl...
> Steve Drake wrote:
>> All,
>>
>> I have been tuning some SQL today, and i came across this problem.
>>
>> I have these statements (these are done to reproduce my problem, the
>> real SQL is much bigger)
>>
>> /* test one */
>> declare @parent varchar(254)
>> set  @parent =  '28CD626A-69B4-42C8-8576-3BF9294E6D70'
>> select * from fnumdetail  inner join   casedef ON CASEDEF.CASE_INTREF
>> = FNUMDETAIL.FND_KEY
>> where fnd_parent  = @parent
>>
>> /* test two */
>> select * from fnumdetail
>> inner join   casedef ON CASEDEF.CASE_INTREF = FNUMDETAIL.FND_KEY
>> where fnd_parent  = '28CD626A-69B4-42C8-8576-3BF9294E6D70'
>>
>> As you can see, they are the same the first one in generating over
>> 200,000 reads, the second one is only doing 4 reads which is what i
>> would expect. Looking at a query plan, the slow one was doing a table
>> scan, the fast one is just using the index.
>>
>> This was fixed by adding (FASTFIRSTROW), very strange, even stranger
>> if this is part of a union it went back to going slow, this fix for
>> that was to make this the first statement in the union.
>>
>> Can anyone tell me why it behaves like this ?
>>
>> Steve
>
> Parameter sniffing. That is, SQL Server can examine parameters sent to
> stored procedures in order to optimize SQL statements. However, local
> variables sometimes are not optimized. The better test is to create the
> stored procedure and pass in the fnd_parent value as a parameter and use
> that value unaltered in the SQL statement.
>
> --
> David Gugick
> Quest Software
> www.imceda.com
> www.quest.com
Author
22 Jul 2005 4:58 PM
Ross Presser
On Fri, 22 Jul 2005 17:26:20 +0100, Steve Drake wrote:

Show quote
> All,
>
> I have been tuning some SQL today, and i came across this problem.
>
> I have these statements (these are done to reproduce my problem, the real
> SQL is much bigger)
>
> /* test one */
> declare @parent varchar(254)
> set  @parent =  '28CD626A-69B4-42C8-8576-3BF9294E6D70'
> select * from fnumdetail  inner join   casedef ON CASEDEF.CASE_INTREF =
> FNUMDETAIL.FND_KEY
> where fnd_parent  = @parent
>
> /* test two */
> select * from fnumdetail
> inner join   casedef ON CASEDEF.CASE_INTREF = FNUMDETAIL.FND_KEY
> where fnd_parent  = '28CD626A-69B4-42C8-8576-3BF9294E6D70'
>
> As you can see, they are the same the first one in generating over 200,000
> reads, the second one is only doing 4 reads which is what i would expect.
> Looking at a query plan, the slow one was doing a table scan, the fast one
> is just using the index.
>
> This was fixed by adding (FASTFIRSTROW), very strange, even stranger if this
> is part of a union it went back to going slow, this fix for that was to make
> this the first statement in the union.
>
> Can anyone tell me why it behaves like this ?
>
> Steve

The query optimizer looks at the query at compile time, not runtime, and
does not have access to the value in @parent. Since that value might be
NULL, it disregards the index on FND_KEY.

In actual fact, I have not seen this behavior with queries as simple as
your example, only ones that use a number of variables in the where clause.
Author
23 Jul 2005 1:27 PM
Steve Drake
but.... if @Parent is NULL, it should still use the INDEX, if it doesn't
than that is a major problem.

its happens from a SP and when you enter the SQL in ISQL.

I think the query optimizer is doing a bad job here.

Steve




Show quote
"Ross Presser" <rpresser@NOSPAMgmail.com.invalid> wrote in message
news:143i76qp8ofq5$.dlg@rosspresser.dyndns.org...
> On Fri, 22 Jul 2005 17:26:20 +0100, Steve Drake wrote:
>
>> All,
>>
>> I have been tuning some SQL today, and i came across this problem.
>>
>> I have these statements (these are done to reproduce my problem, the real
>> SQL is much bigger)
>>
>> /* test one */
>> declare @parent varchar(254)
>> set  @parent =  '28CD626A-69B4-42C8-8576-3BF9294E6D70'
>> select * from fnumdetail  inner join   casedef ON CASEDEF.CASE_INTREF =
>> FNUMDETAIL.FND_KEY
>> where fnd_parent  = @parent
>>
>> /* test two */
>> select * from fnumdetail
>> inner join   casedef ON CASEDEF.CASE_INTREF = FNUMDETAIL.FND_KEY
>> where fnd_parent  = '28CD626A-69B4-42C8-8576-3BF9294E6D70'
>>
>> As you can see, they are the same the first one in generating over
>> 200,000
>> reads, the second one is only doing 4 reads which is what i would expect.
>> Looking at a query plan, the slow one was doing a table scan, the fast
>> one
>> is just using the index.
>>
>> This was fixed by adding (FASTFIRSTROW), very strange, even stranger if
>> this
>> is part of a union it went back to going slow, this fix for that was to
>> make
>> this the first statement in the union.
>>
>> Can anyone tell me why it behaves like this ?
>>
>> Steve
>
> The query optimizer looks at the query at compile time, not runtime, and
> does not have access to the value in @parent. Since that value might be
> NULL, it disregards the index on FND_KEY.
>
> In actual fact, I have not seen this behavior with queries as simple as
> your example, only ones that use a number of variables in the where
> clause.
Author
25 Jul 2005 1:30 PM
Ross Presser
On Sat, 23 Jul 2005 14:27:11 +0100, Steve Drake wrote:

> but.... if @Parent is NULL, it should still use the INDEX, if it doesn't
> than that is a major problem.
>
> its happens from a SP and when you enter the SQL in ISQL.
>
> I think the query optimizer is doing a bad job here.

Nobody is saying this is a *good* feature, but it is one that is fairly
well known.  The optimizer will do better with stored procedure parameters
and literal values, than it can do with local variables.  Not much you can
do about it except redesign your procedure to use fewer variables - or to
use fewer at a time.

AddThis Social Bookmark Button