先看看非嵌套查詢(xún):
a.select * from t1
inner join t2 on t1.id = t2.id
inner join t3 on t1.id = t3.id
where t1.a=1 and t2.b=1 and t3.c=1
b.select * from t1
inner join t2 on t1.id = t2.id and t2.b=1
inner join t3 on t1.id = t3.id
where t1.a=1 and t3.c=1
c.select * from t1
inner join t2 on t1.id = t2.id and t2.b=1
inner join t3 on t1.id = t3.id and t3.c=1
where t1.a=1
在上面三個(gè)非嵌套查詢(xún),讓“and t2.b=1”和“and t3.c=1”分別在join...on和where之間游走,用Management Studio選中“包含實(shí)際的執(zhí)行計(jì)劃”并執(zhí)行這三條語(yǔ)句,都得出下面這個(gè)執(zhí)行計(jì)劃。
三個(gè)“聚集索引掃描”的謂詞從上到下分別是:
1.t3.c=1
2.t1.a=1 (seek謂詞:t1.id=t3.id)
3.t2.b=1 (seek謂詞:t2.id=t3.id)
故可以認(rèn)為:在MS SQL2005中,條件跟在join...on后面 和 跟在where后面是等價(jià)的。
接著看嵌套查詢(xún):
d.select * from t1
inner join (select * from t2 where t2.b=1)a on t1.id=a.id
inner join t3 on t1.id = t3.id
where t1.a=1 and t3.c=1
e.select * from t1
inner join (select * from t2 where t2.b=1)a on t1.id=a.id
inner join (select * from t3 where t3.c=1)b on t1.id=b.id
where t1.a=1
f.elect * from t1
inner join (select t3.id,t2.b,t3.c from t3 inner join t2 on t2.id = t3.id where t2.b=1 and t3.c=1)a on t1.id=a.id
where t1.a=1
第一句sql語(yǔ)句把t2的查詢(xún)變成子查詢(xún),第二句sql語(yǔ)句把t2,t3分別變成子查詢(xún),第三句把t2和t3的查詢(xún)合成一個(gè)子查詢(xún),再看看實(shí)際的執(zhí)行計(jì)劃:
跟上面非嵌套查詢(xún)的執(zhí)行計(jì)劃一模一樣。
故可以認(rèn)為:簡(jiǎn)單(注意是簡(jiǎn)單的,復(fù)雜的情況得另外考慮)嵌套查詢(xún)和其相對(duì)應(yīng)的非嵌套查詢(xún)形式,執(zhí)行效率是一樣的(網(wǎng)上一些文章指出這是MS SQL優(yōu)化器針對(duì)這些嵌套查詢(xún)進(jìn)行了優(yōu)化)。
接著,在上面兩個(gè)執(zhí)行計(jì)劃的圖中又發(fā)現(xiàn)一個(gè)小問(wèn)題,為什么明明是select t1 inner join t2 inner join t3,執(zhí)行計(jì)劃卻把t1和t3先inner join(t1.id = t3.id)再跟t2 inner join(t2.id = t3.id)起來(lái)?
經(jīng)過(guò)三個(gè)表,四個(gè)表,五個(gè)表進(jìn)行連接測(cè)試,發(fā)現(xiàn)這些順序都是不確定的。很可能這些順序是根據(jù)SQL優(yōu)化器內(nèi)的算法所決定的,由于沒(méi)有源代碼,所以無(wú)從考究。
PS:
1.經(jīng)測(cè)試,在join on后面t1.id = t2.id與t2.id = t1.id等價(jià)
如果發(fā)現(xiàn)這文章有錯(cuò)誤,歡迎指出。
作者博客:http://www.cnblogs.com/StephenHuang/