我看了亚伦的文章。这是一本非常好的读物。
我想知道自那篇文章以来是否有一些新功能没有经过测试。
如果您使用的是 2012,为什么不使用格式功能?从逻辑上讲,您希望日期变量为 01 天。查询计划仍会进行聚集索引扫描。
让我们看看这个解决方案如何使用 Aaron 的测试数据库进行叠加。
-- Use the sample
use [DateTesting]
go
-- Johns - log by 6 months
CREATE PROCEDURE dbo.Johns_LogBy6Months
@date SMALLDATETIME
AS
BEGIN
SET NOCOUNT ON;
DECLARE @cmp_date SMALLDATETIME = format(@date, 'yyyyMM01');
DECLARE @c INT;
SELECT @c = COUNT(*)
FROM dbo.SomeLogTable
WHERE DateColumn >= dateadd(m, -7, @cmp_date)
AND DateColumn < @cmp_date
END
GO
-- Aarons - log by 6 months
CREATE PROCEDURE dbo.Aarons_LogBy6Months
@date SMALLDATETIME
AS
BEGIN
SET NOCOUNT ON;
DECLARE @c INT;
DECLARE @cmp_date SMALLDATETIME = DATEADD(MONTH, DATEDIFF(MONTH, '19000101', @date), '19000101');
SELECT @c = COUNT(*)
FROM dbo.SomeLogTable
WHERE
DateColumn >= dateadd(m, -7, @cmp_date)
AND DateColumn < @cmp_date
END
GO
让我们对函数进行 1000 次调用。
-- Sample calls x 1000
PRINT CONVERT(char(23), GETDATE(), 121);
GO
EXEC dbo.Johns_LogCountByDay @date = '20091005';
GO 1000
PRINT CONVERT(char(23), GETDATE(), 121);
GO
EXEC dbo.Aarons_LogBy6Months @date = '20091005';
GO 1000
PRINT CONVERT(char(23), GETDATE(), 121);
GO
这是执行时间。
2013-10-10 11:58:49.547
Beginning execution loop
Batch execution completed 1000 times.
2013-10-10 11:58:52.837
Beginning execution loop
Batch execution completed 1000 times.
2013-10-10 11:58:55.883
总之,调用新的 format() 函数和隐式转换为小日期时间比使用两个字符串(日期)文字的 dateadd() 和 datediff() 需要更多的时间。
format() 解决方案对我来说似乎更直观或自我记录。时间差为 3.3 秒对 3.0 秒。
我必须让速度测试胜过 Aaron 的解决方案。坚持日期变量的不等式比较。他们更快。
简而言之,我将不得不改掉我的坏习惯。