您的位置:首页 > 其它

全面解析11GR2中的BTree索引(含视频)

2013-11-07 12:12 239 查看
案例讨论 数据泵日常应用

http://www.itpub.net/thread-1821915-1-1.html

本文的目录如下:

第01部分-(t1表) 判断用哪个列建立索引——列的选择度是选择索引列的依据之一

第02部分-(t1表) 建索引之前测试新索引将对查询计划有何影响——虚拟索引(nosegment index)

第03部分-(t1表) 普通B树索引

第04部分-(t1表) 唯一索引

第05部分-(t1表) 反转键索引

第06部分-(t1表) 复合索引(也叫级联索引)

第07部分-(t2表) 函数索引

第08部分-(d表+e表) 簇索引

第09部分-(t1_part表) 本地分区索引(较全局索引,更易维护最流行)

第10部分-(t3表) 键压缩索引

第11部分-补充: 索引的基本维护命令

第01部分-(t1表)判断用哪个列建立索引——列的选择度是选择索引列的依据之一

本帖最后由 zcs0237 于 2013-7-30 20:22 编辑

01.01-在创建索引前:手工评估列的选择性

-选择度=(不同值的数目÷行的总数)=索引列有9k不同值÷表记录有1w条=0.9。
-索引的选择性越接近于1,这个索引的效率就越高。
-CBO一般不会使用选择性不好的索引。
-常用于频繁搜索条件的列选择可作为建立索引的列
-常用于对数据排序顺序的列可作为建立索引的列。
一、准备工作:创建测试表、插入1百万条以上记录
SYS@zcs11g> set sqlprompt "_user'@zcs'11g> "
set timing off
set autotrace off
drop table t1 purge;
create table t1(id number,owner varchar2(9), c3 varchar2(30));
begin
for i in 1.. 2000444 loop
insert into t1 values(i,'zzz','z'||i);
end loop;
commit;
end;
/
二、手工评估列的选择性
SYS@zcs11g> set pagesize 0
select '--ID=',ceil(100*count(distinct ID)/count(*))||'%',
'owner=',ceil(100*count(distinct owner)/count(*))||'%',
'c3=',ceil(100*count(distinct c3)/count(*))||'%' from t1;
--ID=100% owner=1% c3=100%

01.02-在创建索引后:收集统计信息以判断列的选择度(如果将'for
all indexed columns size 2'中的数字改大,录视频浪费时间)

SYS@zcs11g> create index t1_idx on t1(id,owner,c3);
execute dbms_stats.gather_table_stats(ownname=>'SYS',tabname=>'T1',method_opt=>'for all indexed columns size 2',cascade=>TRUE);
select '--',a.column_name,ceil(100*a.num_distinct/b.num_rows)||'%'

from user_tab_columns a,user_tables b where a.table_name=b.table_name and a.table_name='T1';

-- ID 100%
-- OWNER 1%
-- C3 99%
SYS@zcs11g> drop index t1_idx;

第02部分-(t1表)建索引之前测试新索引将对查询计划有何影响——虚拟索引(nosegment)

本帖最后由 zcs0237 于 2013-7-29 20:39 编辑

02.01-创建并验证无段索引

一、创建虚拟索引
SYS@zcs11g> create index t1_idxno on t1(id) nosegment;
二、无段索引没有物理段
SYS@zcs11g> select '--',index_name from user_indexes where table_name='T1';

-- no rows selected --看不到名为t1_idxno的索引
三、表上确实定义了索引

SYS@zcs11g> col INDEX_NAME for a22
col COLUMN_NAME for a22
set linesize 999
set pagesize 0
select '--',index_name,column_name from user_ind_columns where table_name='T1';

-- T1_IDXNO ID

02.02-用无段索引评估创建索引的必要性


一、强制session使用虚拟索引
SYS@zcs11g> alter session set "_use_nosegment_indexes" = true;
二、用无段索引对执行计划进行评估:执行计划中有“INDEX RANGE SCAN”
SYS@zcs11g> set pagesize 0
set linesize 999
set autotrace on explain
select '--',ID,OWNER,C3 from t1 where id=6666;

-- 6666 zzz z6666
----------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
----------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 17 | 2 (0)| 00:00:01 |
| 1 | TABLE ACCESS BY INDEX ROWID| T1 | 1 | 17 | 2 (0)| 00:00:01 |
|* 2 |
INDEX RANGE SCAN | T1_IDXNO | 1 | | 1 (0)| 00:00:01 |
----------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - access("ID"=6666)
三、清理现场
SYS@zcs11g> drop index t1_idxno;
set autotrace off

第03部分-(t1表)普通B树索引

本帖最后由 zcs0237 于 2013-7-29 18:53 编辑

多用于oltp系统,从高基数列检索范围小于表的10%时提供了最好的性能。
03.01-无任何索引=00.21s=Table Access Full+Sort Order BY=CPU COST是1731

一、收集统计信息
SYS@zcs11g> execute dbms_stats.gather_table_stats(ownname=>'SYS',tabname=>'T1',method_opt=>'for all indexed columns size 2',cascade=>TRUE);
二、连查几遍记下稳定时的值(原因:buffer cache+dict cache+lib cache)
SYS@zcs11g> alter system flush buffer_cache;
alter system flush shared_pool;
set timing on
set linesize 999
set autotrace on explain
select * from t1 where owner='zzz' and id > 2000000 order by id;
/* 444 rows selected.
Elapsed: 00:00:00.21
---------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
---------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 17 |
1731 (1)| 00:00:21 |
| 1 |
SORT ORDER BY | | 1 | 17 | 1731 (1)| 00:00:21 |
|* 2 |
TABLE ACCESS FULL| T1 | 1 | 17 | 1730 (1)| 00:00:21 |
---------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - filter("ID">2000000 AND "OWNER"='zzz') */

03.02-有普通索引=00.04s=Index Range Scan+Table Access By Index Rowid=Sort Order By被省掉CPU
Cost降为4


一、建Normal索引并查看相关信息
1、创建normal索引
SYS@zcs11g> set autotrace off
create index t1_idx on t1(owner,id);
2、查看完整的索引定义语句
SYS@zcs11g> set long 9999
select dbms_metadata.get_ddl('INDEX', 'T1_IDX') from dual;
select '--',dbms_metadata.get_ddl('INDEX', 'T1_IDX') from dual;
--

CREATE INDEX "SYS"."T1_IDX" ON "SYS"."T1" ("OWNER", "ID")
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 DE
FAULT CELL_FLASH_CACHE DEFAULT)
TABLESPACE "SYSTEM"
3、列出新生成的索引
SYS@zcs11g> set pagesize 333
col funcidx_status for a22
select index_name,funcidx_status,index_type,status FROM dba_indexes where table_name='T1' and owner='SYS';

/* INDEX_NAME FUNCIDX_STATUS INDEX_TYPE STATUS
------------------- ---------------------- ------------------------- --------
T1_IDX NORMAL VALID*/
二、收集统计信息
SYS@zcs11g> execute dbms_stats.gather_table_stats(ownname=>'SYS',tabname=>'T1',method_opt=>'for all indexed columns size 2',cascade=>TRUE);
三、连查几遍记下稳定时的值(原因:buffer cache+dict cache+lib cache)
SYS@zcs11g> alter system flush buffer_cache;
alter system flush shared_pool;
set timing on
set linesize 999
set autotrace on explain
select * from t1 where owner='zzz' and id > 2000000 order by id;

/*444 rows selected.
Elapsed: 00:00:00.04
--------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 17 | 4 (0)| 00:00:01 |
| 1 |
TABLE ACCESS BY INDEX ROWID| T1 | 1 | 17 | 4 (0)| 00:00:01 |
|* 2 |
INDEX RANGE SCAN | T1_IDX | 1 | | 3 (0)| 00:00:01 |
--------------------------------------------------------------------------------------
2 - access("OWNER"='zzz' AND "ID">2000000 AND "ID" IS NOT NULL)
*/

03.03-有普通索引+仅查索引列=00.04s=Index
Range Scan=省去回表,且CPU COST降3


一、连查几遍记下稳定时的值(原因:buffer cache+dict cache+lib cache)
SYS@zcs11g> alter system flush buffer_cache;
alter system flush shared_pool;
set timing on
set linesize 999
set autotrace on explain
select owner,id from t1 where owner='zzz' and id > 2000000 order by id;
/

/*
Elapsed: 00:00:00.05
---------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
---------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 10 | 3 (0)| 00:00:01 |
|* 1 | INDEX RANGE SCAN| T1_IDX | 1 | 10 | 3 (0)| 00:00:01 |
---------------------------------------------------------------------------
1 - access("OWNER"='zzz' AND "ID">2000000 AND "ID" IS NOT NULL) */
二、清理现场
SYS@zcs11g> set autotrace off
drop index t1_idx;

第04部分-(t1表)唯一索引

本帖最后由 zcs0237 于 2013-8-1 16:28 编辑

04.01-补充:列出系统中的唯一索引和非唯一索引

一、列出当前数据库中支持唯一索引特性的索引类型
SYS@zcs11g> set sqlprompt "_user'@zcs'11g> "
select distinct INDEX_TYPE from dba_indexes where uniqueness='UNIQUE';

--IOT – TOP --B树索引.索引组织表
--LOB --建表时自动为lob字段建segment_type=LOBSEGMENT+LOBINDEX的两个段
--FUNCTION-BASED NORMAL --B树索引.函数索引(含降序索引)
--NORMAL --B树索引.升序索引
--CLUSTER --B树索引.聚簇索引
二、列出当前数据库中存在非唯一类索引
SYS@zcs11g> select distinct INDEX_TYPE from dba_indexes where uniqueness='NONUNIQUE';

--FUNCTION-BASED NORMAL --B树索引.函数索引(含降序索引)
--FUNCTION-BASED DOMAIN --域索引.函数索引
--BITMAP --位图索引
--NORMAL --B树索引. 升序索引
--DOMAIN --域索引

04.02-证明:唯一索引各种特性


一、不允许在有重复值的列上建唯一索引
1、不允许在有重复值的列上建唯一索引
SYS@zcs11g> create unique index t1_uniq on t1(owner);

--ORA-01452: cannot CREATE UNIQUE INDEX; duplicate keys found
2、在没有重复值的列上可以创建唯一索引
SYS@zcs11g> create unique index t1_uniq on t1(id);
3、唯一索引是索引
SYS@zcs11g> set pagesize 0
col index_name for a9
col index_type for a9
col uniqueness for a9
select '--',index_name,index_type,uniqueness from user_indexes where table_name='T1';

-- T1_UNIQ NORMAL UNIQUE
4、查看索引列
SYS@zcs11g> col index_name for a9
col column_name for a9
select '--',index_name,column_name from user_ind_columns where table_name ='T1';

-- T1_UNIQ ID
5、唯一索引不是约束
SYS@zcs11g> select CONSTRAINT_NAME from user_constraints where table_name='T1';

--no rows selected
二、不允许向有唯一索引的表中insert/update重复键值的数据
SYS@zcs11g> select '--',id from t1 where rownum=1;

-- 1
SYS@zcs11g> insert into t1 values(1, 'aaa', 'bbb');

-- ORA-00001: unique constraint (SYS.T1_UNIQ) violated
三、唯一性索引列允许空值
SYS@zcs11g> insert into t1 values(null,'aaa', 'bbb');
select '--',count(*) from t1 where id is null;

-- 1
四、一个表中可以有多个唯一性索引
SYS@zcs11g> create unique index t1_uniqc3 on t1(c3);
set pagesize 0
col index_name for a9
col column_name for a9
select '--',index_name,column_name from user_ind_columns where table_name ='T1';

-- T1_UNIQC3 C3
-- T1_UNIQ ID
五、唯一性索引在unusable状态不允许插入数据
1、禁用索引
SYS@zcs11g> alter index t1_uniq unusable;
alter index t1_uniqc3 unusable;
select '--',index_name , status from dba_indexes where table_name='T1';

-- T1_UNIQ UNUSABLE
-- T1_UNIQC3 UNUSABLE
2、插入数据:失败
SYS@zcs11g> insert into t1 values(300000, 'qz','zq');

-- ORA-01502: index 'SYS.T1_UNIQ' or partition of such index is in unusable state
3、删除unusable索引
SYS@zcs11g> drop index t1_uniq;
drop index t1_uniqc3;

04.03-证明:唯一索引>普通索引

一、创建唯一索引和普通索引
SYS@zcs11g> set autotrace off
create unique index t1_uniq on t1(id);
create index t1_normal on t1(c3);
select '--',index_name , status,UNIQUENESS from dba_indexes where table_name='T1';

-- T1_UNIQ VALID UNIQUE
-- T1_NORMAL VALID NONUNIQUE
二、收集统计信息
SYS@zcs11g> execute dbms_stats.gather_table_stats(ownname=>'SYS',tabname=>'T1',method_opt=>'for all indexed columns size 2',cascade=>TRUE);
三、证明:唯一索引>普通索引——where c3='z888'and id=888执行计划中选择了id列的索引T1_UNIQ
SYS@zcs11g> alter system flush buffer_cache;
alter system flush shared_pool;
set linesize 999
set timing on
set autotrace on explain
select * from t1 where c3='z888'and id=888;

/* 888 zzz z888
Elapsed: 00:00:00.02
---------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
---------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 17 | 3 (0)| 00:00:01 |
|* 1 | TABLE ACCESS BY INDEX ROWID| T1 | 1 | 17 | 3 (0)| 00:00:01 |
|* 2 | INDEX UNIQUE SCAN |
T1_UNIQ | 1 | | 2 (0)| 00:00:01 |
---------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter("C3"='z888')
2 - access("ID"=888) */
三、清理现场
SYS@zcs11g> set autotrace off
drop index t1_uniq;
drop index t1_normal;
select '--',index_name , status,UNIQUENESS from dba_indexes where table_name='T1';

-- T1_UNIQ VALID UNIQUE
-- T1_NORMAL VALID NONUNIQUE

04.04-建立主键约束时自动建立的唯一索引:删除时也会自动删除自动创建的唯一索引

主键可以作为外键被引用,普通唯一索引键不能作为外键被引用。
一、有重复值时不允许添加主键
SYS@zcs11g> alter table t1 drop constraint t1_pk;
insert into t1 values(1,'z300000','z3000000');
alter table t1 add constraint t1_pk primary key(id);

--ORA-02437: cannot validate (SYS.T1_PK) - primary key violated
SYS@zcs11g> delete from t1 a where rowid !=(select max(rowid) from t1 b where a.id=b.id);

--1 row deleted.
二、有空值时不允许添加主键约束
SYS@zcs11g> insert into t1 values(null,'z300000','z3000000');
alter table t1 add constraint t1_pk primary key(id);

--ORA-01449: column contains NULL values; cannot alter to NOT NULL
SYS@zcs11g> delete from t1 where id is null;
alter table t1 add constraint t1_pk primary key(id);
三、有主键约束不允许空值
SYS@zcs11g> insert into t1 values(null,'z300000','z3000000');

--ORA-01400: cannot insert NULL into ("SYS"."T1"."ID")
四、有主键约束不允许重复
SYS@zcs11g> insert into t1 values(1,'z300000','z3000000');

--ORA-00001: unique constraint (SYS.T1_PK) violated
SYS@zcs11g> select '--',constraint_name,column_name from user_cons_columns where table_name='T1';

-- T1_PK ID --查看约束列
SYS@zcs11g> select '--'||i.index_name,c.constraint_type from user_indexes i,user_constraints c where i.index_name=c.constraint_name and i.index_name='T1_PK';

--T1_PK P --查看约束类型
五、清理现场(以下方法删除表中已有的主键约束及自动创建的索引)
SYS@zcs11g> select '--'||index_name,index_type,uniqueness from user_indexes where table_name='T1';

--T1_PK NORMAL UNIQUE --查看创建主键时自动创建的唯一索引
SYS@zcs11g> alter table t1 drop constraint t1_pk;
select '--',constraint_name,column_name from user_cons_columns where table_name='T1';

-- no rows selected

04.05-建立唯一约束时自动建立的唯一索引


一、建立Unique constraint
SYS@zcs11g> alter table t1 add constraint t1_uk unique(id);
set pagesize 0
select '--'||i.index_name,c.constraint_type from user_indexes i,user_constraints c where i.index_name=c.constraint_name and i.index_name='T1_UK';

--T1_UK U
二、查看建立Unique constraint时自动建立的唯一索引
SYS@zcs11g> select '--'||index_name,index_type,uniqueness from user_indexes where table_name='T1';

--T1_UK NORMAL UNIQUE
三、查看索引列
SYS@zcs11g> col index_name for a9
col column_name for a9
select '--',index_name,column_name from user_ind_columns where table_name ='T1';

-- T1_UK ID
四、清理现场(以下方法删除主键保留自动创建的索引)



2013-8-1 16:28 上传
下载附件
(29.88 KB)

SYS@zcs11g> alter table t1 drop constraint t1_uk cascade keep index;
select '--',index_name from user_indexes where table_name='T1';

-- T1_UK

SYS@zcs11g> drop index t1_uk;

select '--',index_name,column_name from user_ind_columns where table_name ='T1';

--no rows selected

第05部分--(t1表)反转键索引——主要用于主键与外键的连接,不支持范围扫描

本帖最后由 zcs0237 于 2013-8-7 20:42 编辑

05.01-反转键索引的基本特征——主要提高更新的性能和减少热点块减少叶块竞争

一、主键索引递增的情况下普通B树的总是向索引空间最后面插入记录



2013-7-27 20:17 上传
下载附件
(69.8 KB)

主键是有索引的,insert产生块竞争,因此相邻的索引记录就可能存在于同一数据块中,引起数据块竞争,导致性能下降。尤其是在RAC环境下可能会更严重。

二、反转了b*tree索引列值的每个字节的位置反转,使索引条目分配更均匀
1、同时要执行大量的有序载入,就可以在表中有严格排序的列上使用反转键索引。
2、反转后原来相邻的主键在索引中就分散到不同的数据块中,上面普通索引的问题就解决了。
3、多用于pk,fk的join,提高更新的性能和减少热点块。

05.02-实例演示反向键索引不支持范围扫描(主要用于主键与外键的连接)

一、创建反键索引
SYS@zcs11g> set autotrace off
drop index t1_idx;
create index t1_idx on t1(owner,id) reverse;
alter index t1_idx rename to t1_rev;
二、列出新生成的索引——INDEX_TYPE= NORMAL/REV
SYS@zcs11g> set pagesize 333
col funcidx_status for a16
col index_name for a16
col index_type for a16
select '--',index_name,funcidx_status,index_type,status FROM user_indexes where table_name='T1';

-- INDEX_NAME FUNCIDX_STATUS INDEX_TYPE STATUS
-- ---------------- ---------------- ---------------- --------
-- T1_REV NORMAL/REV VALID
三、收集统计信息
SYS@zcs11g> execute dbms_stats.gather_table_stats(ownname=>'SYS',tabname=>'T1',method_opt=>'for all indexed columns size 2',cascade=>TRUE);
四、反转键不适用于范围扫描
SYS@zcs11g> alter system flush buffer_cache;
alter system flush shared_pool;
set timing on
set linesize 999
set autotrace on explain
select * from t1 where owner='zzz' and id > 2000000 order by id;

/*---------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
---------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 437 | 7429 | 1456 (5)| 00:00:18 |
| 1 | SORT ORDER BY | | 437 | 7429 | 1456 (5)| 00:00:18 |
|* 2 |
TABLE ACCESS FULL| T1 | 437 | 7429 | 1455 (5)| 00:00:18 |
---------------------------------------------------------------------------*/

05.03-修改为非反向键普通索引


SYS@zcs11g> alter index t1_rev rebuild noreverse;
set autotrace off
select '--',index_name,funcidx_status,index_type,status FROM user_indexes where table_name='T1';

-- INDEX_NAME FUNCIDX_STATUS INDEX_TYPE STATUS
-- ---------------- ---------------- ---------------- --------
-- T1_REV NORMAL VALID

第06部分--(t1表)复合索引也叫级联索引

本帖最后由 zcs0237 于 2013-7-29 18:52 编辑

1、当两个或多个列经常一起出现在where条件中时,则在这些列上同时创建组合索引
2、组合索引中列的顺序是任意的,也无需相邻。
3、但是建议将最频繁访问的列放在列表的最前面
4、最多16个字段组合在一起,组成一个索引。
5、在同一张表上可以有多个索引,但是要求列的组合必须不同。
06.01-创建Concatenated Indexes

SYS@zcs10G> set autotrace off;
drop index t1_idx;
create index t1_idx on t1(id,owner);
analyze table t1 compute statistics for table for all indexes for all indexed columns;
col index_name for a9
col column_name for a9
select '--',index_name,column_name from user_ind_columns where table_name ='T1';
-- T1_IDX OWNER
-- T1_IDX ID

06.02-对索引进行范围匹配或对非唯一索引进行单一匹配时采用Index Range Scan


SYS@zcs10G> alter system flush buffer_cache;
alter system flush shared_pool;
set autotrace on explain;
set linesize 999
select * from t1 where id=2000000 and owner= 'zzz ';
--对唯一索引显示为index unique scan
/* --------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 445 | 7565 | 6 (0)| 00:00:01 |
| 1 | TABLE ACCESS BY INDEX ROWID| T1 | 445 | 7565 | 6 (0)| 00:00:01 |
|* 2 |
INDEX RANGE SCAN | T1_IDX | 445 | | 4 (0)| 00:00:01 |
-------------------------------------------------------------------------------------- */

06.03-查询中没有使用前导列时可能使用index skip scan

SYS@zcs11g> select /*+index_ss(t1 t1_idx)*/* from t1 where owner='zzzz'; --数据不典型,加了hint执行计划中才显示出效果
--------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 17 | 2000K (1)| 06:40:11 |
| 1 | TABLE ACCESS BY INDEX ROWID| T1 | 1 | 17 | 2000K (1)| 06:40:11 |
|* 2 |
INDEX SKIP SCAN | T1_IDX | 1 | | 2000K (1)| 06:40:11 |
--------------------------------------------------------------------------------------

第07部分-(t2表)函数索引(索引列=函数运算后的列值,条件中包含函数时可以提高查询效

本帖最后由 zcs0237 于 2013-7-29 18:50 编辑

07.01-函数索引技术的使用不具有普遍意义

一、适用范围
1、一个函数索引只能解决这个函数在查询中存在的调用问题,换成另外一个函数调用则这个函数索引将会失效。

2、仅在WHERE条件语句中包含函数或表达式时时创建
函数包括:算数表达式、PL/SQL函数、程序包函数、SQL函数、用户自定义函数
3、必须使用基于成本的优化器,基于规则的优化器将被忽略。
二、如何启用
1、必须设置以下两个查询重写参数(默认已开启):
QUERY_REWRITE_INTEGRITY=TRUSTED
SCOTT@zcs11g> show parameter QUERY_REWRITE_ENABLED

--query_rewrite_enabled string TRUE
SCOTT@zcs11g> show parameter QUERY_REWRITE_INTEGRITY

--query_rewrite_integrity string enforced
2、未设置查询重写时需要使用/*+ INDEX(ic_index)*/ 提示

07.02-补充:让scott能使用autotrace


一、创建scott模式
$ cp scott.sql $ORACLE_HOME/rdbms/admin ;
cd $ORACLE_HOME/rdbms/admin ;
sqlplus / as sysdba
set sqlprompt "_user'@zcs'11g> "
--startup

start scott.sql
alter user scott identified by tiger;
alter user scott account unlock;
二、添加autotrace权限
SYS@zcs11g> conn / as sysdba
set echo on
drop role plustrace;
create role plustrace;
grant select on v_$sesstat to plustrace;
grant select on v_$statname to plustrace;
grant select on v_$mystat to plustrace;
grant plustrace to dba with admin option;
set echo off

SYS@zcs11g> grant dba to scott;
conn scott/tiger

show user

-- USER is "SCOTT"

07.03-有普通索引+查询条件包含函数——执行计划走全表扫描


一、创建普通索引
SCOTT@zcs11g> create table t2 as select * from emp;
set linesize 999
set pagesize 0
set autotrace off;
drop index t2_ename;
create index t2_ename on t2(ename) ;
select index_name,index_type,funcidx_status,status FROM user_indexes where table_name='T2';

-- EMP_ENAME NORMAL VALID

补充:Status of a function-based index
NULL - Index is not a function-based index
ENABLED - Function-based index is enabled
DISABLED - Function-based index is disabled
二、条件中包括函数——不走索引
SCOTT@zcs11g> alter system flush buffer_cache;
alter system flush shared_pool;
set pagesize 0
set linesize 999
set autotrace on explain;
select '--',empno,ename ,sal from t2 where upper(ename)='ALLEN';
/

/*--------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 33 | 3 (0)| 00:00:01 |
|* 1 |
TABLE ACCESS FULL| T2 | 1 | 33 | 3 (0)| 00:00:01 |
--------------------------------------------------------------------------*/

07.04-有函数索引+查询条件包含函数——执行计划走函数索引


一、建立函数索引(语法:CREATE INDEX index ON table(FUNCTION(column)))
SCOTT@zcs11g> set linesize 999
set pagesize 0
set autotrace off;
drop index t2_ename;
create index t2_ename on t2(upper(ename)) ;
select '--',index_name,index_type,funcidx_status,status FROM user_indexes where table_name='T2';

-- T2_ENAME FUNCTION-BASED NORMAL ENABLED VALID

补充:Status of a function-based index
NULL - Index is not a function-based index
ENABLED - Function-based index is enabled
DISABLED - Function-based index is disabled
二、条件中包括函数——走索引
SCOTT@zcs11g> alter system flush buffer_cache;
alter system flush shared_pool;
set autotrace traceonly explain;
select '--',empno,ename ,sal from t2 where upper(ename)='ALLEN';
/

/*----------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
----------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 33 | 2 (0)| 00:00:01 |
| 1 | TABLE ACCESS BY INDEX ROWID| T2 | 1 | 33 | 2 (0)| 00:00:01 |
|* 2 |
INDEX RANGE SCAN | T2_ENAME | 1 | | 1 (0)| 00:00:01 |
----------------------------------------------------------------------------------------*/

07.05-监控基于函数的索引


一、监视索引到底用没有用:查看v$object_usage.index_name.used=YES=表示索引被使用
SCOTT@zcs11g> set autotrace off;
alter index t2_ename MONITORING USAGE;
select '--',empno,ename ,sal from t2 where upper(ename)='ALLEN';
select '--'||used from v$object_usage where table_name='T2' and index_name='T2_ENAME';

--YES
二、关闭对index1索引的监控
SYS@zcs11g> alter index t2_ename nomonitoring usage;
select '--'||monitoring from v$object_usage where index_name='T2_ENAME';

--NO

第08部分-(d表+e表)簇索引(1~n个表的相同列值的记录行组成一个簇放在同一块中+重复部

本帖最后由 zcs0237 于 2013-7-29 18:50 编辑



2013-7-27 20:20 上传
下载附件
(199.82 KB)

-索引项的排序和数据行的排序完全一致,改变主键需要重新排序
-频繁修改索引列,不应使用聚簇索引
-聚簇还可以用于单个表,可以按某个列将数据分组存储
-全表扫描-增加很多无用的数据

08.01-索引簇+簇索引+建簇表的创建与管理


一、创建簇时需指定簇键列(另一种簇:哈希簇不能像索引簇那样关联多个表)
1、建聚簇(一开始就要指定单个簇的size空间大小)
备注:若指定了hashkeys,hashis 或single table hashkeys等散列参数则创建散列簇。
ZCS1@zcs11G> set sqlprompt "_user'@zcs'11g> "
drop cluster e_d_cluster including tables cascade constraints;
create cluster e_d_cluster (deptno number(2)) size 1000 pctfree 50 tablespace users;

说明:
-块大小/簇Size=每个块能容纳的最大簇的数目。
-簇size设置过大,在每个block将得到很少的key,会浪费空间;
-簇size设置过小,出现过多的跨块连接,降低性能。
2、更改簇
ZCS1@zcs11G> alter cluster e_d_cluster pctfree 30 initrans 3;
select '--',pct_free,ini_trans from dba_clusters where cluster_name='E_D_CLUSTER';

-- 30 3

INITRANS =块上预分配的ITLs空间=设大一点可减少ITL动态扩充的 Overhead。
3、补充:删除簇
--删除不包含表及索引的簇
ZCS1@zcs11G> drop cluster emp_dept_cluster;

--如果簇中包含表但未使用including tables子句,将收到错误信息
ZCS1@zcs11G> drop cluster emp_dept_cluster including tables;

对于包含簇之外的foreign key约束说参照的主键,需要使用cascade constraints子句
ZCS1@zcs11G> drop cluster emp_dept including tables cascade constraints;
二、创建簇的索引(因为数据一旦存储顺序只有一种,所以一个表只能有一个聚簇索引)
1、创建簇索引(可通过簇索引的簇键+blockid对簇的数据行进行访问)
SYS@zcs11G> create index e_d_cluster_idx on cluster e_d_cluster;

补充:
-Cluster index的作用是存储cluster key,并且返回包含该key的block的地址。
-当字段数据更新频率较低,查询使用频率较高并且存在大量重复值是建议使用聚簇索引
-cluster index是建立在cluster key上的一个B-tree树。该索引必须在任何数据行被插入到聚簇表之前被创建。
2、簇索引是簇上的索引
SYS@zcs11g> set pagesize 999
select index_type,table_name,table_type from user_indexes where INDEX_NAME='E_D_CLUSTER_IDX';

--INDEX_TYPE TABLE_NAME TABLE_TYPE
--------------------------- ------------------------------ -----------
--CLUSTER E_D_CLUSTER CLUSTER
3、补充:删除簇索引(不影响簇或它的簇表)
ZCS1@zcs11G> drop index e_d_cluster_idx;

三、建簇表(将虚拟簇表关联到已存在cluster segment里)
1、create table d (簇列,...) cluster簇名(簇列,...)
SYS@zcs11g> drop table d purge;
create table d cluster e_d_cluster(deptno) as select * from scott.dept;

drop table e purge;
create table e cluster e_d_cluster(deptno) as select * from scott.emp;
2、验证聚簇表的类型
ZCS1@zcs11G> set pagesize 0
set linesize 333
select '--',table_name,cluster_name from USER_TABLES where regexp_like(TABLE_NAME,'^D$|^E$');

-- D E_D_CLUSTER
-- E E_D_CLUSTER
3、查看簇列
SYS@zcs11g> select '--',cluster_name,clu_column_name from user_clu_columns where cluster_name='E_D_CLUSTER';

-- E_D_CLUSTER DEPTNO
-- E_D_CLUSTER DEPTNO

08.02-证明簇表的四个特性

一、聚簇中的表无法被TRUNCATE(因为块中不只一张表的数据)
ZCS1@zcs11G> truncate table d;

--ORA-03292: Table to be truncated is part of a cluster
二、数据对象号相同(簇表使用相同的簇段)
SYS@zcs11G> col object_name for a11
select '--',object_name,object_id,data_object_id from user_objects where object_name in ('D','E','E_D_CLUSTER');

-- D 74556 74554
-- E 74557 74554
-- E_D_CLUSTER 74554 74554
三、簇表中会出现rowid重复的情况 (簇表共享相同数据块)
1、select查看rowid
SYS@zcs11g>
select rowid from d intersect select rowid from e;

AAASM6AAEAAAAIMAAA
AAASM6AAEAAAAIMAAB
AAASM6AAEAAAAIMAAC
AAASM6AAEAAAAIMAAD

补充:Rowid如果相同时使用逻辑名称及object_id来区分



2013-7-27 20:21 上传
下载附件
(58.87 KB)

例: 6=AAASNE 3=AAE 6=AAAAIN 3=AAA
四、簇上无索引,索引簇表不允许插入数据(在把数据放入之前,cluster上须存在index)
1、簇上无索引,向簇表插数据失败
ZCS1@zcs11G> drop index e_d_cluster_idx;
insert into d select * from scott.dept;

--ORA-02032: clustered tables cannot be used before the cluster index is built
2、簇上有索引,簇表可插入数据
ZCS1@zcs11G> create index e_d_cluster_idx on cluster e_d_cluster;
insert into d select * from scott.dept;

--4 rows created.
ZCS1@zcs11G> rollback;

第09部分-(t1_part表)本地分区索引+范围分区表=最易维护最流行

本帖最后由 zcs0237 于 2013-7-29 18:49 编辑

一、局部分区索引有分区维护容易,平时用的最多(位图索引只能为局部分区索引)
1、基于分区表创建。
2、每个索引分区对应一个表分区。
3、又可以分为本地前缀索引和本地非前缀索引。
如果局部索引的索引列以分区键开头,则称为前缀局部索引。
如果局部索引的列不是以分区键开头,或者不包含分区键列,则称为非前缀索引。

二、全局分区索引主要是维护麻烦,不太建议使用(跨区查询等一些特殊情况下有些优势)
1、基于非分区表或分区表创建
2、全局索引的分区键和分区数和表的分区键和分区数可能都不相同
3、一个索引分区能指向n个表分区,同时,一个表分区,也可能指向n个索引分区

09.01-范围分区表(分区表共四类:范围+散列+列表+复合)

一、创建表空间
SYS@zcs11g> conn / as sysdba
set sqlprompt "_user'@zcs'11g> "
drop tablespace ZZ11 INCLUDING CONTENTS and datafiles;
drop tablespace ZZ12 INCLUDING CONTENTS and datafiles;
drop tablespace ZZ13 INCLUDING CONTENTS and datafiles;
drop tablespace ZZ11i INCLUDING CONTENTS and datafiles;
drop tablespace ZZ12i INCLUDING CONTENTS and datafiles;
drop tablespace ZZ13i INCLUDING CONTENTS and datafiles;
select '--'||name from v$tablespace where name like '%ZZ%' order by name;

-- no rows selected
SYS@zcs11g> create tablespace zz11 datafile '/tmp/zz11.dbf' size 99M reuse uniform size 3M;
create tablespace zz12 datafile '/tmp/zz12.dbf' size 99M reuse uniform size 3M;
create tablespace zz13 datafile '/tmp/zz13.dbf' size 99M reuse uniform size 3M;
create tablespace zz11i datafile '/tmp/zz11i.dbf' size 99M reuse uniform size 3M;
create tablespace zz12i datafile '/tmp/zz12i.dbf' size 99M reuse uniform size 3M;
create tablespace zz13i datafile '/tmp/zz13i.dbf' size 99M reuse uniform size 3M;
select '--'||name from v$tablespace where name like '%ZZ%' order by name;
/

--ZZ11
--ZZ11I
--ZZ12
--ZZ12I
--ZZ13
--ZZ13I
二、创建范围分区表
1、创建分区表
SYS@zcs11g> create table t1_part
(id number(6),date1 date) partition by range(date1)
( partition p2011 values less than (to_date('01/01/2012','DD/MM/YYYY')) tablespace zz11
, partition p2012 values less than (to_date('01/01/2013','DD/MM/YYYY')) tablespace zz12) ;
set pagesize 0
select '--'||partitioning_type,subpartitioning_type,status from all_part_tables where table_name='T1_PART';

--RANGE NONE VALID
2、表引分的大小
SYS@zcs11g> select '--',partition_name,bytes/1024/1024||'MB' from dba_segments where segment_name='T1_PART';

--P2012 3MB
--P2011 3MB

09.02-创建本地(唯一)分区索引

一、为分区表添加分区索引
SYS@zcs11g> drop index t1_part_idx;
create unique index t1_part_uk ON t1_part(id,date1)
local (partition p2011i tablespace zz11i,partition p2012i tablespace zz12i);
select '--',p.partition_name,p.status from user_ind_partitions p,user_indexes i where i.index_name='T1_PART_UK' and i.index_name=p.index_name;

-- P2011I USABLE
-- P2012I USABLE
二、索引名称、索引类型、是否前缀分区
SYS@zcs11g> select '--',partitioning_type,locality,alignment from user_part_indexes where index_name='T1_PART_UK';

-- RANGE LOCAL NON_PREFIXED
三、把索引设为unusable再rebuild(相比drop简楷掉了create index语句)
1、设为unusable
SYS@zcs11g> alter index t1_part_uk modify partition p2011i unusable;
select '--',partition_name,status from all_ind_partitions where index_name='T1_PART_UK';

-- P2011I UNUSABLE
-- P2012I USABLE
2、rebuild本地分区索引
SYS@zcs11g> alter index t1_part_uk rebuild partition p2011i;
select '--',partition_name,status from all_ind_partitions where index_name='T1_PART_UK';

--T1_PART_PK P2011I USABLE
--T1_PART_PK P2012I USABLE

09.03-表级分区改变时本地索引分区是否依然usable

一、添加表级分区——索引不受影响
1、添加表级分区:索引级分区自动添加
SYS@zcs11g> alter table t1_part add partition p2013 values less than (to_date('01/01/2014','DD/MM/YYYY')) tablespace zz13i;
select '--',partition_name,status from all_ind_partitions where index_name='T1_PART_UK';

-- P2011I USABLE
-- P2012I USABLE
-- P2013 USABLE
2、为新的表级索引改名
SYS@zcs11g> alter index T1_PART_UK rename partition P2013 to P2013i;
select '--',partition_name,status from all_ind_partitions where index_name='T1_PART_UK';

-- P2011I USABLE
-- P2012I USABLE
-- P2013I USABLE
二、截断表级分区——索引不受影响
1、准备:添加数据到表级分区
SYS@zcs11g> insert into t1_part values(131,(TO_DATE('2013-06-06', 'SYYYY-MM-DD')));
insert into t1_part values(132,(TO_DATE('2013-08-08', 'SYYYY-MM-DD')));
insert into t1_part values(121,(TO_DATE('2012-06-06', 'SYYYY-MM-DD')));
insert into t1_part values(122,(TO_DATE('2012-08-08', 'SYYYY-MM-DD')));
insert into t1_part values(111,(TO_DATE('2011-06-06', 'SYYYY-MM-DD')));
insert into t1_part values(112,(TO_DATE('2011-08-08', 'SYYYY-MM-DD')));
2、截断表级分区
SYS@zcs11g> select '--'||partition_name from DBA_TAB_PARTITIONS where TABLE_NAME='T1_PART';

--P2011
--P2012
--P2013
SYS@zcs11g> alter table t1_part truncate partition p2013;
3、对索引级分区的影响
SYS@zcs11g> select '--',partition_name,status from all_ind_partitions where index_name ='T1_PART_UK';

-- P2011I USABLE
-- P2012I USABLE
-- P2013I USABLE
三、拆分表级分区
1、查看分区范围
SYS@zcs11g> set linesize 999
col high_value for a333
col partition_name for a9
select '--',partition_name,high_value from dba_tab_partitions where table_name='T1_PART';

-- P2011 TO_DATE(' 2012-01-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIA
-- P2012 TO_DATE(' 2013-01-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIA
-- P2013 TO_DATE(' 2014-01-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIA
2、表级分区拆分出小范围子分区对索引级分区的影响(结果:07/01/2013=上半年数据分拆到p2013_1子分区中)
SYS@zcs11g> alter table t1_part split partition p2013 at (to_date('07/01/2013','DD/MM/YYYY')) into (partition p2013_1 tablespace users,partition p2013 tablespace users);
select '--',partition_name,status from all_ind_partitions where index_name='T1_PART_UK';

-- P2011I USABLE
-- P2012I USABLE
-- P2013I USABLE
-- P2013_1 USABLE
四、移动表级分区——索引不受影响
1、表级分区的位置
SYS@zcs11g> select '--'||partition_name,tablespace_name from dba_tab_partitions where table_name='T1_PART';

--P2011 ZZ11
--P2012 ZZ12
--P2013_1 USERS
--P2013 USERS
2、移动表级分区对索引级分区的影响——依然usable
SYS@zcs11g> alter table t1_part move partition p2013 tablespace zz13;
select '--',partition_name,status from all_ind_partitions where index_name='T1_PART_UK';

-- P2011I USABLE
-- P2012I USABLE
-- P2013I USABLE
-- P2013_1 USABLE
五、合并表级分区——索引不受影响(与DarlKuhn的书中说法不致)
SYS@zcs11g> col tablespace_name for a6
set linesize 999
select '--'||partition_name,high_value from dba_tab_partitions where table_name='T1_PART';

--P2011 TO_DATE(' 2012-01-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIAN')
--P2012 TO_DATE(' 2013-01-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIAN')
--P2013_1 TO_DATE(' 2013-01-07 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIAN')
--P2013 TO_DATE(' 2014-01-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIAN')
SYS@zcs11g> alter table t1_part merge partitions p2013_1,p2013 into partition p2013_1;

--ORA-14275: cannot reuse lower-bound partition as resulting partition

SYS@zcs11g> alter table t1_part merge partitions p2013_1,p2013 into partition p2013;
select '--',partition_name,status from all_ind_partitions where index_name='T1_PART_UK';

-- P2011I USABLE
-- P2012I USABLE
-- P2013I USABLE
SYS@zcs11g> col tablespace_name for a6
select '--' ,partition_name,tablespace_name,high_value from dba_tab_partitions where table_name='T1_PART';

--P2011 ZZ11 TO_DATE(' 2012-01-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIAN')
--P2012 ZZ12 TO_DATE(' 2013-01-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIAN')
--P2013 SYSTEM TO_DATE(' 2014-01-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIAN')
六、表级分区所在表空间只读——索引分区也只读,依然usable
SYS@zcs11g> alter tablespace zz12 read only;
select '--',partition_name,status from all_ind_partitions where index_name='T1_PART_UK';

--T1_PART_PK P2011I USABLE
--T1_PART_PK P2012I
USABLE
--T1_PART_PK P2013I USABLE
七、表级分区删除——索引级分区依然unusable
SYS@zcs11g> alter table t1_part drop partition p2011;
select '--',partition_name,status from all_ind_partitions where index_name='T1_PART_UK';

-- P2012I USABLE
-- P2013I USABLE
八、清理现场
SYS@zcs11g> drop table t1_part purge;
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: