|
database
newsgroups
|
|||||||||||||||||||||||
|
|||||||||||||||||||||||
Same query much slow in function, any idea?declare @c int,@y int select @c=10005143,@y=2005 insert @hit select id=startmm,hit=count(id) from memlog where (LoginXCentralMemID=@c or MemID=@c) and startyy=@y group by startmm it takes 10 seconds but put it in a function, like below, and run select * from utest() it takes 40 second, any idea? create function utest() returns @hit table(a int,b int) as begin declare @c int,@y int select @c=10005143,@y=2005 insert @hit select id=startmm,hit=count(id) from memlog where (LoginXCentralMemID=@c or MemID=@c) and startyy=@y group by startmm return end thanks! Difficult to say without seeing the execution plan. How many rows? It just
might be that a temporary table is created when the function is executed to store the data before returning it to the client. ML --- http://milambda.blogspot.com/ Seeing the CREATE TABLE statement and CREATE INDEX statements
for memlog would help, as would having an idea of the data distribution, i.e., how many rows the table contains, and how many of those rows satisfy each of the individual conditions of the WHERE clause. I can suggest that an inline UDF is likely to perform better, since it doesn't have to materialize the result set as a separate step from returning the result set: create function utest() returns table as return select startmm as id, count(id) as hit from memlog where (LoginXCentralMemID=1005143 or MemID=1005143) and startyy=2005 group by startmm Steve Kass Drew University davidw wrote: Show quote >if I run this >declare @c int,@y int >select @c=10005143,@y=2005 >insert @hit >select id=startmm,hit=count(id) > from memlog > where (LoginXCentralMemID=@c or MemID=@c) and startyy=@y > group by startmm > >it takes 10 seconds > >but put it in a function, like below, and run >select * from utest() >it takes 40 second, any idea? > >create function utest() returns > @hit table(a int,b int) >as >begin >declare @c int,@y int >select @c=10005143,@y=2005 >insert @hit >select id=startmm,hit=count(id) > from memlog > where (LoginXCentralMemID=@c or MemID=@c) and startyy=@y > group by startmm >return >end > >thanks! > > > > Thanks for reply. thank you ML on the previous reply too.
The table has around 6 million records, it is clustered index is LoginXCentralMemID MemID ID all them are interger, it has some date fields, all are interger too, they are startyy,startmm,startdd,starthh,startww the five date related fields has another non-clustered index. I did a test, if I run > select startdd as id, count(id) as hit it takes 3 seconds, and I put it into a test function, it takes 3 seconds> from memlog > where (LoginXCentralMemID=1005143 or MemID=1005143) > and startyy=2005 and startmm=11 > group by startdd too. But the query I show you before takes 10 seconds when run directly, but 40 seconds in a function. And I just tried the inline solution, it takes 10 seconds, so it works just like run the query directly. But the thing is my function take a parameter, and run different queries inside it, so it can not be a inline function. I am not sure how to get execution plan from a function. Any idea what else I can do to figure out the issue? thanks! David Show quote "Steve Kass" <sk***@drew.edu> wrote in message news:%23NGlBII$FHA.3992@TK2MSFTNGP15.phx.gbl... > Seeing the CREATE TABLE statement and CREATE INDEX statements > for memlog would help, as would having an idea of the data distribution, > i.e., how many rows the table contains, and how many of those rows > satisfy each of the individual conditions of the WHERE clause. > > I can suggest that an inline UDF is likely to perform better, since it > doesn't have to materialize the result set as a separate step from returning > the result set: > > create function utest() > returns table as return > select startmm as id, count(id) as hit > from memlog > where (LoginXCentralMemID=1005143 or MemID=1005143) > and startyy=2005 > group by startmm > > Steve Kass > Drew University > > davidw wrote: > > >if I run this > >declare @c int,@y int > >select @c=10005143,@y=2005 > >insert @hit > >select id=startmm,hit=count(id) > > from memlog > > where (LoginXCentralMemID=@c or MemID=@c) and startyy=@y > > group by startmm > > > >it takes 10 seconds > > > >but put it in a function, like below, and run > >select * from utest() > >it takes 40 second, any idea? > > > >create function utest() returns > > @hit table(a int,b int) > >as > >begin > >declare @c int,@y int > >select @c=10005143,@y=2005 > >insert @hit > >select id=startmm,hit=count(id) > > from memlog > > where (LoginXCentralMemID=@c or MemID=@c) and startyy=@y > > group by startmm > >return > >end > > > >thanks! > > > > > > > > When you pass parameters in the where clause of the function or SP some
times the query engine can not use index properly.If you create a complete sql string in function using parameter and execute it as a dynamic sql it will run as u expect. Like @Execstr = ' select id=startmm,hit=count(id) from memlog where (LoginXCentralMemID= ' + @c + 'or MemID= ' + @c + ') and startyy= ' + @y +' group by startmm ' Exec (@execstr). Regards Amish I don't think you can run that in a function.
Show quote "amish" <shahami***@gmail.com> wrote in message news:1134116896.747683.221140@g49g2000cwa.googlegroups.com... > When you pass parameters in the where clause of the function or SP some > times the query engine can not use index properly.If you create a > complete sql string in function using parameter and execute it as a > dynamic sql it will run as u expect. > > Like @Execstr = ' select id=startmm,hit=count(id) from memlog where > (LoginXCentralMemID= ' + @c + 'or MemID= ' + @c + ') and startyy= ' + > @y +' group by startmm ' > Exec (@execstr). > > > Regards > Amish > |
|||||||||||||||||||||||