2010-04-20 50 views
1

我有一个SQL查询,我试图调试。它适用于小数据集,但是在大量数据集中,它的这个特定部分会导致它花费45-50秒而不是秒速。此子查询是较大查询中的一个选择项。基本上,我试图找出当工作最早日期是在同一类别,因为我们在看(表DR)在SQL查询子查询造成巨大的延迟

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, 

这卷起执行键查找当前行适合一些18000000在有346,000条记录的桌子上进行。我试过在它上面创建一个索引,但没有取得任何成功。而且,在同一个查询中选择一个最大值是次要的,因为它不需要执行很多次。

任何有关尝试不同方法的建议?谢谢!

回答

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 

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

+0

谢谢!那就是诀窍。 – Spencer 2010-04-20 17:42:24