转 exists in (二)

SQL in与exists用法对比
本文对比了SQL中in与exists两种子查询方式的执行效率及适用场景。in适用于小表查询大表,exists则适合大表查询。通过具体例子说明了不同情况下的性能差异。

http://blog.youkuaiyun.com/lick4050312/article/details/4476333

select * from A
where id in(select id from B)

以上查询使用了in语句,in()只执行一次,它查出B表中的所有id字段并缓存起来.之后,检查A表的id是否与B表中的id相等,如果相等则将A表的记录加入结果集中,直到遍历完A表的所有记录.
它的查询过程类似于以下过程

List resultSet=[];
Array A=(select * from A);
Array B=(select id from B);

for(int i=0;i
   for(int j=0;j
      if(A[i].id==B[j].id) {
         resultSet.add(A[i]);
         break;
      }
   }
}
return resultSet;

可以看出,当B表数据较大时不适合使用in(),因为它会B表数据全部遍历一次.
如:A表有10000条记录,B表有1000000条记录,那么最多有可能遍历10000*1000000次,效率很差.
再如:A表有10000条记录,B表有100条记录,那么最多有可能遍历10000*100次,遍历次数大大减少,效率大大提升.

结论:in()适合B表比A表数据小的情况

select a.* from A a
where exists(select 1 from B b where a.id=b.id)

以上查询使用了exists语句,exists()会执行A.length次,它并不缓存exists()结果集,因为exists()结果集的内容并不重要,重要的是结果集中是否有记录,如果有则返回true,没有则返回false.
它的查询过程类似于以下过程

List resultSet=[];
Array A=(select * from A)

for(int i=0;i
   if(exists(A[i].id) {    //执行select 1 from B b where b.id=a.id是否有记录返回
       resultSet.add(A[i]);
   }
}
return resultSet;

当B表比A表数据大时适合使用exists(),因为它没有那么遍历操作,只需要再执行一次查询就行.
如:A表有10000条记录,B表有1000000条记录,那么exists()会执行10000次去判断A表中的id是否与B表中的id相等.
如:A表有10000条记录,B表有100000000条记录,那么exists()还是执行10000次,因为它只执行A.length次,可见B表数据越多,越适合exists()发挥效果.
再如:A表有10000条记录,B表有100条记录,那么exists()还是执行10000次,还不如使用in()遍历10000*100次,因为in()是在内存里遍历比较,而exists()需要查询数据库,我们都知道查询数据库所消耗的性能更高,而内存比较很快.

结论:exists()适合B表比A表数据大的情况

请详细分析下面代码:<#import "/decorators/includes/macros.ftl" as m> <#assign ww = JspTaglibs["/WEB-INF/webwork.tld"] /> <#include "/template/includes/actionerrors.ftl"> <#assign useStepNo=false> <#if requestForm.stepForms?exists> <#list requestForm.stepForms as stepForm> <#if stepForm.stepNo?exists> <#assign useStepNo=true> </#if> </#list> </#if> <script> document.onkeydown = function() { if(event.keyCode==116) { event.keyCode=0; event.returnValue = false; } if ((window.event.altKey)&&amp;(window.event.keyCode==115)){ //屏蔽Alt+F4 event.keyCode=0; event.returnValue=false; alert("Please do not exit like this again. This case maybe have some problem cause of the action.Please check it.\r\n 请下次不要再这样退出。由于你的这个动作,这个单子可能已经产生了错误,请检查。"); return false; } if ((event.ctrlKey)&&amp;(event.keyCode==87)){ //屏蔽 Ctrl+n event.keyCode=0; event.returnValue=false; return false; } } //document.oncontextmenu = function() {event.returnValue = false;} function continueRuncard(){ var date = new Date(); var minute=date.getMinutes(); if(parseInt(minute)>=0 && parseInt(minute)<=5) { alert("整点系统同步中.\n请稍后再试!"); return false; } var compareResultComment=document.getElementById("compareResultComment"); if (compareResultComment!=null){ confineStringLength(compareResultComment,500); if(compareResultComment.value==""){ return false; } } var form = document.forms['']; form.action="continueRuncard.action"; form.submit(); } function cancelRuncard(){ var date = new Date(); var minute=date.getMinutes(); if(parseInt(minute)>=0 && parseInt(minute)<=5) { alert("整点系统同步中.\n请稍后再试!"); return false; } var form = document.forms['']; form.action="cancelRuncard.action"; form.submit(); } function compareWithMes(){ <#if Rework> alert("Because RunCard's category is rework. \r\n System will not execute this function!"); return false; </#if> var form = document.forms['submitRequestFormForm']; if(!confirm("Do you want to create the comparison with MES document?\n你是否需要E-RC与MES做对比?\n\n确定 = E-RC对比MES(此动作可能需要花费几分钟时间,请耐心等待)\n\n取消 = E-RC不比对MES")){ return false; } form.action="eRuncardRule.action"; form.submit(); } function submitRunCard(){ var compareResultComment=document.getElementById("compareResultComment"); if (compareResultComment!=null){ confineStringLength(compareResultComment,500); if(compareResultComment.value==""){ return false; } } var date = new Date(); var minute=date.getMinutes(); if(parseInt(minute)>=0 && parseInt(minute)<=5) { alert("整点系统同步中.\n请稍后再试!"); return false; } disableButton(); var f=document.submitRequestFormForm; f.action = "submitRequestForm.action"; var xmlHttp = XmlHttp.create(); var async = false; xmlHttp.open("GET", "checkStepNoExistInFecp.action?lotId=${requestForm.lotId?if_exists}&holdStepNo=${requestForm.holdStepNo?if_exists}", async); xmlHttp.send(null); if(xmlHttp.responseText != null && xmlHttp.responseText == '<success/>'){ if (!confirm("你确认是否需要在这步做STR/MSTR and Link STR/MSTR \nNumber? If yes, 请确认E-runcard condition exactly \n match with FECP/STR, MSTR system\n\n确定 = 确认 Link STR/MSTR Number, submit E-runcard \n\n取消 = 修改 E-runcard")){ f.action = "viewUpdateRequestForm.action"; //f.submit(); } f.submit(); }else if(xmlHttp.responseXML != null && xmlHttp.responseXML.getElementsByTagName("success").length > 0){ if (!confirm("你确认是否需要在这步做STR/MSTR and Link STR/MSTR \nNumber? If yes, 请确认E-runcard condition exactly \n match with FECP/STR, MSTR system\n\n确定 = 确认 Link STR/MSTR Number, submit E-runcard \n\n取消 = 修改 E-runcard")){ f.action = "viewUpdateRequestForm.action"; //f.submit(); } f.submit(); }else{ f.submit(); } } </script> <@ww.form name="'submitRequestFormForm'" namespace="'/user'" validate="'true'" method="'post'" theme="'simple'"> <@ww.hidden name="'requestFormId'" value="${requestForm.id}"/> <@ww.token name="submitToken"/> <div class="app"> <h3>View e-Runcard Request Form</h3> <table border="0" cellspacing="1" cellpadding="8" width="100%"> <tr class="b"> <td>RunCard No.:</td> <td>${requestForm.caseNo?if_exists}</td> <td>Status:</td> <td><font color="red">${requestForm.status?if_exists}</font></td> </tr> <tr class="b"> <td>Applicant:</td> <td><@m.directoryLink requestForm.applicant?if_exists/> </td> <td>Organization:</td> <td>${requestForm.applicantOrg?if_exists}</td> </tr> <tr class="b"> <td>Submit Date:</td> <td>${requestForm.submitDate?if_exists}</td> <td>Effective Date:</td> <td>${requestForm.effectiveDate?if_exists}</td> </tr> <#include "viewIncludeLotInfo.ftl"/> <#include "viewIncludeSignInfo.ftl"/> <#include "viewIncludeErcHeaderInfo.ftl"/> <#include "viewIncludeErcCompleteInfo.ftl"/> <#switch requestForm.formType> <#case "Auto Reposition Step"> <#break> <#default> <table border="0" cellspacing="1" cellpadding="8" width="100%"> <tr> <th colspan="4">RunCard Steps Information</th> </tr> <#assign showWGAction = true > <#include "stepForm/includeStepForm.ftl"/> </table> </#switch> </table> <hr/> <#if requestForm.match?default("")=="N"> <table border="0" cellspacing="1" cellpadding="8" width="100%"> <tr class="b"> <td>Compare Result Comment <BR>请输入原因(Only 500 characters)</td> <td><@ww.textarea name="'requestForm.compareResultComment'" id="compareResultComment" cols="80" rows="5" theme="'simple'"/></td> </tr> </table> </#if> <table width="100%"> <tr> <td class="center"> <#if requestForm.formType="Normal"> <input type="button" onclick="compareWithMes()" value="Compare"/>&nbsp;&nbsp;&nbsp;&nbsp; </#if> <#if requestForm.haveQtime?exists> <#if requestForm.haveQtime=="Y"> <#if requestForm.formType!="Scan Defect"> <#if requestForm.formType="Normal" && useStepNo && requestForm.match=="No Comparison" && !Rework> <input type="button" class="btn" value="Continue Runcard" onclick="alert('please compare runcard first.');"/>&nbsp;&nbsp;&nbsp;&nbsp; <#else> <input type="button" class="btn" value="Continue Runcard" onclick="continueRuncard()"/>&nbsp;&nbsp;&nbsp;&nbsp; </#if> </#if> <input type="button" class="btn" value="Cancel Runcard" onclick="cancelRuncard()"/>&nbsp;&nbsp;&nbsp;&nbsp; </#if> <#else> <#if requestForm.formType="Normal" && useStepNo && requestForm.match=="No Comparison" && !Rework> <input type="button" class="btn" value="Submit" onclick="alert('please compare runcard first.');"/>&nbsp;&nbsp;&nbsp;&nbsp; <#else> <input type="button" class="btn" value="Submit" onclick="submitRunCard()"/>&nbsp;&nbsp;&nbsp;&nbsp; </#if> <input type="button" class="btn" value="Back" onclick="document.location.href='${req.contextPath}/user/viewUpdateRequestForm.action?requestFormId=${requestForm.id}'"/> </#if> </td> </tr> </table> <div> </@ww.form>
09-20
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值