有如下执行计划(从 AWR 中抓出)。
select * from table(dbms_xplan.display_awr('3m7f7xdpkdrtv', NULL, NULL, 'ALL')) ;
SQL_ID 3m7f7xdpkdrtv
--------------------
select a.int_id,a.zh_label,a0.zh_label from VIEW_RMS_POS_PORT a inner
join (select int_id,zh_label from RMS_LOCALNET_POS where
stateflag=:"SYS_B_00") a0 on to_char(a.up_pos_id)=to_char(a0.int_id)
where a0.zh_label in (:"SYS_B_01",:"SYS_B_02",:"SYS_B_03",:"SYS_B_04",
:"SYS_B_05",:"SYS_B_06",:"SYS_B_07",:"SYS_B_08",:"SYS_B_09",:"SYS_B_10")
and :"SYS_B_11"=:"SYS_B_12" and (a.zh_label in (:"SYS_B_13")) and
a.stateflag=:"SYS_B_14"
Plan hash value: 494215470
------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes |
------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | | |
| 1 | FILTER | | | |
| 2 | NESTED LOOPS | | 1 | 94 |
| 3 | INDEX RANGE SCAN | RMS_JK_POS_PORT_PK | 1 | 43 |
| 4 | TABLE ACCESS BY INDEX ROWID| RMS_LOCALNET_POS | 1 | 51 |
| 5 | INDEX SKIP SCAN | RMS_LOCALNET_POS_PUI | 35 | |
------------------------------------------------------------------------------
Query Block Name / Object Alias (identified by operation id):
-------------------------------------------------------------
1 - SEL$D26F4AE5
3 - SEL$D26F4AE5 / RMS_JK_POS_PORT@SEL$2
4 - SEL$D26F4AE5 / RMS_LOCALNET_POS@SEL$3
5 - SEL$D26F4AE5 / RMS_LOCALNET_POS@SEL$3
该 SQL 在 AWR 中属于 TOP SQL,执行计划走了嵌套循环,被驱动表走了 INDEX SKIP SCAN。在第 5 章中我们讲到,嵌套循环被驱动表只能走 INDEX UNIQUE SCAN 或者 INDEX RANGE SCAN。为什么嵌套循环被驱动表不能走 INDEX SKIP SCAN 呢?这是因为嵌套循环会传值,从驱动表传值给被驱动表,传值相当于过滤条件。有过滤条件但是走了 INDEX SKIP SCAN,很有可能是被驱动表连接列没包含在索引中,或者连接列在索引中放错了位置。
被驱动表连接列是 int_id,现在我们查看索引 RMS_LOCALNET_POS_PUI 具体情况。
SELECT DBMS_METADATA.GET_DDL('INDEX','RMS_LOCALNET_POS_PUI','HBRMW6') FROM DUAL;
CREATE INDEX "HBRMW6"."RMS_LOCALNET_POS_PUI" ON "HBRMW6"."RMS_LOCALNET_POS" ("PRO_TASK_ID", "STATEFLAG")
PCTFREE 10 INITRANS 2 MAXTRANS 255 COMPUTE STATISTICS
STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1
BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT)
TABLESPACE "HBRMW_TBS"
被驱动表索引中竟然没有包含连接列。这说明该执行计划是错误的。我们将连接列和过滤列组合起来创建组合索引,从而解决该 SQL 性能问题。