开发者

Why does sp_executesql run slower when parameters are passed as arguments

开发者 https://www.devze.com 2023-02-20 01:36 出处:网络
Query 1: (lightning fast) sp_executesql \"select * from tablesView where Id = 1\" vs. Query 2: (too slow)

Query 1: (lightning fast)

sp_executesql "select * from tablesView where Id = 1"

vs.

Query 2: (too slow)

sp_executesql "select * from tablesView where Id = @Id", N"@Id int", @Id=1

tablesView - a view containing multiple joins

LINQ always converts queries to Query2 form and hence the performance is really bad.

Questions: I need reason for query2 slowness, and any resolution if there's one. And a resolution for LINQ.

----Additional comments:

The per开发者_C百科formance hit is definitely because of the 2 columns which are using ranking functions(row_number) but I can't avoid them I need them.


I'm going to go out on a limb here and assume that you have a lot of rows where ID = 1.

If not, please correct me.

One possible reason that SQL Server is processing your query slow is that it looks at the query and goes:

hmm, I wonder what he's going to pass for that parameter.
is it going to be 1? where I have about a gazillion rows?
or perhaps 1742, where I have just 3
I just don't know, I better do a table scan to be sure to produce an execution plan that will cover all my bases

If a column, or a column set, has low selectivity (ie. the number of unique values is far less than the number of rows), SQL Server will sometimes revert to a tablescan or similar, just to get all rows deterministically.

At least that's been my experience. In particular I've seen the same behavior when doing date range selects on tables with time-bound data, doing a WHERE dt <= @dt AND dt >= @dt to get all rows where @dt is inside a period of time in that row, reverts to a table-scan, and then when I place the actual date into the SQL as a literal it runs far faster.

The problem here is the selectivity, SQL Server doesn't know how to best cater for all scenarios when building an execution plan for your statement, so it'll try to guess.

Try adding a query hint to specify a typical value for the parameter, ie.:

sp_executesql "select * from tablesView where Id = @Id option (optimize for (@id = 1742))", N"@Id int", @Id=1


This could be a parameter sniffing problem. Try including the line:

OPTION (RECOMPILE)

at the end of your SQL query.

There is an article here explaining what parameter sniffing is: http://blogs.technet.com/b/mdegre/archive/2012/03/19/what-is-parameter-sniffing.aspx


  1. Avoid using SELECT *
  2. ADO.NET 3.5 there is "parameter quessing" in Linq 1=TINYINT 2345=SMALLINT 76357242=INT .. in ADO.NET 4.0 parameter quessing is replaced with default INT data type 1=INT, 2335=INT ,76357242=INT)
0

精彩评论

暂无评论...
验证码 换一张
取 消