Quantcast
Channel: Forum SQL Server Database Engine
Viewing all articles
Browse latest Browse all 15694

How to avoid an expensive SORT after a JOIN?

$
0
0
I have an query with an expensive SORT after the join:

use tempdb
drop table tempdb..t1
drop table tempdb..t2
drop table tempdb..t3
create table  t1(c1 int, c2 int, c3 int, c4 int, c5 int)
create table  t2 (c1 int, c2 int, c3 int, c4 int, c5 int)
create table  t3 (c1 int, c2 int, c3 int, c4 int, c5 int)
go
set nocount off
declare @x int =1
declare @max int =500000
while(@x<=@max)
begin
 insert into t1 values(@x,@max-@x,(@max-@x)*10,@x*100,@x);
 insert into t2 values(@x,@x,@x,@x,@x);
 insert into t3 values(@x,@x,(@x)*10,@x,@x);
 set @x+=1;
end
go
select * from t1
select * from t2
select * from t3
go
create   clustered index idxt1a on t1(c2,c4,c3,c5)
create   index idxt1b on t1(c3) include (c1)
CREATE STATISTICS [_dta_stat_3_2_4_5] ON [dbo].[t1]([c3], [c2], [c4], [c5])
CREATE STATISTICS [_dta_stat_4_3_5] ON [dbo].[t1]([c4], [c3], [c5])
create index idxt2 on t2(c2) --ok
create index idxt3 on t3(c3) --ok
go
set statistics io on
set statistics time on
set statistics profile on
go
select t1.* from t1 --WITH (INDEX (idxt1b))
inner /*merge*/ join t2 on t1.c2=t2.c2   
inner  join t3 on t1.c3=t3.c3
order by t1.c2, t1.c4,t1.c3,t1.c5
--option (FORCE ORDER)
go
set statistics io off
set statistics time off
set statistics profile off


----------
----------
Ideally, I'd like to avoid the expensive in memory SORT, which is spilling into tempdb.
----------
----------

Work done:
1. I tried various combinations of indexes to try to get an index intersection going - no luck
2. Also tried rewriting somehow to a union all - since previous query also returned duplicates - worse performance
--- rewritten as union all  -------------
set statistics io on
set statistics time on
set statistics profile on
go
select t1.* from t1 WITH (INDEX (idxt1a))
inner /*merge*/ join t2 on t1.c2=t2.c2 
--order by t1.c2--,t1.c4,t1.c3,t1.c5
union all
select t1.* from t1 WITH (INDEX (idxt1b))
inner /*merge*/ join t3 on t1.c3=t3.c3
order by t1.c2,t1.c4,t1.c3,t1.c5
--option (FORCE ORDER)
-- WITH (INDEX (idxt1d))
--option (Table hint ( t1, INDEX(idxt1b)))
go
set statistics io off
set statistics time off
set statistics profile off

3. Rewrote to use Exists clause - not much better performance
--- rewritten as EXISTS   -------------
set statistics io on
set statistics time on
set statistics profile on
go
select t1.* from t1 --WITH (INDEX (idxt1b))
where  exists (select c2 from t2 where t1.c2=t2.c2)
and exists (select c3 from t3 where t1.c3=t3.c3)
order by t1.c2, t1.c4,t1.c3,t1.c5
--option (FORCE ORDER)
go
set statistics io off
set statistics time off
set statistics profile off

4.--- rewritten as IN   -------------
set statistics io on
set statistics time on
set statistics profile on
go
select t1.* from t1 --WITH (INDEX (idxt1b))
where  t1.c2 in (select c2 from t2)
and t1.c3 in (select c3 from t3)
order by t1.c2, t1.c4,t1.c3,t1.c5
--option (FORCE ORDER)
go
set statistics io off
set statistics time off
set statistics profile off

Any creative ideas of how to avoid the sort after the joins?


Viewing all articles
Browse latest Browse all 15694

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>