os: centos 7.4
db: oracle 11.2.0.4
oracle 从 11g 开始提供 invisible index 索引,这对线上系统添加索引引起的性能异常提供了可控的方法。
-- drop table tmp_t0 purge;
create table tmp_t0
as
select *
from dba_objects
where 1=1
;
insert into tmp_t0
select *
from tmp_t0
;
insert into tmp_t0
select *
from tmp_t0
;
insert into tmp_t0
select *
from tmp_t0
;
commit;
create index IND_TMP_T0_N1 on tmp_t0(object_id) online ;
alter index IND_TMP_T0_N1 visible;
alter index IND_TMP_T0_N1 invisible;
收集统计信息
BEGIN
dbms_stats.gather_table_stats(
ownname=> 'scott' ,
tabname=> 'tmp_t0',
--partname=> 'p1',
estimate_percent=> 100 ,
cascade=> TRUE,
--method_opt=>'for all columns size 1 ',
--method_opt=>'for all columns size repeat ',
method_opt=>'for all indexed columns size skewonly ',
no_invalidate=>FALSE,
granularity=>'AUTO',
degree=>2
);
END ;
optimizer_use_invisible_indexes 参数控制优化器是否使用 invisible 索引,默认为 false
SQL> show parameter optimizer_use_invisible_indexes;
NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
optimizer_use_invisible_indexes boolean FALSE
SQL> set lines 200;
SQL> set pages 200;
SQL>
SQL>
SQL> set autotrace traceonly;
SQL> alter session set optimizer_use_invisible_indexes = false;
SQL> select *
from TMP_T0 t
where 1=1
and t.object_id=442350
;
Execution Plan
----------------------------------------------------------
Plan hash value: 1652152861
----------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
----------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 32 | 3168 | 137 (0)| 00:00:02 |
|* 1 | TABLE ACCESS FULL| TMP_T0 | 32 | 3168 | 137 (0)| 00:00:02 |
----------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter("T"."OBJECT_ID"=442350)
session 级别启用 invisible index,可以看到执行计划使用了 IND_TMP_T0_N1
SQL> alter session set optimizer_use_invisible_indexes = true;
SQL> select *
from TMP_T0 t
where 1=1
and t.object_id=442350
;
Execution Plan
----------------------------------------------------------
Plan hash value: 1276431902
---------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
---------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 32 | 3168 | 33 (0)| 00:00:01 |
| 1 | TABLE ACCESS BY INDEX ROWID| TMP_T0 | 32 | 3168 | 33 (0)| 00:00:01 |
|* 2 | INDEX RANGE SCAN | IND_TMP_T0_N1 | 32 | | 1 (0)| 00:00:01 |
---------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - access("T"."OBJECT_ID"=442350)
能否在 sql 语句级通过 hint 控制?
SQL> alter session set optimizer_use_invisible_indexes = false;
SQL> select/*+ opt_param('optimizer_use_invisible_indexes', 'true') */ *
from TMP_T0 t
where 1=1
and t.object_id=442350
;
Execution Plan
----------------------------------------------------------
Plan hash value: 1652152861
----------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
----------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 32 | 3168 | 137 (0)| 00:00:02 |
|* 1 | TABLE ACCESS FULL| TMP_T0 | 32 | 3168 | 137 (0)| 00:00:02 |
----------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter("T"."OBJECT_ID"=442350)
SQL> select/*+ opt_param('optimizer_use_invisible_indexes', 'true') index(t IND_TMP_T0_N1) */ *
from TMP_T0 t
where 1=1
and t.object_id=442350
;
Execution Plan
----------------------------------------------------------
Plan hash value: 1652152861
----------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
----------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 32 | 3168 | 137 (0)| 00:00:02 |
|* 1 | TABLE ACCESS FULL| TMP_T0 | 32 | 3168 | 137 (0)| 00:00:02 |
----------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter("T"."OBJECT_ID"=442350)
看上去无法通过 hint 控制使用 invisible index,只能在 system 级别和 system 级别参数来启用禁用不可见索引。