2017-06-16 46 views
0

在我的项目中,我需要在同一个表中找到基于旧版本和新版本的差异任务。左外连接Sql server中的性能问题

id  | task | latest_Rev 
1    A   N 
1    B   N 
2    C   Y 
2    A   Y 
2    B   Y 

预期结果:

id  |  task | latest_Rev 
    2    C   Y 

所以,我想下面的查询

Select new.* 
    from Rev_tmp nw with (nolock) 
    left outer 
    join rev_tmp old with (nolock) 
    on nw.id -1 = old.id 
    and nw.task = old.task 
    and nw.latest_rev = 'y' 
    where old.task is null 

,当我的表具有20K以上的记录此查询需要更多的时间? 如何缩短时间?

在我的公司不允许使用子查询

+2

比什么呢?你的表格如何索引?什么是查询计划? –

+2

不允许使用子查询听起来很奇怪。你允许使用CTE吗?派生表?你为什么被允许使用NOLOCK? –

+0

我的表没有所有主要字段的聚集索引。它是一个规则。 @JamesZ。 – Sathish

回答

5

使用LAG函数删除自加入

SELECT * 
FROM (SELECT *, 
       CASE WHEN latest_Rev = 'y' THEN Lag(latest_Rev) OVER(partition BY task ORDER BY id) ELSE NULL END AS prev_rev 
     FROM Rev_tmp) a 
WHERE prev_rev IS NULL 
+0

什么是更好的表现?我的“不存在”或你的“滞后”?在大桌子上,我认为它不存在,你怎么看待这个问题? – Esperento57

+1

@ Esperento57 - 显然'LAG','Not exists'需要*扫描/查找表格两次。 –

+0

是的,但你也使用'案例'和临时表为你的地方;) – Esperento57

0
  1. latest_Rev应该有点类型(布尔当量),我更好地表现(详细here
  2. 可能是你可以在ID添加索引,任务 ,latest_Rev列

你可以试试这个查询(替换用不存在左外)

Select * 
from Rev_tmp nw 
where nw.latest_rev = 'y' and not exists 
(
select * from rev_tmp old 
where nw.id -1 = old.id and nw.task = old.task 
) 
0

我的回答假设

  • 不能更改索引
  • 不能使用子查询
  • 所有字段建立索引分开

如果查看查询,真正减少结果集的唯一值是latest_rev='Y'。如果你想消除这种情况,你肯定会得到一个表扫描。所以我们希望使用索引来评估这个条件。不幸的是,一个仅仅重视'Y'和'N'的领域很可能会被忽略,因为它具有可怕的选择性。你可以可能得到更好的性能,如果你哄SQL Server无论如何使用它。如果latest_rev指数被称为idx_latest_rev那就试试这个:

Set transaction isolated level read uncommitted 

Select new.* 
from Rev_tmp nw with (index(idx_latest_rev)) 
left outer 
join rev_tmp old 
on nw.id -1 = old.id 
and nw.task = old.task 
where old.task is null 
and nw.latest_rev = 'y'