Alf*_*f47 10 performance sql-server query query-refactor query-performance
这两个查询在逻辑上是等价的吗?
DECLARE @DateTime DATETIME = GETDATE()
Run Code Online (Sandbox Code Playgroud)
查询 1
SELECT *
FROM MyTable
WHERE Datediff(DAY, LogInsertTime, @DateTime) > 7
Run Code Online (Sandbox Code Playgroud)
查询 2
SELECT *
FROM MyTable
WHERE LogInsertTime < @DateTime - 7
Run Code Online (Sandbox Code Playgroud)
如果它们在逻辑上不是等价的,您能否给我第一个查询的逻辑等价,以便 WHERE 子句可以有效地使用索引(即消除函数包装)?
Aar*_*and 15
您发布的两个查询在逻辑上是否相同无关紧要;你不应该使用它们中的任何一个。我将尝试引导您远离以下几件事:
LogDateTime已编入索引(或可能曾经编入索引)。我不喜欢速记日期数学,我建议反对它。当然,打字速度更快,但尝试使用DATE数据类型,你会得到一个丑陋的错误。最好把它拼出来,例如:
WHERE LogInsertTime < DATEADD(DAY, -7, @DateTime);
Run Code Online (Sandbox Code Playgroud)我会使用以下 sargeable 查询:
SELECT * FROM MyTable WHERE LogInsertTime < DATEADD(DAY, -7, @DateTime)
Run Code Online (Sandbox Code Playgroud)
原因:我认为 @DateTime-7 的结果没有记录。即使它恰好相当于 DATEADD(DAY, -7, @DateTime),它也可能在以后的版本中中断。
它们不是等价的。7 天前但在当前时间之前的记录 - 只会在查询 #2 中返回:
使用该DATEADD函数比较天数时,不考虑时间部分。在比较星期日和星期一时,无论时间如何,该函数都将返回 1。
演示:
DECLARE @MyTable TABLE(pk INT, LogInsertTime DATETIME);
INSERT @MyTable
VALUES (1, DATEADD(HOUR, 1, CAST(DATEADD(DAY, -7, CAST (GETDATE() AS DATE))AS DATETIME))),
(2, DATEADD(HOUR, 23, CAST(DATEADD(DAY, -7, CAST (GETDATE() AS DATE)) AS DATETIME)));
DECLARE @DateTime DATETIME = GETDATE();
SELECT *
FROM @MyTable
WHERE DATEDIFF(DAY, LogInsertTime, @DateTime) > 7;
-- 0 records.
SELECT *
FROM @MyTable
WHERE LogInsertTime < @DateTime - 7;
-- 1 record.
Run Code Online (Sandbox Code Playgroud)
将启用潜在索引使用的第一个查询的逻辑等效项是删除时间部分@DateTime或将时间设置为0:00:00:
SELECT *
FROM @MyTable
WHERE LogInsertTime < CAST(@DateTime - 7 AS DATE);
Run Code Online (Sandbox Code Playgroud)
第一个查询不能使用索引LogInsertTime的原因是因为该列隐藏在一个函数中。查询 #2 将列与常量值进行比较,这使优化器能够选择 上的索引LogInsertTime。
| 归档时间: |
|
| 查看次数: |
699 次 |
| 最近记录: |