【问题标题】:Why is exec sp_executesql much slower than inline sql?为什么 exec sp_executesql 比 inline sql 慢得多?
【发布时间】:2015-06-01 04:23:57
【问题描述】:

我在 Management Studio 中测试过这个查询,执行速度非常快(不到一秒)

declare @p_Message_0 varchar(3) = 'whh'
declare @p_CreatedTime_0 datetime = '2015-06-01'

SELECT count(1) FROM (SELECT * FROM [Logs](nolock) WHERE CONTAINS([Message], @p_Message_0) AND [CreatedTime]<@p_CreatedTime_0) t
SELECT t2.* FROM (SELECT t.*,ROW_NUMBER() OVER (ORDER BY Id DESC) as rownum FROM (SELECT * FROM [Logs](nolock) t WHERE CONTAINS([Message], @p_Message_0) AND [CreatedTime]<@p_CreatedTime_0) t) t2 WHERE rownum>0 AND rownum<=20

执行计划如下:

然后我把它移到 C# ado.net 中,它就这样运行

exec sp_executesql N'SELECT count(1) FROM (SELECT * FROM [Logs](nolock) WHERE CONTAINS([Message], @p_Message_0) AND [CreatedTime]<@p_CreatedTime_0) t
SELECT t2.* FROM (SELECT t.*,ROW_NUMBER() OVER (ORDER BY Id desc) as rownum FROM (SELECT * FROM [Logs](nolock) t WHERE CONTAINS([Message], @p_Message_0) AND [CreatedTime]<@p_CreatedTime_0) t) t2 WHERE rownum>0 AND rownum<=20',N'@p_Message_0 varchar(3),@p_CreatedTime_0 datetime',@p_Message_0='whh',@p_CreatedTime_0='2015-06-01'

这个运行速度真的很慢(大约 30 秒)。执行计划如:

我不知道这两个计划有何不同。 Sql server 是 2008 R2 的 SP2,我试过参数提示和 OPTION (RECOMPILE),都不适合我。

【问题讨论】:

    标签: c# sql-server ado.net full-text-search sp-executesql


    【解决方案1】:

    尝试更新统计信息。第一个使用带有今天日期的变量。变量不会被嗅探,所以你会得到一个猜测的分布。第二个使用参数。这可以被嗅探。

    如果今天没有更新统计信息,SQL Server 会认为该日期不存在任何行,因此会在此基础上给出计划。比如一个嵌套循环计划,估计执行一次 TVF,但实际上执行了很多次。

    又名the ascending date problem

    【讨论】:

    • 将datetime列索引改成CLUSTERED INDEX后,速度很快,非常感谢!
    • 顺便说一句,更新 statisitcs 并不快,我不知道为什么。
    • 如何为 LINQ to sql 查询添加 OPTIMIZE FOR UNKNOWN
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-10-31
    • 1970-01-01
    • 2017-12-26
    • 2011-01-25
    • 2012-12-20
    • 1970-01-01
    • 2023-03-25
    相关资源
    最近更新 更多