关于不可见索引的学习(r3笔记74天)
不可见索引在日常工作中可能实用比较少,自己体验了一把,还是比较实用的功能,在平时的工作中不妨尝试一下。
我们来先体验一下,然后再细细的总结一下。
测试环境基于11gR2
> sqlplus -v
SQL*Plus: Release 11.2.0.2.0 Production
我们先来创建一个表来看看,然后创建一个不可见索引,来看看索引的访问情况。
create table t as select *from dba_objects where object_id is not null and rownum<100000;
我们随机抽取5条数据,后续的查询都会基于里面的1条数据来做说明。
select *from (select object_id from t order by dbms_random.value()) where rownum<5;
OBJECT_ID
----------
9445
4672
5048
4096
打开debug,来看看sql语句的执行情况。
set autot trace exp stat
我们选取了object_id为9445的记录。在没有索引的情况下,看看执行情况,好做比对。
select *from t where object_id=9445 ;
Execution Plan
----------------------------------------------------------
Plan hash value: 1601196873
--------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 116 | 24012 | 26 (0)| 00:00:01 |
|* 1 | TABLE ACCESS FULL| T | 116 | 24012 | 26 (0)| 00:00:01 |
--------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter("OBJECT_ID"=9445)
Statistics
----------------------------------------------------------
18 recursive calls
0 db block gets
177 consistent gets
0 physical reads
0 redo size
1632 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
上面的语句毫无疑问走了全表扫描,因为我们还没有创建索引。
我们来创建一个唯一性索引,来在查询中启用一下索引,这个时候索引还是可见的。
create unique index inx_t on t(object_id) ;
SQL> select *from t where object_id=9445;
Execution Plan
----------------------------------------------------------
Plan hash value: 1855406669
-------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 207 | 1 (0)| 00:00:01 |
| 1 | TABLE ACCESS BY INDEX ROWID| T | 1 | 207 | 1 (0)| 00:00:01 |
|* 2 | INDEX UNIQUE SCAN | INX_T | 1 | | 1 (0)| 00:00:01 |
-------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - access("OBJECT_ID"=9445)
Statistics
----------------------------------------------------------
1 recursive calls
0 db block gets
3 consistent gets
1 physical reads
0 redo size
1499 bytes sent via SQL*Net to client
509 bytes received via SQL*Net from client
1 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
1 rows processed
这个时候一切都没有什么特别之处。
我们来尝试下面的步骤。把索引改为不可见索引,或者我们删除已经存在的索引,然后重建一个不可见索引。
--删除,重建索引
drop index inx_t;
create unique index inx_t on t(object_id) invisible;
--修改索引属性,改为不可见
alter index inx_t invisible;
然后再次尝试运行同样的sql语句。看看是否索引能够正常启用。
select *from t where object_id=9445;
Execution Plan
----------------------------------------------------------
Plan hash value: 1601196873
--------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 116 | 24012 | 26 (0)| 00:00:01 |
|* 1 | TABLE ACCESS FULL| T | 116 | 24012 | 26 (0)| 00:00:01 |
--------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter("OBJECT_ID"=9445)
Statistics
----------------------------------------------------------
9 recursive calls
0 db block gets
139 consistent gets
0 physical reads
0 redo size
1632 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
这个时候索引没有启用,感觉就跟删除了一样。其实在dml操作中还是会有消耗和正常的索引是一样的,只是在优化器中对这个索引不可见。
我们来使用hint看看是否能够正常启用。
select /*+index(t inx_t)*/ *from t where object_id=9445;
SQL> select /*+index(t inx_t)*/ *from t where object_id=9445;
Execution Plan
----------------------------------------------------------
Plan hash value: 1601196873
--------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 116 | 24012 | 26 (0)| 00:00:01 |
|* 1 | TABLE ACCESS FULL| T | 116 | 24012 | 26 (0)| 00:00:01 |
--------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter("OBJECT_ID"=9445)
Statistics
----------------------------------------------------------
1 recursive calls
0 db block gets
135 consistent gets
0 physical reads
0 redo size
1632 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
结果尽管使用了hint,但是还是不买账,依旧没有反应。
我们来看看怎么使用不可见索引。
默认在数据库参数中,有一个参数optimizer_use_invisible_indexes,默认是不会启用不可见索引的。我们可以从session级别,system级别进行设定。一般都会在session级启用,来查看索引是否能够达到预期目标,然后再决定是否设定为可见。
SQL> show parameter vis
NAME TYPE VALUE
------------------------------------ --------------------------------- ------------------------------
optimizer_use_invisible_indexes boolean FALSE
我们在session级启用。
alter session set "optimizer_use_invisible_indexes"=true;
然后执行同样的语句。可以看到索引能够正常启用了。
select *from t where object_id=9445;
Execution Plan
----------------------------------------------------------
Plan hash value: 1855406669
-------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 207 | 1 (0)| 00:00:01 |
| 1 | TABLE ACCESS BY INDEX ROWID| T | 1 | 207 | 1 (0)| 00:00:01 |
|* 2 | INDEX UNIQUE SCAN | INX_T | 1 | | 1 (0)| 00:00:01 |
-------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - access("OBJECT_ID"=9445)
Statistics
----------------------------------------------------------
0 recursive calls
0 db block gets
3 consistent gets
0 physical reads
0 redo size
1499 bytes sent via SQL*Net to client
509 bytes received via SQL*Net from client
1 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
1 rows processed
我们恢复原值。来看看,又开始走了全表扫描。
alter session set "optimizer_use_invisible_indexes"=false;
select *from t where object_id=9445;
Execution Plan
----------------------------------------------------------
Plan hash value: 1601196873
--------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 116 | 24012 | 26 (0)| 00:00:01 |
|* 1 | TABLE ACCESS FULL| T | 116 | 24012 | 26 (0)| 00:00:01 |
--------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter("OBJECT_ID"=9445)
Statistics
----------------------------------------------------------
1 recursive calls
0 db block gets
135 consistent gets
0 physical reads
0 redo size
1632 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
如果在session级别确认了索引能够极大的提高效率,可以修改索引的属性,把索引置为可见状态。
我们设置索引为可见,看看语句的执行情况,索引又能够正常启用了。
alter index inx_t visible;
select *from t where object_id=9445;
Execution Plan
----------------------------------------------------------
Plan hash value: 1855406669
-------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 207 | 1 (0)| 00:00:01 |
| 1 | TABLE ACCESS BY INDEX ROWID| T | 1 | 207 | 1 (0)| 00:00:01 |
|* 2 | INDEX UNIQUE SCAN | INX_T | 1 | | 1 (0)| 00:00:01 |
-------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - access("OBJECT_ID"=9445)
Statistics
----------------------------------------------------------
0 recursive calls
0 db block gets
3 consistent gets
0 physical reads
0 redo size
1499 bytes sent via SQL*Net to client
509 bytes received via SQL*Net from client
1 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
1 rows processed
大体的测试就这么多,还有几个问题需要考虑一下,如果不可见索引的使用这么灵活。我们可以根据不可见索引来评估一条sql语句的执行效率情况,那么是否在高可用场景中使用呢。
我们可以做一个简单的测试来说明,在创建不可见索引的时候,是否还存在着锁,这样就能够判断是否适用于高可用场景了。
我们删除表,然后创建新的表,表中的数据尽量多一些,让创建索引的时间稍微长一点。
drop table t;
create table t as select *from dba_objects where rownum<5000000;
create index inx_t on t(object_id) invisible;
然后我们查看锁的情况。可以看到在创建不可见索引的过程中还是存在着锁。在线业务中还是会有影响的。
SID_SERIAL ORACLE_USE OBJECT_NAME LOGON_TIM SEC_WAIT OSUSER MACHINE PROGRAM STATE STATUS LOCK_ MODE_HELD
------------ ---------- --------------- --------- -------- ---------- ---------- -------------------- ---------- ---------- ----- ----------
763,33293 N1 OBJ$ 04-DEC-14 0 testuser testdb sqlplus@xx (TNS V1-V3) WAITED SHORT TIME ACTIVE DML Row-X (SX)
763,33293 N1 T 04-DEC-14 0 testuser testdb sqlplus@xx (TNS V1-V3) WAITED SHORT TIME ACTIVE DML Share
763,33293 N1 T 04-DEC-14 0 testuser testdb sqlplus@xx (TNS V1-V3) WAITED SHORT TIME ACTIVE DL Row-X (SX)
763,33293 N1 T 04-DEC-14 0 testuser testdb sqlplus@xx (TNS V1-V3) WAITED SHORT TIME ACTIVE DL Row-X (SX)
不可见索引在数据字典视图中和普通索引没有太大的区别,都有对应的索引段,这是在索引对应的数据字典中有一个字段visibility标明索引是否可见。
SQL> select segment_name,segment_type,blocks from user_segments where segment_name='INX_T'
SEGMENT_NAME SEGMENT_TYPE BLOCKS
-------------------- ------------------ ----------
INX_T INDEX 10240
SQL> SELECT INDEX_NAME,VISIBILITY FROM USER_INDEXES WHERE INDEX_NAME='INX_T';
INDEX_NAME VISIBILIT
------------------------------ ---------
INX_T INVISIBLE
- .NET4.0的可扩展缓存系统
- 让WordPress 在RSS 中Feed 截断文字输出
- [C#1] 11-接口
- jquery 标签中的属性操作
- 使用MongoDB存储访问者信息
- 解决WordPress 打开Feed页面“This page contains the following errors…”的问题
- jquery表单属性筛选元素
- [C#1] 10-事件
- Windows 7的VPC虚拟机自动不与主机时间同步的解决办法
- [C#1] 9-委托
- jquery基本选择器
- rainyday.js——超逼真全屏雨滴模拟插件
- [C#1] 8-数组
- ASP.NET MVC2 数据模型验证类库:MVC Foolproof Validation
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 07 . Nginx常用模块及案例
- 08 . Nginx状态码
- 09 . Nginx配置LNMP和LNMT架构
- 01 . Mysql简介及部署
- jquery点击按钮,添加一行input输入框
- 02 . Mysql基础操作及增删改查
- 03 . MysSQL权限和备份
- 04 . Mysql主从复制和Mycat读写分离
- 02 . Python之数据类型
- 05 . k8s实战之部署PHP/JAVA网站
- 拖不得了,Android11真的来了,最全适配实践指南奉上
- 03 . Python入门之运算符
- 04 . Python入门之条件语句
- vue-element的select下拉框赋值
- 女儿拿着小天才电话手表问我App启动流程