Azure SQL数据库左连接循环,包含150万条记录

时间:2017-08-30 11:50:50

标签: sql-server azure indexing query-optimization azure-sql-database

我有Table Customer_AJ(客户varchar,项目编号,购买日期时间),并且我有两个表,其中包含成功和失败,并且我希望所有在未来30分钟内没有成功的失败的客户。

我尝试使用不存在但是它在hashMatch上循环(正如我在查询计划中看到的那样,Iam附加查询和执行计划的屏幕截图..

with Failure as (
        select * from [dbo].[Customer_AJ]  where item in  ( 20, 34, 35, 36, 37, 47, 53, 54 )
        )     ,
success as (
    select * from  Customer_AJ where Item in  ( 1, 3, 40, 42, 43, 5 )
        )     ,
final  as (
        select f.customer, f.item,f.purchase from  Failure  f  left outer join success s
         on f.customer = s.customer and DATEDIFF( minute , f.purchase , s.purchase ) between 0 and 30
         where s.customer is NULL         
        )
    select * from final

Here is the Query Execution plan for it

2 个答案:

答案 0 :(得分:1)

核心问题将是列上的DATEDIFF函数。它将导致扫描。如果你有数百万行,那么每次都会很慢。您需要找到一种在不应用该功能的情况下加入数据的方法。

完整的执行计划可能是其他建议,而不是图像。

答案 1 :(得分:0)

就个人而言,在寻找不存在的东西时,我更喜欢使用“显而易见的”。 WHERE NOT EXISTS()语法。查询优化器将使用与LEFT OUTER JOIN ... WHERE field IS NULL语法相同的计划,但它更容易阅读。

SELECT f.customer, f.item, f.purchase
  FROM Failure  f  
 WHERE NOT EXISTS ( SELECT *
                      FROM Success s
                     WHERE s.customer = f.customer
                       AND DATEDIFF( minute , f.purchase , s.purchase ) between 0 and 30 )

DateDiff()是一个性能杀手,因为没有办法快速获得匹配数据,优化器也无法预测匹配的行数。要解决此问题,您可以尝试将DateDiff()转换为DateAdd()构造:

SELECT f.customer, f.item, f.purchase
  FROM Failure  f  
 WHERE NOT EXISTS ( SELECT *
                      FROM Success s
                     WHERE s.customer = f.customer
                       AND s.purchase >= f.purchase
                       AND s.purchase <= DateAdd(minute, +30, f.purchase) )

假设您的Customer_AJ表上有一个索引,其中包含以下字段:customer, item, purchase这应该会使FailureSuccess之间的联接相当快。

(您可能希望尝试并交换字段的顺序,因为它确实依赖于您的数据的样子,但由于我们在purchase列中有一系列匹配项。我很确定你想保留最后一个。)