我想不通,为什么这个查询将与变量对没有他们这么慢。 我读了一些在那里,我需要启用“动态参数”,但我找不到在哪里做到这一点。
DECLARE
@BeginDate AS DATETIME
,@EndDate AS DATETIME
SELECT
@BeginDate = '2010-05-20'
,@EndDate = '2010-05-25'
-- Fix date range to include time values
SET @BeginDate = CONVERT(VARCHAR(10), ISNULL(@BeginDate, '01/01/1990'), 101) + ' 00:00'
SET @EndDate = CONVERT(VARCHAR(10), ISNULL(@EndDate, '12/31/2099'), 101) + ' 23:59'
SELECT
*
FROM
claim c
WHERE
(c.Received_Date BETWEEN @BeginDate AND @EndDate) --this is much slower
--(c.Received_Date BETWEEN '2010-05-20' AND '2010-05-25') --this is much faster
什么数据类型是“c.Received_Date”?
如果不是日期时间则因为@ BEGINDATE / @结束日期日期时间是该列将被转换为日期时间。 这就是所谓的数据类型的优先级 。 这包括如果该列是SMALLDATETIME(按链接),因为日期时间几乎最高的优先级
与常量,优化器将使用列数据类型
转换装置没有索引寻道可以在计划,这是原因被使用。
编辑,看到查询计划后
对于文字,SQL Server将摸索出了一个寻求其次书签查找是最好的,因为值是文字。
一般情况下,(为什么我们使用了覆盖索引和偶然的原因之一)超过一把行书签查找是昂贵的。
对于使用变量的查询时,它采取了一般的情况下,因为如果值的变化可以重复使用计划。 一般情况下是可以避免的书签查找,在这种情况下,你有一个PK(聚集索引)扫描
详细了解为何书签查找通常是在一个糟糕的事情 简单的对话
在这种情况下,你可以尝试一个索引提示来强制,但如果范围太广这将是很慢。 或者你可以删除SELECT *
(不好的做法,反正),并通过替换SELECT col1, col2 etc
,并使用覆盖索引
SET STATISTICS IO ON
SET STATISTICS TIME ON
扫描次数和逻辑读取?
你已经提到,在不同的服务器上相同的数据相同的查询跑得快。
是硬件相同,或至少相当类似?
- 处理器 - 同样数量?
- 任何处理器使用超线程技术?
- 是磁盘相同的物理布局(磁盘速度,数据独立的轴上,日志,tempdb的?)
这种行为通常可以通过过时的统计数据中可以看出。
use dbfoo;
go
exec sp_updatestats
go
最后,比较每只箱子SQL设置:
exec sp_configure 'show advanced options', '1'
go
RECONFIGURE
exec sp_configure;
go