简体   繁体   中英

Performance Issue in Left outer join Sql server

In my project I need find difference task based on old and new revision in the same table.

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

Expected Result:

   id       |     task   | latest_Rev   
   2               C           Y

So I tried following query

  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

when my table have more than 20k records this query takes more time? How to reduce the time?

In my company don't allow to use subquery

Use LAG function to remove the self join

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 
  1. latest_Rev should be a Bit type (boolean equivalent), i better for performance (Detail here )
  2. May be can you add index on id, task , latest_Rev columns

You can try this query (replace left outer by not exists)

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
)

My answer assumes

  • You can't change the indexes
  • You can't use subqueries
  • All fields are indexed separately

If you look at the query, the only value that really reduces the resultset is latest_rev='Y' . If you were to eliminate that condition, you'd definitely get a table scan. So we want that condition to be evaluated using an index. Unfortunately a field that just values 'Y' and 'N' is likely to be ignored because it will have terrible selectivity. You might get better performance if you coax SQL Server into using it anyway. If the index on latest_rev is called idx_latest_rev then try this:

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'

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM