我无法弄清楚为什么这个查询在变量和没有变量时会如此慢。我读了一些我需要启用“动态参数”的地方,但我找不到在哪里这样做。
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
答案 0 :(得分:7)
什么数据类型是“c.Received_Date”?
如果不是datetime,那么该列将转换为datetime,因为@ BeginDate / @ EndDate是datetime。这称为data type precedence。这包括列是否为smalldatetime(根据链接),因为datetime几乎具有最高优先级
对于常量,优化器将使用列数据类型
转换意味着没有索引可以在计划中使用,这是原因。
查看查询计划后编辑
对于文字,SQL Server计算出搜索后跟书签查找是最好的,因为值是文字。
通常情况下,书签查找费用很高(顺便说一下,我们使用覆盖索引的原因之一)超过少数几行。
对于使用变量的查询,它采用了一般情况,因为如果值更改,则可以重用该计划。一般情况是避免书签查找,在这种情况下,您有一个PK(聚集索引)扫描
上详细了解为什么书签查找通常是坏事在这种情况下,您可以尝试使用索引提示强制它,但如果范围太宽则会非常慢。或者您可以删除SELECT *
(无论如何都是错误的做法)并替换为SELECT col1, col2 etc
并使用covering index
答案 1 :(得分:1)
SET STATISTICS IO ON
SET STATISTICS TIME ON
扫描次数和逻辑读数?
答案 2 :(得分:0)
您已经提到对不同服务器上相同数据的相同查询运行速度很快。
硬件是相同的,还是至少相当类似?
此行为通常可以通过过时的统计信息来查看。
use dbfoo;
go
exec sp_updatestats
go
最后,比较每个框的SQL设置:
exec sp_configure 'show advanced options', '1'
go
RECONFIGURE
exec sp_configure;
go