sql server - Make use of index when JOIN'ing against multiple columns -
simplified, have 2 tables, contacts , donotcall
create table contacts ( id int primary key, phone1 varchar(20) null, phone2 varchar(20) null, phone3 varchar(20) null, phone4 varchar(20) null ); create table donotcall ( list_id int not null, phone varchar(20) not null ); create nonclustered index ix_donotcall_list_phone on donotcall ( list_id asc, phone asc ); i see contacts matches phone number in specific list of donotcall phone. faster lookup, have indexed donotcall on list_id , phone.
when make following join takes long time (eg. 9 seconds):
select distinct c.id contacts c join donotcall d on d.list_id = 1 , d.phone in (c.phone1, c.phone2, c.phone3, c.phone4) 
while if left join on each phone field seperately runs lot faster (eg. 1.5 seconds):
select c.id contacts c left join donotcall d1 on d1.list_id = 1 , d1.phone = c.phone1 left join donotcall d2 on d2.list_id = 1 , d2.phone = c.phone2 left join donotcall d3 on d3.list_id = 1 , d3.phone = c.phone3 left join donotcall d4 on d4.list_id = 1 , d4.phone = c.phone4 d1.phone not null or d2.phone not null or d3.phone not null or d4.phone not null 
my assumption first snippet runs because doesn't utilize index on donotcall.
so, how join towards multiple columns , still have use index?
sql server might think resolving in (c.phone1, c.phone2, c.phone3, c.phone4) using index expensive.
you can test if index faster hint:
select c.* contacts c join donotcall d (index(ix_donotcall_list_phone)) on d.list_id = 1 , d.phone in (c.phone1, c.phone2, c.phone3, c.phone4) from query plans posted, shows first plan estimated produce 40k rows, returns 21 rows. second plan estimates 1 row (and of course returns 21 too.)
are statistics date? out-of-date statistics can explain query analyzer making bad choices. statistics should updated automatically or in weekly job. check age of statistics with:
select object_name(ind.object_id) tablename , ind.name indexname , stats_date(ind.object_id, ind.index_id) statisticsdate sys.indexes ind order stats_date(ind.object_id, ind.index_id) desc you can update them manually with:
exec sp_updatestats;
Comments
Post a Comment