有如下执行计划(从 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 innerjoin (select int_id,zh_label from RMS_LOCALNET_POS wherestateflag=:"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")) anda.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$D26F4AE53 - SEL$D26F4AE5 / RMS_JK_POS_PORT@SEL$24 - SEL$D26F4AE5 / RMS_LOCALNET_POS@SEL$35 - 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 STATISTICSSTORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT)TABLESPACE "HBRMW_TBS"
被驱动表索引中竟然没有包含连接列。这说明该执行计划是错误的。我们将连接列和过滤列组合起来创建组合索引,从而解决该 SQL 性能问题。
