select * from A where id in(select id from B)
以上查詢使用了in語句,in()只執(zhí)行一次,它查出B表中的所有id字段并緩存起來.之后,檢查A表的id是否與B表中的id相等,如果相等則將A表的記錄加入結(jié)果集中,直到遍歷完A表的所有記錄.
它的查詢過程類似于以下過程
List resultSet=[];
Array A=(select * from A);
Array B=(select id from B);
for(int i=0;i<A.length;i++){
? ?for(int j=0;j<B.length;j++){
? ? ? ? ?if(A[i].id==B[j].id) {?
? ? ? ? ?resultSet.add(A[i]);
? ? ? ? ?break;
? ? ? ? ?}
? ?}
}
return resultSet;
可以看出,當(dāng)B表數(shù)據(jù)較大時不適合使用in(),因為它會B表數(shù)據(jù)全部遍歷一次.
如:A表有10000條記錄,B表有1000000條記錄,那么最多有可能遍歷10000*1000000次,效率很差.
再如:A表有10000條記錄,B表有100條記錄,那么最多有可能遍歷10000*100次,遍歷次數(shù)大大減少,效率大大提升.
結(jié)論:in()適合B表比A表數(shù)據(jù)小的情況
select a.* from A a
where exists(select 1 from B b where a.id=b.id)
以上查詢使用了exists語句,exists()會執(zhí)行A.length次,它并不緩存exists()結(jié)果集,因為exists()結(jié)果集的內(nèi)容并不重要,重要的是結(jié)果集中是否有記錄,如果有則返回true,沒有則返回false.
它的查詢過程類似于以下過程
List resultSet=[];
Array A=(select * from A)
for(int i=0;i<A.length;i++){
? ? ? ?if(exists(A[i].id) {??? //執(zhí)行select 1 from B b where b.id=a.id是否有記錄返回
? ? ? ? resultSet.add(A[i]);
? ? ? ?}
}
? ? ? ? return resultSet;
當(dāng)B表比A表數(shù)據(jù)大時適合使用exists(),因為它沒有那么遍歷操作,只需要再執(zhí)行一次查詢就行.
如:A表有10000條記錄,B表有1000000條記錄,那么exists()會執(zhí)行10000次去判斷A表中的id是否與B表中的id相等.
如:A表有10000條記錄,B表有100000000條記錄,那么exists()還是執(zhí)行10000次,因為它只執(zhí)行A.length次,可見B表數(shù)據(jù)越多,越適合exists()發(fā)揮效果.
再如:A表有10000條記錄,B表有100條記錄,那么exists()還是執(zhí)行10000次,還不如使用in()遍歷10000*100次,因為in()是在內(nèi)存里遍歷比較,而exists()需要查詢數(shù)據(jù)庫,我們都知道查詢數(shù)據(jù)庫所消耗的性能更高,而內(nèi)存比較很快.
結(jié)論:exists()適合B表比A表數(shù)據(jù)大的情況
當(dāng)A表數(shù)據(jù)與B表數(shù)據(jù)一樣大時,in與exists效率差不多,可任選一個使用.