2012-02-17 53 views
2

以下两个查询中,哪一个更快?该表包含超过100M条记录。所以我只想知道在where子句中使用ISNULL是否与首先为变量赋值并仅在where子句中使用变量相同?日期范围查询方法的性能比较

declare @dt datetime 
select COUNT(*) from pandl 
    where PaymentDate >= ISNULL(@dt, convert(nvarchar(10),getdate(), 121)) 

select @dt = ISNULL(@dt, convert(nvarchar(10),getdate(), 121)) 
select COUNT(*) from pandl 
    where PaymentDate >= @dt 
+7

你是否运行它们以查看哪个更快?您是否使用过SQL Profiler来查看每个查询的执行计划? – Pondlife 2012-02-17 13:54:28

+0

你想使用多少个不同的“现在”值?第二个查询捕获当前的日期/时间,如果需要的话,然后搜索。 – HABO 2012-02-17 14:04:31

+1

@ user92546这是一个很好的观点,但仅仅为了添加一些信息,即使'getdate()'在第一个查询过程中被多次评估(我将不得不运行一些测试来验证),因为转换将它舍入了它直到今天,如果查询在午夜之前开始并且仍然在处理(并且在午夜之后将新值赋给'getdate()'),那才真正重要。我完全同意你的看法,一次分配更好,只是想澄清什么时候它可能非常糟糕,而不是“最好”。 – 2012-02-17 14:18:26

回答

2

第二个会更好。从where子句中调用函数将使查询优化器使用扫描而不是搜索。换句话说,你会得到一个不太理想的执行计划

+0

+1 Hola Brandon! – 2012-02-17 14:02:00

+2

从'where'子句检查的值*上调用函数*肯定会导致扫描。但是我的印象是,如果返回值在调用的整个过程中不会改变,SQL Server就足够了解调用该函数的次数。 – cHao 2012-02-17 14:06:58

+0

@ cHao是的,这是真的,问题中的两个版本都不会导致扫描。我只是给了布兰登第一个+1,因为我同意他的第一句话。 :-) – 2012-02-17 14:09:45

2

我会建议一个稍微不同的方法,避免稍微昂贵的转换为字符串,并使用稍小的数据类型来存储日期(因为你不喜欢“T需要分分钟的间隔,如果你只在乎时间的界限):

DECLARE @dt SMALLDATETIME; 
SET @dt = DATEADD(DAY, DATEDIFF(DAY, '19000101', CURRENT_TIMESTAMP), '19000101'); --* 

SELECT COUNT(*) FROM dbo.pandl 
    WHERE PaymentDate >= @dt; 

如果你想继续使用转换为字符串,使用CHAR(10) - 我不认为风格121将生成需要Unicode支持的任何日期格式。

*是的,你可以做到这一点没有外DATEADD但与新的类型,如DATE

1

FWIW,如果你没有一个指标,它是不会影响计划:在文本模式下

http://data.stackexchange.com/stackoverflow/query/61684/http-stackoverflow-com-questions-9329461-ms-sql-query-performance

运行,检查显示的执行计划。

我想在StackExchange这些日期列之一将有一个索引,但我没有找到一个。

除此之外,我在这方面的其他答案 - 不要不必要地使用nvarchar,不要将日期转换为字符串没有很好的理由,不要使用可以在查询之外更易读的函数在查询内部(如果不需要,请不要在查询中使用函数)。

+0

+1显示实际执行计划! – Justin 2012-02-17 14:20:26