If you have a query like this:
select * from zd where z in (select z from zh where y = 'A' and y = zd.y)
It is recommended to index on both y,z fields of both zh and zd tables
create index x_zh on zh(y,z) create index x_zd on zd(y,z)
The query above internally gets translated to:
select * from zd where exists (select * from zh where y = 'A' and y = zd.y and z = zd.z)
In Oracle and Postgres that query has intuitive form:
select * from zd where (y,z) in (select y,z from zh where y = 'A')
Here's the execution plan:
Whole code for proof of concept:
-- first pair of tables...
select * into zh
from(values
('A',1),
('B',2),
('C',3)) as x(y,z)
select * into zd
from(values
('A',1),
('B',2),
('C',3)) as x(y,z)
-- performant index
create index x_zh on zh(y,z)
create index x_zd on zd(y,z)
-- ...first pair of tables
-- second pair of tables...
select * into wh
from(values
('A',1),
('B',2),
('C',3)) as x(y,w)
select * into wd
from(values
('A',1),
('B',2),
('C',3)) as x(y,w)
-- these index doesn't get used
create index x_wh_y on wh(y)
create index x_wh_z on wh(w)
create index x_wd_y on wd(y)
create index x_wd_z on wd(w)
-- ...second pair of tables
-- execute this in execution planner, highlight them then press Ctrl+L:
select * from zd where z in (select z from zh where y = 'A' and y = zd.y)
select * from wd where w in (select w from wh where y = 'A' and y = wd.y)
Here's the output:
Here's the index seek predicates(I hope I have enough street cred to use the word predicate LOL):
As we can see from the seek predicates execution plan: zh.y,zh.z == 'A',zd.z ; even though it's from Sql Server, it has more affinity with this query style(i.e. Postgres and Oracle style):
select * from zd where (y,z) in (select y,z from zh where y = 'A')
Which internally gets translated to:
select * from zd where (y,z) in (select 'A',z from zh where y = 'A')
Let's just hope that future Sql Server will support tuples in subquery




No comments:
Post a Comment