我正在尝试优化一些非常复杂的SQL查询,因为它需要很长时间才能完成。
在我的查询中,我动态创建了具有许多相同函数的SQL语句,因此我创建了一个临时表,其中每个函数只调用一次而不是多次 - 这使我的执行时间缩短了3/4。
所以我的问题是,如果说1000个日期计算的范围缩小到100,我可以期待看到很多不同吗?
编辑: 查询如下所示:
SELECT DISTINCT M.MID, M.RE FROM #TEMP INNER JOIN M ON #TEMP.MID=M.MID
WHERE ( #TEMP.Property1=1 ) AND
DATEDIFF( year, M.DOB, @date2 ) >= 15 AND DATEDIFF( year, M.DOB, @date2 ) <= 17
这些是作为字符串动态生成的(按位组合在一起),然后执行,以便可以在每次迭代时更改各种参数 - 主要是最后一行,包含各种DATEDIFF查询。
这样的约有420个查询,这些日期计算就像这样计算。我知道我可以轻松地将它们全部放入临时表(1000个日期变为50) - 但它是否值得,它会在几秒钟内产生任何差异吗?我希望能比十分之一秒更好地改善。
答案 0 :(得分:13)
这取决于你所做的事情,说实话的程度。
例如,如果您在WHERE子句中使用DATEDIFF(或实际上任何其他函数),那么这将导致性能较差,因为它会阻止在该列上使用索引。
e.g。基本示例,查找2009年的所有记录
WHERE DATEDIFF(yyyy, DateColumn, '2009-01-01') = 0
不会很好地利用DateColumn上的索引。鉴于更好的解决方案,提供最佳索引使用将是:
WHERE DateColumn >= '2009-01-01' AND DateColumn < '2010-01-01'
我recently blogged关于它的差异(与性能统计/执行计划比较),如果你感兴趣的话。
这比将DATEDIFF作为结果集中的列返回要花费更多。
我首先要确定花费最多时间的各个查询。检查执行计划以查看问题所在并从那里调整。
修改强> 根据您给出的示例查询,您可以尝试在WHERE子句中删除DATEDIFF的使用。找到在给定日期10岁的每个人的基本示例 - 我认为数学是正确的,但无论如何你都会得到这个想法!给它一个快速测试,似乎很好。应该很容易适应你的场景。如果你想找到某个日期(例如)15到17岁之间的人,那么这种方法也是可以的。
-- Assuming @Date2 is set to the date at which you want to calculate someone's age
DECLARE @AgeAtDate INTEGER
SET @AgeAtDate = 10
DECLARE @BornFrom DATETIME
DECLARE @BornUntil DATETIME
SELECT @BornFrom = DATEADD(yyyy, -(@AgeAtDate + 1), @Date2)
SELECT @BornUntil = DATEADD(yyyy, -@AgeAtDate , @Date2)
SELECT DOB
FROM YourTable
WHERE DOB > @BornFrom AND DOB <= @BornUntil
一个重要的补充说明,就是来自DOB的年龄计算,这种方法更准确。您当前的实施仅考虑出生年份,而不是实际的一天(例如,2009年12月1日出生的人将在2010年1月1日出现1岁时,直到2010年12月1日他们不是1岁)。
希望这有帮助。
答案 1 :(得分:0)
与其他处理日期时间值的方法(如字符串)相比,DATEDIFF非常有效。 (see this SO answer)。
在这种情况下,听起来你会翻阅相同的数据,这可能比使用临时表更昂贵。例如,将生成统计信息。
答案 2 :(得分:0)
您可能能够提高性能的一件事可能是在MID上的临时表上放置一个索引。
检查执行计划以查看它是否有帮助(可能取决于临时表中的行数)。