我有一个我正在尝试调试的SQL查询。它适用于小型数据集,但在大型数据集中,它的这一特定部分会导致它需要45-50秒而不是速度低于秒。此子查询是较大查询中的选择项之一。我基本上试图弄清楚最早的工作日期是否与我们正在查看的当前行相同(来自表dr)
ISNULL(CONVERT(varchar(25),(SELECT MIN(drsd.DateWorked) FROM [TableName] drsd
WHERE drsd.UserID = dr.UserID
AND drsd.Val1 = dr.Val1
OR (((drsd.Val2 = dr.Val2 AND LEN(dr.Val2) > 0) AND (drsd.Val3 = dr.Val3 AND LEN(dr.Val3) > 0) AND (drsd.Val4 = dr.Val4 AND LEN(dr.Val4) > 0))
OR (drsd.Val5 = dr.Val5 AND LEN(dr.Val5) > 0)
OR ((drsd.Val6 = dr.Val6 AND LEN(dr.Val6) > 0) AND (drsd.Val7 = dr.Val7 AND LEN(dr.Val2) > 0))))), '') AS WorkStartDate,
这最终会在拥有346,000条记录的表上执行大约1800万次密钥查找。我试过在它上面创建一个索引,但没有取得任何成功。此外,在同一查询中选择最大值的时间是次秒,因为它根本不必执行很多次。
有什么不同的尝试方法吗?谢谢!
答案 0 :(得分:4)
在drsd (UserID, DateWorked)
上创建综合索引。
drsd
中的记录分布也可能偏向更大的日期,如下所示:
DateWorked Condition
01.01.2001 FALSE
02.01.2001 FALSE
…
18.04.2010 FALSE
19.04.2010 TRUE
在这种情况下,MAX
查询只需要浏览1
条记录,而MIN
查询则必须浏览2001
的所有记录。
在这种情况下,您需要创建四个单独的索引:
UserId, Val1, DateWorked
UserId, Val2, Val3, Val4, DateWorked
UserId, Val5, DateWorked
UserId, Val6, Val7, DateWorked
并重写子查询:
SELECT MIN(dateWorked)
FROM (
SELECT MIN(DateWorked) AS DateWorked
FROM drsd
WHERE UserID = dr.UserID
AND Val1 = dr.Val1
UNION ALL
SELECT MIN(DateWorked)
FROM drsd
WHERE UserID = dr.UserID
AND drsd.Val2 = dr.Val2 AND LEN(dr.Val2) > 0
AND drsd.Val3 = dr.Val3 AND LEN(dr.Val3) > 0
AND drsd.Val4 = dr.Val4 AND LEN(dr.Val4) > 0
UNION ALL
SELECT MIN(DateWorked)
FROM drsd
WHERE UserID = dr.UserID
AND drsd.Val5 = dr.Val5 AND LEN(dr.Val5) > 0
UNION ALL
SELECT MIN(DateWorked)
FROM drsd
WHERE UserID = dr.UserID
AND drsd.Val6 = dr.Val6 AND LEN(dr.Val6) > 0
AND drsd.Val7 = dr.Val7 AND LEN(dr.Val7) > 0
) q
每个查询都将使用自己的索引,最终查询将只选择四个值中的最小值(即时)。