oralce索引学习

来源:互联网 发布:python开发网页怎么样? 编辑:程序博客网 时间:2024/05/19 02:01
索引的存储结构:
1索引块内的值必须是顺序的
2索引块件的值逻辑上也是顺序的
3但是索引块间物理上可以不顺序。

函数索引注意事项:
创建完函数索引,必须要进行分析后才能使用。
确保函数索引涉及的表达式没有空值,否则无法使用函数索引。

基于表分区单独创建的索引称为本地索引,本地索引分前缀本地分区索引和非前缀本地
分区索引。
基于全表的分区键来建立分区索引段的称为全局分区索引。
全区分区索引只有前缀全局分区索引。
SQL> analyze index I_T_SO_SALE_04 validate structure;
索引已分析
SQL> select index_name,blevel,num_rows from user_indexes where index_name like 'I_T_SO%';
INDEX_NAME                         BLEVEL   NUM_ROWS
------------------------------ ---------- ----------
I_T_SO_SQUARE_CT1
I_T_SO_SQUARECHANGE2
I_T_SO_SALE_04
I_T_SO_SALE_03
I_T_SO_ESTIMATE0001
I_T_SO_CREMONTH_V51
I_T_SO_APPLY_02
I_T_SO_ALLRETURN_02
I_T_SO_ALLRESULT_02
已选择9行。

索引会按键的有序顺序进行访问,索引指向的块则随机的存储在堆中,也就是逻辑上是有序的,物理上是没有顺序的。通过索引访问表时,会执行大量分散,随机的i/o.等待事件db file sequential read这里说的顺序读,其实是读索引值时逻辑上是顺序的。
快速全索引扫描:对结果没有顺序要求,所以可以按照物理地址来多块读。

反转索引的几个缺点:
1由于反转索引存储键值的特点,导致不支持范围查找。
2反转索引会导致聚餐因子变大
3反转索引回导致更多的物理读。

函数索引的几个限制:
1必须分析
2 varchar2或raw要截断
3主键不可以。iot可以

函数索引的应用:对列的部分数据索引。
有的时候一个列上我们只想对某部分的数据创建索引,创建位图索引对并发性就不是很好了,可以通过函数来实现。
create index p_idx on big_table(case temporary when 'N' then 'N' end);
SQL> create table t(x int);
表已创建。
SQL> create index t_idx on t(case when x=42 then 1 end);
索引已创建。
SQL> set autotrace traceonly explain
SQL> select /*+ index(t t_idx) */ * from t where (case when x=42 then 1 end)=1;
执行计划
----------------------------------------------------------
Plan hash value: 470836197
| Id  | Operation                   | Name  | Rows  | Bytes | Cost (%CPU)| Time
    |

|   0 | SELECT STATEMENT            |       |     1 |    13 |     1   (0)| 00:00
:01 |


|   1 |  TABLE ACCESS BY INDEX ROWID| T     |     1 |    13 |     1   (0)| 00:00
:01 |


|*  2 |   INDEX RANGE SCAN          | T_IDX |     1 |       |     1   (0)| 00:00
:01 |


--------------------------------------------------------------------------------
-----

Predicate Information (identified by operation id):
---------------------------------------------------
   2 - access(CASE "X" WHEN 42 THEN 1 END =1)
Note
-----
   - dynamic sampling used for this statement


   看到上面的函数索引发生了查询转换。

SQL> select column_expression from user_ind_expressions where index_name='T_IDX';

COLUMN_EXPRESSION
--------------------------------------------------------------------------------
CASE "X" WHEN 42 THEN 1 END

SQL>
在定义里面也是发生了转换。

域索引:
SQL> insert into t values('1 12345 987');
已创建 1 行。
SQL> insert into t values('1 12345 987 567');
已创建 1 行。
SQL> create index t_idx on t(x) indextype is ctxsys.context;
SQL>    select x,score(0) from t where contains(x,'1 or 12345 or 567',0)>0 order by 2 desc;
X                                                    SCORE(0)
-------------------------------------------------- ----------
1 12345 987 567                                             4
1 12345 987                                                 3


压缩索引:
压缩键索引的基本概念是,每个键条目分解为两个部分:“前缀”和“后缀”
前缀建立在组合索引的前几列上,这些列有许多重复的值。
SQL> create table t as select * from all_objects;
SQL> create index t_idx on t(owner,object_type,object_name);
索引已创建。
SQL> analyze index t_idx validate structure;
索引已分析
SQL> create table idx_stats as select 'noncompressed' what,a.* from index_stats a;
表已创建。
SQL> drop index t_idx;
索引已删除。
SQL> create index t_idx on t(owner,object_type,object_name) compress 1;
索引已创建。
SQL> analyze index t_idx validate structure;
索引已分析
SQL> insert into idx_stats select 'compress 1',a.* from index_stats a;
已创建 1 行。
SQL> drop index t_idx;
索引已删除。
SQL> create index t_idx on t(owner,object_type,object_name) compress 2;
索引已创建。
SQL> analyze index t_idx validate structure;
索引已分析
SQL> insert into idx_stats select 'compress 2',a.* from index_stats a;
SQL> select what,height,lf_blks,br_blks,btree_space,opt_cmpr_count,opt_cmpr_pctsave from idx_stats;
SQL> select what,height,lf_blks,br_blks,btree_space,opt_cmpr_count,opt_cmpr_pctsave from idx_stats;
WHAT              HEIGHT    LF_BLKS    BR_BLKS BTREE_SPACE OPT_CMPR_COUNT OPT_CMPR_PCTSAVE
------------- ---------- ---------- ---------- ----------- -------------- ----------------
noncompressed          3        401          3     3232096              2               29
compress 1             3        353          3     2846684              2               19
compress 2             3        284          3     2294960              2                0
compress 3             3        450          3     3622296              2               36


压缩索引可以实现两种压缩模式:
1分支节点压缩
2叶节点压缩

位图索引:
创建索引的nosort选项的具体含义是?
如果索引列是有序的,可以添加nosort来加快速度。
create index index1 on orders(order_mode) nosort nologging parallel;

当表中的一行被删除的时候,这时候索引上对应的记录也跟着被删除,但是空间
会被留着,等待着被新的记录插入。所以如果索引不断的插入删除的话,容易
形成碎片和空间浪费。
索引项更新不同于表更新,索引项的更新意味着键值的改变,实际上是删除键值,在插入键值。
索引是有序的,如果直接跟新,那就不是有序的了。

所以有两种对索引的维护:合并和重建。
alter index index1 coalesce;合并
alter index index1 shrink space compact;
不会降低高水位
alter index index1 shrink space;
会降低高水位

索引的监控:
alter index index1 monitoring usage;
alter index index1 nomonitoring usage;
select * from v$object_usage;

在创建索引的时候就直接指定收集索引的信息。这样效率高些。
create index index1 on emp(empno) compute statistics;10g后是默认的。

虚拟索引:创建一个索引,但是不分配空间,就是用来判断优化器是否会使用到它
虚拟列索引
create table inv(inv_id number,inv_count number,inv_status generated always as 
(case when inv_count<=100 then 'GETTING LOW'
when inv_count>100 then 'OKAY' end));
自定义函数返回varcha2类型结果的测试:
 create or replace package stats as cnt number default 0;
 end;
 /
create or replace 
function my_soundex( p_string in varchar2 ) return varchar 

deterministic 
as 
l_return_string varchar2(6) default substr( p_string, 1, 1 
 ); 
l_char          varchar2(1); 
l_last_digit          number default 0; 
type vcArray is table of varchar2(10) index by binary_integer; 
l_code_table          vcArray; 
begin 
stats.cnt := stats.cnt+1; 
l_code_table(1) := 'BPFV'; 
l_code_table(2) := 'CSKGJQXZ'; 
l_code_table(3) := 'DT'; 
l_code_table(4) := 'L'; 
l_code_table(5) := 'MN'; 
l_code_table(6) := 'R'; 
for i in 1 .. length(p_string) 
loop 
exit when (length(l_return_string)= 6); 
l_char :=upper(substr( p_string, i, 1 ) ); 
for j in 1 .. l_code_table.count 
loop 
if (instr(l_code_table(j),l_char ) > 0 AND j <> l_last_digit) 
then 
l_return_string := l_return_string || to_char(j,'fm9'); 
l_last_digit := j; 
end if; 
end loop; 
end loop; 
return rpad( l_return_string, 6, '0' ); 
end; 


B树索引有多个子类型
索引组织表
唯一索引
反向键索引
键压缩索引
降序索引

索引组织表
索引组织表(IOT)不仅可以存储数据,还可以存储为表建立的索引。索引组织表的数据是根据主键排序后的顺序进行排列的,这样就提高了访问的速度。但是这是由牺牲插入和更新性能为代价的(每次写入和更新后都要重新进行重新排序)。
索引组织表适用场景:
IOT 就是类似一个全是索引的表,表中的所有字段都放在索引上,所以就等于是约定了数据存放的时候是按照严格规定的,在数据插入以前其实就已经确定了其位置,所以不管插入的先后顺序,它在那个物理上的那个位置与插入的先后顺序无关。这样在进行查询的时候就可以少访问很多blocks,但是插入的时候,速度就比普通的表要慢一些。
适用于信息检索、空间和OLAP程序。

   索引组织表的适用情况:
    1、 代码查找表。
    2、 经常通过主码访问的表。
    3、 构建自己的索引结构。
    4、 加强数据的共同定位,要数据按特定顺序物理存储。
    5、 经常用between…and…对主码或唯一码进行查询。数据物理上分类查询。如一张订单表,按日期装载数据,想查单个客户不同时期的订货和统计情况。
 
    经常更新的表当然不适合IOT,因为oracle需要不断维护索引,而且由于字段多索引成本就大。如果不是经常使用主键访问表,就不要使用IOT
create table indexTable(
       ID varchar2 ( 10 ),
       NAME varchar2 ( 20 ),
       constraint pk_id primary key ( ID )
      )
     organization index ;
唯一索引与定义主键或唯一约束时自动生成的索引的对比:
反向键索引:
当插入大量顺序值是,如何使用反向索引,就可以避免i/o集中在索引内的某个物理磁盘位置。
create index i on cutst(cust_id) reverse;

键压缩索引
键压缩索引有助于减少前导列经常重复的组合索引的存储和i/o要求
create index cust_indx on cust(last_name,first_name) compress 2;

降序索引
默认是升序的,如果一个劣质为数值类型数据的列上创建索引,最小的数值将首先出现在索引中,而最大的数值将被存储在最右边的叶节点上。
create index cust_idx on cust(cust_id desc);
对于某些列以升序排序而另一些以降序排序的查询时有用的。
特定的索引类型:
位图索引
位图连接索引
基于函数的索引
虚拟列索引
不可见索引
全局分区索引
本地分区索引
域索引
b树聚簇索引
散列聚簇索引

位图索引
使用场景:在where子句中使用多个and或or连接操作的sql语句(数据仓库)
不适用场景:经常执行insert/update/delete等操作的oltp库中
create bitmap index cust_idx on cust(custom_id);
位图连接索引
位图连接索引在索引中存储两个表之间的连接结果,避免了检索结果时对表进行连接。在使用一个表的外键列和另一个表的主键列连接两个表时,适合用位图连接索引。
通常适合有定期批量加载,然后不作更新的表的数据仓库环境。当更新有位图连接索引的表时,可能导致多行被锁定。位图连接索引使用关键字bitmap指定,并且必须提供一个连接条件。
create table d_customers(customer_id primary key,cust_name varchar2(30));
create bitmap index i_cust on f_sales(d_customers.cust_name) from f_sales,d_customers where f_sales.d_customer_id=d_customers.d_customer_id;

基于函数的索引索引
基于函数的索引引用其定义中的sql函数或表达式创建。

虚拟列索引
一种代替函数索引的方法是在表中添加一个虚拟列,然后为虚拟列创建索引。需要通过测试来确定在基于函数的索引和虚拟列的索引究竟哪种更适合你的性能要求。
这种方式在11g或更高版本中使用
create table inv(inv_id number,inv_count number,inv_status generated always as(case when inv_count<=100 then "GETTING LOW' when inv_count>100 then 'OKAY' end));
create index inv_idx1 on inv(inv_status);


虚拟索引

通过nosegment子句可以只是oracle创建永远不会被使用的索引,并且不会分配区给索引
create index cust_idx on cust(first_name)nosegment;
可以通过alter session set "_use_nosegment_indexes"=true;来确定该索引是否可以被优化器使用。
使用场景:要创建一个很大的索引,并且不分配空间,以便确定优化器是否会使用,可以创建该类型的索引来测试。

不可见索引
不可见意味着优化器为查询语句检索数据时不使用该索引。然而在对基础表插入,更新或删除记录是,数据库任然在维护该索引结构。
在11g或高版本中使用
create index cust_idx on cust(last_name) invisible;

全局和本地分区索引
可以为常规表或分区表创建全局分区索引,全局分区索引使用分区策略的索引,但这种分区并不映射到基础表的段。
create index f_sales_idx on f_sales(sales_amt) global partiton by range(sales_amt)
(partition pg1 values less than (25),

 partition pg2 values less than (50),

 partition pg3 values less than (maxvalue));

 本地分区索引必须建立在分区表上。这种索引与其基础表遵循相同的分区策略,本地分区索引的分区只包含其相应的表分区中的值。
create table f_sales(sales_amt number,d_date,id number,d_product_id number,d_customer_id number) partition by range(sale_amt)(
partition p1 values less than (100),
partition p2 vlaues less than (10000),
partition p3 values less than (maxvalue));

create index f_sales_idx on f_sales(d_date_id,sales_amt)local;

适合创建索引的列:
1 为经常用作where子句中谓词的列创建索引
2为在select子句中使用的列创建覆盖索引(这个主要是考虑了,可以使用索引结构本省来满足查询的结果,不通过回表了。)
3考虑为在order by grouby union或者distinct子句中使用的列创建索引。
4为外键列创建索引

索引范围扫描:优化器确定它使用索引结构检索查询所需的多个行是有效的,那么就使用这种扫描。
索引快速全扫描:优化器确定表中的大部分行需要进行检索,那么就使用这种扫描,但所需要的信息都存储在索引中,由于索引结构通常比表结构小,优化器确定全索引扫描更高效。对于统计count值的查询时很
常见的。

------------------------------------b树索引---------------------
创建b树索引要准备考虑问题:
1首先对大小评估
2考虑指定表索引的表空间
3让对象从他们的表空间继承存储参数
4定义创建索引时要使用的命名标准。

使用下面的语句来预估索引的大小
set serveroutput on
exec dbms_stats.gather_table_stats(user,'EMP');
variable used_bytes number
variable alloc_bytes number
exec dbms_space.create_index_cost('create index i_emp on emp(deptno)',:used_bytes,:alloc_bytes);
print :used_bytes 索引数据需要多少空间
print :alloc_bytes 在表空间内分配多大空间

显示一个用户下面的所有的索引定义
select dbms_metadata.get_ddl('INDEX',index_name) from user_indexes;

删除索引的步骤:
1启用对索引的监控
2使索引不可见
3使索引不可用
不可见索引任然由oracle维护,但查询优化器确定执行计划的时候不会考虑他,不可见索引任然可以由oracle在内部使用,用来避免锁定问题或强制执行约束。
alter index addr_fk1 invisible;
alter index addr_fk1 visible;
不可用索引是优化器不使用这个索引,并且当dml语句操作它的表时,oracle也不会维护该索引。不能在内部使用,用于强制执行约束或避免锁定问题。
在主键上创建索引的几种方法:
1 create able cust(cust_id number,first_name varchar2(200),last_name varchar2(200));
alter table cust add constraint cust_pk primary key(cust_id) using index tablespace users;
创建了跟约束同名的索引
2create table cust( cust_id number primary key,first_name varchar2(200),last_name varchar2(200)); 这个创建了主键约束和相应的唯一索引,自动生成一个名字,缺点是不允许在多个列上定义主键。
3分别创建索引和主键约束
create table cust(cust_id number,first_name varchar2(20),last_name varchar2(20));
create unique index cust_pk on cust(cust_id);
alter table cust add constriant cust_pk primary key(cust_id);
优点是,独立于索引删除或禁用主键约束。
删除主键约束和索引
alter table cust disable constraint cust_pk;
alter table cust drop constraint cust_pk;
alter table cust drop primary key;
在删除或禁用约束时,可以选择不删除相关索引
alter table cust drop constraint cust_pk keep index.
唯一键与主键的区别:
1 唯一键可以包含null
2可以有多个唯一键
分区索引
可以把本地分区索引创建为前缀或非前缀索引,在创建本地分区的前缀索引时,意味着表的分区列在索引的前导端,如果分区列不在索引的前导端,就被当作非前缀索引。
在创建本地分区的唯一索引时,索引必须包括分区列。
create unique index emp_indx on employees_part(employee_id,hire_date) local;
需要在表上定义主键约束时,首先使用主键约束的列创建唯一索引,然后在添加约束,如
create unique index employees_ind on employees_part(employee_id,hire_date) local;
alter table employees_part add constraint employees_part_pk primary key(employee_id,hire_date);
这个好处是禁用和重新启用约束,不必删除底层索引。如果索引是内联创建的,禁用约束后就删除了这个索引。
创建全局分区索引
全局分区索引类似于分区表,只不过这个分区的对象是索引,分区表的对象是表。创建分区索引的语法类似如下:
create index employee_idx on emp(mgr) global partition by range(mgr)
(partition manager_100 values less than(100),
partition manager_200 values less than(200),
partition manager_300 values less than(300),
partition manager_max values less than(maxvalue));
select partition_name,status from user_ind_partitions where index_name=upper('employee_idx');
PARTITION_NAME                 STATUS
------------------------------ --------
MANAGER_100                    USABLE
MANAGER_200                    USABLE
MANAGER_300                    USABLE
MANAGER_MAX                    USABLE
向全局分区索引中添加一个分区
alter index employee_idx split partition manager_max at(400) into(partition manager_max,partition manager_400);
索引已更改。
SQL> select partition_name,status from user_ind_partitions where index_name=upper('employee_idx');
PARTITION_NAME                 STATUS
------------------------------ --------
MANAGER_100                    USABLE
MANAGER_200                    USABLE
MANAGER_300                    USABLE
MANAGER_400                    USABLE
MANAGER_MAX                    USABLE
SQL> alter index employee_idx drop partition manager_300;
索引已更改。
SQL> select partition_name,status from user_ind_partitions where index_name=upper('employee_idx');
PARTITION_NAME                 STATUS
------------------------------ --------
MANAGER_100                    USABLE
MANAGER_200                    USABLE
MANAGER_400                    USABLE
MANAGER_MAX                    USABLE
重建全局索引分区
alter index employee_idx rebuild partition manager_300;
创建全局唯一索引分区的语句
create unique index employee_idx on emp(mgr,empno) global partition by range(mgr)
(partition manager_100 values less than (100),
partition manager_200 values less than (200),
partition manager_300 values less than (300),
partition manager_max values less than (maxvalue);
全局分区索引必须创建为前缀索引,也就是分区列必须在该索引的前导列。
另一种全局分区索引类型时散列分区索引。
将索引分区设置为不可用
alter table emp_par modify partiton pmax unusable local indexes;
重建分区索引
alter table emp_par modify partition pmax rebuild unusable local indexes;
oracle11g引入了间隔分区功能,让oracle在输入的数据与表中已有的分区边界不匹配是,自动创建保存这些数据的表分区。
查看分区索引的信息:
select table_name,index_name,partition_name,p.status from user_ind_partitions p join user_indexes i using(index_name) where table_name='EMP'
union
select table_name,index_name,null,status from user_indexes where table_name='EMP' order by 2,3;
TABLE_NAME                     INDEX_NAME                     PARTITION_NAME                 STATUS
------------------------------ ------------------------------ ------------------------------ --------
EMP                            EMPLOYEE_IDX                   MANAGER_100                    USABLE
EMP                            EMPLOYEE_IDX                   MANAGER_200                    USABLE
EMP                            EMPLOYEE_IDX                   MANAGER_400                    USABLE
EMP                            EMPLOYEE_IDX                   MANAGER_MAX                    USABLE
EMP                            EMPLOYEE_IDX                                                  N/A
EMP                            PK_EMP                                                        VALID

select table_name,index_name,partitioning_type,locality,alignment from user_part_indexes;
TABLE_NAME                     INDEX_NAME                     PARTITION LOCALI ALIGNMENT
------------------------------ ------------------------------ --------- ------ ------------
EMP                            EMPLOYEE_IDX                   RANGE     GLOBAL PREFIXED
SALE_DATA                      SALE_DATA_INX                  RANGE     LOCAL  PREFIXED

监控索引的使用
alter index employees_idx monitoring usage;
select index_name,monitoring,used from v$object_usage;
关闭索引监控
alter index employees_idx nomonitoring usage;
查看索引使用的次数
select d.object_name,d.operation,d.options,count(1) from dba_hist_sql_plan d,dba_hist_sqlstat h where d.object_owner<>'SYS' and d.operation like '%INDEX%' and d.sql_id=h.sql_id
group by d.object_name,d.operation,d.options order by 1,2,3;
不使用索引的hint
select /*+ no_index(employees emp_id) */ employee_id from employees where employee_id>200;
如果no_index没有指定任何索引名称,优化器会忽略你指定的表的所有索引。
当谓词中使用不等条件时候
优化器更倾向于使用全表扫描,解决的方法就是重写查询,消除不等于子句,如果有多个谓词,更有必要重写,当制定not in子句时,优化器的行为与指定不等于是相同的。
select * from emp where trunc(start_date)=trunc(sysdate);
可以改写成下面的语句
select * from emp where start_date>=trunc(sysdate) and start_date<trunc(sysdate+1);
想要在index提示中指定多个索引,oracle建议指定index_combine提示,而不是index提示,这种情况性爱,优化器将使用两个指定索引成本最低的组合。
select /*+ index_combine(e emp_manager_ix emp_department_ix) */ * from employees e where manager_id=108 or department=100;
索引连接
两个索引包含返回查询结果所需要的所有列,就可以指定数据库使用索引连接,是索引的散列连接,它将返回查询所要求的所有列。
 explain plan for  select /*+ index_join(emp EMPLOYEE_IDX I_EMP_DEPT) */ deptno from emp where mgr<234 and deptno<34;
Plan hash value: 2867664701
---------------------------------------------------------------------------------------------------------------
| Id  | Operation                  | Name             | Rows  | Bytes | Cost (%CPU)| Time     | Pstart| Pstop |
---------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT           |                  |     1 |     7 |     3  (34)| 00:00:01 |       |       |
|*  1 |  VIEW                      | index$_join$_001 |     1 |     7 |     3  (34)| 00:00:01 |       |       |
|*  2 |   HASH JOIN                |                  |       |       |            |          |       |       |
|   3 |    PARTITION RANGE ITERATOR|                  |     1 |     7 |     2  (50)| 00:00:01 |     1 |     3 |
|*  4 |     INDEX RANGE SCAN       | EMPLOYEE_IDX     |     1 |     7 |     2  (50)| 00:00:01 |     1 |     3 |
|*  5 |    INDEX RANGE SCAN        | I_EMP_DEPT       |     1 |     7 |     2  (50)| 00:00:01 |       |       |

PLAN_TABLE_OUTPUT
在处理分区索引时,可以指示优化器使用并行,可以并行化的操作包括索引范围扫描,全索引扫描和索引快速全扫描。
select /*+ parallel_index(employees,employee_id_idx,4) */ last_name,employee_id from employees;
对索引启用并行
alter index test_idx parallel;
select degree from user_indexes where index_name='test_idx';
alter index test_idx parallel 12;
create index test_idx3 on test(x) parallel (degree 8);
alter index m_idx noparallel;
索引的维护
set serveroutput on
begin
for ind in
(select object_name from user_objects where object_type='INDEX')
loop
dbms_output.put_line('Gathering index statistics for'||ind.object_name||'......');
dbms_stats.gather_index_stats(user,ind.object_name,estimate_percent=>100);
dbms_output.put_line('gathering index statistics for'|| ind.object_name||' is complete!');
end loop;
end;
下面的实验说明唯一索引,在不可用后,dml操作依然无法进行,因为索引是唯一的,这个索引不可用,对表的插入或更新,可能会违反唯一约束。
SQL> create unique index i_ename on emp(ename);
索引已创建。
SQL> alter session set skip_unusable_indexes=false;
会话已更改。
SQL> alter inde i_ename unusable;
alter inde i_ename unusable
      *
第 1 行出现错误:
ORA-00940: 无效的 ALTER 命令
SQL> alter index i_ename unusable;
索引已更改。
SQL> insert into emp(empno,ename) values(32,'ii');
insert into emp(empno,ename) values(32,'ii')
*
第 1 行出现错误:
ORA-01502: 索引 'SCOTT.I_ENAME' 或这类索引的分区处于不可用状态

索引的重建,合并,收缩
回收为使用的空间
alter index test_idx deallocate unused;
段内空间不会被释放,只有段尾的空间才被释放。
在并行创建索引的时候,创建后的索引的并行度就变了。表也一样,这个是需要注意的。
SQL> create index i_mgr on emp(mgr) parallel 10;
索引已创建。
SQL> select index_name,degree from user_indexes where index_name='I_MGR';
INDEX_NAME                     DEGREE
------------------------------ ----------------------------------------
I_MGR                          10
alter index i_mgr noparallel;
索引已更改。
SQL> select index_name,degree from user_indexes where index_name='I_MGR';
INDEX_NAME                     DEGREE
------------------------------ ----------------------------------------
I_MGR                          1
移动索引
alter index test_idx rebuild parallel 12 nologging tablespace dev_test;
表移动
alter table test move tablespace dev_test;
下面的实验是看索引条目被删除后,空间是否会重用
create table reb_test(cust_id number,cust_code number,cust_name varchar2(20));
insert into reb_test select rownum,rownum,'Groucho Marx' from dual connect by level <10;
commit;
create index reb_test_cust_idx on reb_test(cust_id);
delete from reb_test where cust_id in(1,2,3,4);
commit;
analyze index reb_test_cust_idx validate structure;
select lf_rows,del_lf_rows,del_rows/lf_rows*100 del_pct from index_stats;
   LF_ROWS DEL_LF_ROWS    DEL_PCT
---------- ----------- ----------
         9           4 44.4444444
SQL> insert into reb_test values(999,1,'Franco Marx');
已创建 1 行。
SQL> commit;
提交完成。
SQL> analyze index reb_test_cust_idx validate structure;
索引已分析
SQL> select lf_rows,del_lf_rows,del_rows/lf_rows*100 del_pct from index_stats;
select lf_rows,del_lf_rows,del_rows/lf_rows*100 del_pct from index_stats
第 1 行出现错误:
ORA-00904: "DEL_ROWS": 标识符无效
SQL> select lf_rows,del_lf_rows,del_lf_rows/lf_rows*100 del_pct from index_stats;
   LF_ROWS DEL_LF_ROWS    DEL_PCT
---------- ----------- ----------
         6           0          0
analyze index ... validate structure命令可能会导致大量的锁定问题。
合并索引
alter index test_idx coalesce;
合并的目的是减少索引中的碎片,并不释放已分配给索引段的空间,合并索引对索引数据执行就地重组,吧相邻的叶块组合成一个叶块,并把新的空叶块放到索引段的空闲列表中。
收缩索引
alter index test_idx shrink space;
收缩索引压缩了索引段而数据库将立即释放已经腾出来的空间,时间可能很长。
shrink space compact只执行端空间碎片整理,不会立即释放空闲空间。这个操作比合并索引复杂。
合并不会产生锁,回收会产生锁

0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 淋浴分水器坏了怎么办 花洒从侧面漏水怎么办 花洒接口处漏水怎么办 买到香港箭牌该怎么办 雨伞杆抽出来了怎么办 招行的young卡怎么办 高一数学50分怎么办 在无烟房抽烟了怎么办 喂奶粉的新生儿腹部很大怎么办 剑三身份证忘了怎么办 中药剂量吃大了怎么办 社保卡3年没激活怎么办 社保卡2年没激活怎么办 cad没保存关了怎么办 cad未响应没保存怎么办 办公椅扶手坏了怎么办 玩刺客信条卡bug怎么办 我玩刺客信条1卡怎么办 玩刺客信条3卡死怎么办 mac玩刺客信条卡怎么办 阴部长了个疙瘩怎么办 两个人觉得累了怎么办 朋友把我拉黑了怎么办 下雨了怎么办我好想你 雨停怎么办我好想你 下雨天怎么办我好想你 天谕账号忘记了怎么办 天谕账号被冻结怎么办 促黄体生成素低怎么办 地暖家里太干燥怎么办 剑灵摧毁了东西怎么办 想打嗝打不出来怎么办 孩子满100天要怎么办 宝宝吃奶粉过敏了怎么办 1岁宝宝不喝奶粉怎么办 母乳不够宝宝不喝奶粉怎么办 宝宝吃奶粉上火了怎么办 我小孩不喝奶粉怎么办 2岁宝宝不喝奶粉怎么办 婴儿吃奶粉上火了怎么办 100天的宝宝咳嗽怎么办