sql中in、exists在驱动表选择上的执行效率测试分析(二)

2014-11-24 12:13:11 · 作者: · 浏览: 2
| TABLE ACCESS FULL| B | 499 | 6986 | | 5 (0)| 00:00:01 |

------------------------------------------------------------------------------------

Predicate Information (identified by operation id):

---------------------------------------------------

2 -access("A"."OBJECT_NAME"="B"."OBJECT_NAME")

3.2 小表B驱动

SQL> select count(*) from a where exists(select 1 from b wherea.object_name=b.object_name);

COUNT(*)

----------

15968

1 row selected.

Elapsed: 00:00:00.29

Execution Plan

----------------------------------------------------------

Plan hash value: 894329177

------------------------------------------------------------------------------

| Id |Operation | Name | Rows | Bytes | Cost (%CPU)| Time |

------------------------------------------------------------------------------

| 0 | SELECTSTATEMENT | | 1 | 39 | 13006 (1)| 00:00:01 |

| 1 | SORT AGGREGATE | | 1 | 39 | | |

|* 2 | HASH JOIN RIGHT SEMI| | 27474 | 1046K| 13006 (1)| 00:00:01 |

| 3 | TABLE ACCESS FULL | B | 499 | 6986 | 5 (0)| 00:00:01 |

| 4 | TABLE ACCESS FULL | A | 2850K| 67M| 12992 (1)| 00:00:01 |

------------------------------------------------------------------------------

Predicate Information (identified by operation id):

---------------------------------------------------

2 - access("A"."OBJECT_NAME"="B"."OBJECT_NAME")

--还是发现小表作为驱动表快,小表为驱动29毫秒,大表A为驱动表,执行时间2.47秒

结论:

1 发现不管用大表还是小表还是大表作为驱动表,exists执行效率都比in要高。

2 不管使用exits还是in,oracle优化器默认都使用了hash join进行了连接处理。

3 不管使用exits还是in,经测试证明小表作为驱动表,效率更优

4 oracle优化器默认使用小表作为驱动表,说明优化器判断准确,符合预期

exists为什么效率比in高

1 可以看到测试中的结果都使用了hash join,相当于在连接键上创建了一个索引,加快了处理速度,in语句也同样获益。

2 可以发现in后的结果集要比exits后的结果集大,这是导致exists效率高的一个主要原因,本例例外(b表完全是a表的子集)。

3 in后面的结果集需要首先查询计算出来,然后进行散列连接,最后执行主查询,时间长

exists后面的结果集直接实现了散列连接,和主查询同步进行连接,存在就返回相应数据,处理步骤少,处理时间短,再结合第二条处理比in节省资源。

如何进一步提速

其实很简单,在内表,也就是被驱动表上的相关列上创建索引,经过测试,exists的效率为2毫秒,相对没有索引的情况,速度提高100倍以上,这里不再列出加索引的测试。