决定对哪些列创建索引往往是很难的。主键是被自动索引的,外键也应该创建索引,那其他的呢 ? 更困难的是决定删除某个可能不好的索引。每插入一条记录,所有索引都必须更新。如果一个被索引的列被更新,该索引也要被更新。在不引起用户查询出现一系列全表扫描或笛卡尔积连接的情况下,决定哪些索引需要被删除是很困难的,尤其是在需要调优的第三方应用程序代码不能改变的情况下。
不可视索引是该问题一个可能的解决方案,Oracle允许隐藏索引(使其不可见),但是索引上的维护工作还会继续(在任何DML操作:INSERT/UPDATE/DELETE期间),因为可能需要快速重新启用它。
可以通过下面的方法使得索引可见或不可见;
- ALTER INDEX idx1 INVISIBLE;
- ALTER INDEX idx1 VISIBLE;
- CREATE INDEX … INVISIBLE;
下面的查询显示了在表emp的deptno列上新建一个不可见索引,在接下来的查询中,我们看不到该索引:
SQL> conn scott/oracle
SQL> set line 200
SQL> select index_name,table_name,column_name from user_ind_columns;
INDEX_NAME TABLE_NAME COLUMN_NAME
-------------------- ------------------------------ ----------------------------------------
PK_DEPT DEPT DEPTNO
PK_EMP EMP EMPNO
SQL> create index emp_deptno_index on emp(deptno) invisible;
索引已创建。
SQL> select index_name,table_name,column_name from user_ind_columns;
INDEX_NAME TABLE_NAME COLUMN_NAME
-------------------- ------------------------------ ----------------------------------------
EMP_DEPTNO_INDEX EMP DEPTNO
PK_DEPT DEPT DEPTNO
PK_EMP EMP EMPNO
SQL>
SQL> set autot trace
SQL> select count(*) from scott.emp where deptno=30;
执行计划
----------------------------------------------------------
Plan hash value: 2083865914
---------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
---------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 3 | 3 (0)| 00:00:01 |
| 1 | SORT AGGREGATE | | 1 | 3 | | |
|* 2 | TABLE ACCESS FULL| EMP | 5 | 15 | 3 (0)| 00:00:01 |
---------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - filter("DEPTNO"=30)
统计信息
----------------------------------------------------------
1 recursive calls
0 db block gets
7 consistent gets
0 physical reads
0 redo size
527 bytes sent via SQL*Net to client
520 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
1 rows processed
SQL>
复制
虽然这时候索引是不可见的,但是可以使用提示来强制使用这个索引。从Oracle 11.2 版本开始就可以使用USE_INVISIBLE_INDEXES提示。
SQL> select /*+ use_invisible_indexes */ count(*) from scott.emp where deptno=30;
执行计划
----------------------------------------------------------
Plan hash value: 467672213
--------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 3 | 1 (0)| 00:00:01 |
| 1 | SORT AGGREGATE | | 1 | 3 | | |
|* 2 | INDEX RANGE SCAN| EMP_DEPTNO_INDEX | 5 | 15 | 1 (0)| 00:00:01 |
--------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - access("DEPTNO"=30)
统计信息
----------------------------------------------------------
1 recursive calls
0 db block gets
1 consistent gets
0 physical reads
0 redo size
527 bytes sent via SQL*Net to client
520 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
1 rows processed
SQL>
复制
如果把索引设置为可见状态,就不需要INDEX提示了。
SQL> alter index scott.EMP_DEPTNO_INDEX visible;
索引已更改。
SQL> select count(*) from scott.emp where deptno=30;
执行计划
----------------------------------------------------------
Plan hash value: 467672213
---------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 3 | 1 (0)| 00:00:01 |
| 1 | SORT AGGREGATE | | 1 | 3 | | |
|* 2 | INDEX RANGE SCAN| EMP_DEPTNO_INDEX | 5 | 15 | 1 (0)| 00:00:01 |
---------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - access("DEPTNO"=30)
统计信息
----------------------------------------------------------
222 recursive calls
0 db block gets
44 consistent gets
0 physical reads
0 redo size
527 bytes sent via SQL*Net to client
520 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
6 sorts (memory)
0 sorts (disk)
1 rows processed
SQL>
复制
在不将其变成不可见的前提下,也可以使用NO_INDEX提示关闭某个索引,看看除此之外是否会使用其他的索引(或者不使用索引)。换句话说,使用除了NO_INDEX中指定的索引之外的任何其他索引。
SQL> select /*+ no_index(e EMP_DEPTNO_INDEX) */ count(*) from scott.emp e where deptno=30;
执行计划
----------------------------------------------------------
Plan hash value: 2083865914
---------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
---------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 3 | 3 (0)| 00:00:01 |
| 1 | SORT AGGREGATE | | 1 | 3 | | |
|* 2 | TABLE ACCESS FULL| EMP | 5 | 15 | 3 (0)| 00:00:01 |
---------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - filter("DEPTNO"=30)
统计信息
----------------------------------------------------------
1 recursive calls
0 db block gets
7 consistent gets
0 physical reads
0 redo size
527 bytes sent via SQL*Net to client
520 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
1 rows processed
SQL>
复制
可以随时将这个索引设为不可见:
SQL> alter index scott.EMP_DEPTNO_INDEX invisible;
索引已更改。
SQL>
复制
可以通过USER_INDEXES或DBA_INDEXES视图来查看索引的可见性:
SQL> select index_name,visibility from dba_indexes where index_name='EMP_DEPTNO_INDEX';
INDEX_NAME VISIBILIT
-------------------- ---------
EMP_DEPTNO_INDEX INVISIBLE
SQL>
复制
总结
通过使用不可见索引,可以通过使用索引不可见的方法,临时“隐藏”它们来查询在没有它们时的性能。由于不可见索引依然被维护,因此如果需要的话,可以重新变为可见状态。
「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。
文章被以下合辑收录
评论
相关阅读
Oracle RAC 一键安装翻车?手把手教你如何排错!
Lucifer三思而后行
553次阅读
2025-04-15 17:24:06
【纯干货】Oracle 19C RU 19.27 发布,如何快速升级和安装?
Lucifer三思而后行
475次阅读
2025-04-18 14:18:38
Oracle SQL 执行计划分析与优化指南
Digital Observer
451次阅读
2025-04-01 11:08:44
XTTS跨版本迁移升级方案(11g to 19c RAC for Linux)
zwtian
450次阅读
2025-04-08 09:12:48
墨天轮个人数说知识点合集
JiekeXu
446次阅读
2025-04-01 15:56:03
【ORACLE】记录一些ORACLE的merge into语句的BUG
DarkAthena
439次阅读
2025-04-22 00:20:37
Oracle数据库一键巡检并生成HTML结果,免费脚本速来下载!
陈举超
415次阅读
2025-04-20 10:07:02
【ORACLE】你以为的真的是你以为的么?--ORA-38104: Columns referenced in the ON Clause cannot be updated
DarkAthena
414次阅读
2025-04-22 00:13:51
Oracle 19c RAC更换IP实战,运维必看!
szrsu
394次阅读
2025-04-08 23:57:08
【活动】分享你的压箱底干货文档,三篇解锁进阶奖励!
墨天轮编辑部
365次阅读
2025-04-17 17:02:24