奇怪的SQL性能:参数比函数调用慢

时间:2011-01-18 17:12:12

标签: .net sql linq sql-server-2005

我有一个项目倾倒在我的腿上,而且我远远超出了我的元素。有一个表,大约有10,000,000行正在被查询。特别是有一个查询运行时间太长,并且超时。 Linq生成的查询是

-- Region Parameters
DECLARE @p0 Int = 335
DECLARE @p1 DateTime = DATEADD(day,-7,GETDATE())
-- EndRegion
SELECT *
FROM [Events] AS [t0], 
    [Devices] AS [t1], 
    [EventTypes] AS [t2], 
    [DeviceTypes] AS [t3]
WHERE ([t1].[DeviceID] = [t0].[DeviceID]) 
    AND ([t2].[EventTypeID] = [t0].[EventTypeID]) 
    AND ([t3].[DeviceTypeID] = [t1].[DeviceTypeID]) 
    AND ([t1].[RoomID] = @p0) 
    AND ([t0].[EventTime] >= @p1)

如果我将最后一行更改为[t0].[EventTime] >= DATEADD(day,-7,GETDATE())而不是使用变量@p1,则查询从运行45秒到运行需要3秒。

我的两个问题是1)为什么这个简单的改变会如此大幅提升性能2)是否有办法迫使Linq不使用变量并内联datetime对象?

Linq代码是C#.NET 3.5,服务器是MSSQL 2005

编辑:为简洁起见,我添加了SELECT *,实际查询不会这样做。

3 个答案:

答案 0 :(得分:3)

  • DATEADD(day,-7,GETDATE())可以优化,因为它是常量
  • @ p1是改进计划重用的参数化

看到文字与参数的差异很常见

另一个选项是[t0]。[EventTime]是smalldatetime,你有数据类型优先级强制转换到datetime以匹配@ p1。通过直接使用DATEADD,优化器会将DATEADD表达式更改为smalldatetime

答案 1 :(得分:2)

  

如果我改变最后一行   [t0]。[EventTime]> =   DATEADD(day,-7,GETDATE())而不是   使用变量@ p1,查询进行   从45秒开始跑到   花3秒钟跑。

我对这种说法很怀疑。你确定在交换后冲洗了缓冲区吗?您是否尝试过交换,使用@ p1 param时仍然表现不佳?

关于性能故障排除的一般说明。

  1. 运行两个语句“set statistics io on”和“set statistics time on”
  2. 按住Ctrl-M或使用工具栏显示实际执行计划
  3. 始终使用“dbcc freeproccache”和“dbcc dropcleanbuffers”刷新缓冲区并在运行之间清除计划缓存
  4. 将多个版本对齐并一起运行以查看执行计划中的相对COST
  5. 如果在寻求建议时需要,请转储计划的文本版本“set showplan_text on”并以to-Text模式运行查询
  6. 执行计划为您提供了发展方向的总体方向,但并不总是准确的。将其与IO和CPU统计信息进行平衡。

答案 2 :(得分:2)

10.0.1600是SQL Server 2008 RTM。尝试升级到SP2(无论如何这都是个好主意!)。

通常当我遇到奇怪的优化问题时,我发现SQL Server已经过时,而较新的SP解决了这些问题。不总是,但经常。