Oracle的优化原则

3.3.1. 优化原则

执行计划中首先要检查表的连接方式是否符合下面的原则,其次才是表的访问方式。因为连接方式决定着访问方式,也就是说连接方式决定着索引要不要用、如何用。

概念解释:

结果集:根据查询条件对表进行过滤后的集合。

驱动表:执行计划中,同一父节点下的两个表,显示在上方的是驱动表,下方的是被驱动表

 

原则1: NESTED LOOP

适用场景:

驱动表结果集很小(通常记录数在1000以内),被驱动表小或者存在高效索引可利用。例如:

 

使用限制:

工作原理:

取驱动表A结果集一条记录,通过连接键与被驱动表B做比较。循环这个动作直到驱动表记录取完。

COST=COST(A)+n*COST(B),其中COST(A)是访问A表的代价,COST(B)是访问B表的代价,n是A表结果集记录数。

 

原则2: MERGE JOIN

适用场景:

该连接方式一般很少会用到,通常用于不等价连接和交叉连接。当其中一个表的结果集有序时也可能会出现。

使用限制:

工作原理:

分别访问A表和B表并按连接键排序,然后依次交替比较、合并。

COST=COST(A)+COST(B)+SORT(A)+SORT(B)

注意:

某些执行计划中会出现MERGE JOIN CARTESIAN,表示两个表无条件连接,产生了笛卡尔积。这通常是由于表连接顺序错误导致的

 

原则3: HASH JOIN

适用场景:

通常用于大表之间的连接。

使用限制:

只能用于等价连接

工作原理:

选择较小表,并在内存中建立该表基于连接键的哈希表,然后扫描大表并与哈希表比较。

理想情况下(即小表可以全部放到内存里),COST=COST(A)+COST(B)

 

对于连接键是否需要建索引,hash join不需要,nested loop通常需要。

除了不等价连接的情况,hash join基本上可以替代merge join。

至于是hash join快还是nested loop快,要看hash join的COST(B)和nested loop的n*COST(B)哪个更小。注意,这两个COST(B)是有差别的。例如:ACT_FUNDACCOUNT表记录数1549488blocks 29696,索引IDX_ACT_FUNDACCOUNT_C高度为3.

 

红色方框中是nested loop方式下的COST(B)=3(索引高度)+1(回表)。

 

红色方框中是hash join方式下的COST(B)= 29696(blocks)。

29696/(3+1)=7424,也就是当n(A表结果集)<7424时,nested loop更快,反之hash join更快。

 

原则4: FILTER

通常FILTER用来做一些条件过滤操作,如下图所示:

 

 

 

这种情况下,我们不需要关注这个操作。但有时候它也算是表连接方式的一种,工作原理和NESTED LOOP类似,但会维护一个hash table,可以认为是介于NESTED LOOP和HASH JOIN之间的一种方式,如下图所示:

 

显然,这里的FILTER就是表的连接方式,一般它只会出现在含有in/exists子查询的sql中。当连接键branch_no的distinct值越多其效率越接近NESTED LOOP,越少则越接近HASH JOIN。

通常连接键的唯一性都较高(比如上面例子中通常会用client_id字段进行连接),所以一般都可以用NESTED LOOP的原则来判断FILTER是否合适。由于ACT_FUNDACCOUNT表数据量较大,所以上面例子所展示的执行计划效率较差,正确的方式应该是下面这样:

 

 

 

原则5: 索引效率

通过索引字段返回的数据越少,该索引越快;反之越慢。当返回的数据量超过某个临界点时,走索引比全表扫描要慢,这个临界点一般是表总数据量的20%左右。

 

例如下面的语句(source_flag是索引字段):

select * from act_fundaccount where source_flag = :a;

要分析执行计划的好坏,首先要知道绑定变量:a的值以及source_flag字段的数据分布,如下图:

 

按照本原则,当绑定变量:a值为0时,应该走全表扫描,如下图:

当值为1时,应该走索引范围扫描,然后回表,如下图:

 

 

 

原则6: 大表UPDATE

UPDATE操作使用的是NESTED LOOP方式,所以当被更新结果集比较大时,效率较差。可以用MERGE改写sql,替换UPDATE。本质上是用HASH JOIN 替换NESTED LOOP。

 

从上面所述原则不难看出,要分析执行计划优劣,首先要了解表数据量、数据分布(即值的占比),之后才能按上面所说的原则进行判断。

posted @ 2022-11-21 20:37  编程小白1024  阅读(372)  评论(0编辑  收藏  举报