1、优化原则:小表驱动大表,即小的数据集驱动大的数据集
select * from A where id in (select id from B)
以上SQL语句等价于:
for select id from B
for select * from A where A.id=B.id
当B表的数据集必须小于A表的数据集时,用IN优于EXISTS
select * from A where exists (select 1 from B where B.id=A.id)
以上SQL语句等价于:
for select * from A
for select * from B where B.id=A.id
当A表的数据集必须小于B表的数据集时,用EXISTS优于IN。
注意:A表与B表的ID字段应建立索引
2、EXISTS
语法如下
SELECT ……FROM table WHERE EXISTS (subquery)
该语法可以理解为:将主查询中的数据,放到子查询中做条件验证,根据验证结果(TRUE或FALSE)来决定主查询的数据结果是否得以保留。
提示
- EXISTS (subquery)只返回TRUE或FALSE,因此子查询中的SELECT * 也可以是SELECT 1 或SELECT ‘X’,官方说法是实际执行时会忽略SELECT清单,因此没有区别
- EXISTS子查询的实际执行过程可能经过了优化而不是我们理解上的逐条对比,如果担心效率问题,可以进行实际校验以确定时候有效率问题
- EXISTS子查询往往可以用条件表达式、其他子查询或者JOIN来代替,何种最优需要具体问题具体分析
总结
- IN:只执行一次;EXISTS:执行A.length次;
- IN:确定给定的值是否与子查询或列表中的值相匹配。in在查询的时候,首先查询子查询的表,然后将内表和外表做一个笛卡尔积,然后按照条件进行筛选。所以相对内表比较小的时候,in的速度较快;
- EXISTS:指定一个子查询,检测行的存在。遍历循环外表,然后看外表中的记录有没有和内表的数据一样的。匹配上就将结果放入结果集中;
- in 和 exists的区别: 如果子查询得出的结果集记录较少,主查询中的表较大且又有索引时应该用in, 反之如果外层的主查询记录较少,子查询中的表大,又有索引时使用exists。其实我们区分in和exists主要是造成了驱动顺序的改变(这是性能变化的关键),如果是exists,那么以外层表为驱动表,先被访问,如果是IN,那么先执行子查询,所以我们会以驱动表的快速返回为目标,那么就会考虑到索引及结果集的关系了 ,另外IN时不对NULL进行处理;
- IN 是把外表和内表作hash 连接,而exists是对外表作loop循环,每次loop循环再对内表进行查询