Sub查询中的SQL MIN会导致很大的延迟

时间:2010-04-20 14:28:45

标签: sql subquery

我有一个我正在尝试调试的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万次密钥查找。我试过在它上面创建一个索引,但没有取得任何成功。此外,在同一查询中选择最大值的时间是次秒,因为它根本不必执行很多次。

有什么不同的尝试方法吗?谢谢!

1 个答案:

答案 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

每个查询都将使用自己的索引,最终查询将只选择四个值中的最小值(即时)。