2011年3月2日
索引键压缩
通过index_stats视图判断索引是否需要压缩:
select opt_cmpr_count,opt_cmpr_pctsave from index_stats;
--opt_cmpr_pctsave表示压缩后可节省的空间
--opt_cmpr_count表示应该压缩的列数即长度
压缩语法:
create index index_name on t1(col1, col2, col3, col4) compress &1;--创建时压缩
alter index index_name rebuild compress &1;--重建时压缩
--&1表示压缩的长度
--备注:index_stats视图只有在对索引进行结构分析后才会有记录,而且只存储最后一次对索引分析结构的信息,且只能在本会话中查询看到
反向键索引( reverse key index ):
这也是 B* 树索引,只不过键中的字节会 “ 反转 “ 。利用反向键索引,如果索引中填充的是
递增的值,索引条目在索引中可以得到更均匀的分布。例如,如果使用一个序列来生成主键,这个序列将生成诸如 987500 、 987501 、
987502 等值。这些值是顺序的,所以倘若使用一 个传统的 B* 树索引,这些值就可能放在同一个右侧块上,这就加剧了对这一块的竞争。
利用反向键, Oracl e则会逻辑地对 205789 、 105789 、 005789 等建立索引。 Oracle 将数据放在索引中之前,将先把所存储数据的
字节反转,这样原来可能在索引中相邻放置的值在字节反转之后就会相距很远。通过反转字节,对索引的插入就会分布到多个块上。
语法:create index index_name on t1(col1) reverse;
降序索引
降序索引是8i里面新出现的一种索引,是B*Tree的另一个衍生物,他的变化就是列在索引中的储存方式从升序变成了降序,在某些场合下
降序索引将会起作用。如下:
SQL> set autotrace traceonly explain;
SQL> select * from sys_log where log_id between 45534536 and 45534845 order by l
og_date asc,log_id desc;
执行计划
----------------------------------------------------------
-------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)|
-------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 309 | 24411 | 130 (4)|
| 1 | SORT ORDER BY | | 309 | 24411 | 130 (4)|
| 2 | TABLE ACCESS FULL| SYS_LOG | 309 | 24411 | 129 (4)|
-------------------------------------------------------------------
--查看创建降序索引后的区别,少了排序步骤(这是因为创建降序索引时Oracle已把数据都按降序排好了)
create index inx_syslog on sys_log(log_id desc,log_date asc);
SQL> exec dbms_stats.gather_index_stats('LTTFM','INX_SYSLOG');
SQL> select * from sys_log where log_id between 45534536 and 45534845 order by l
og_id desc,log_date asc;
执行计划
----------------------------------------------------------
-------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)|
-------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 309 | 24411 | 5 (0)|
| 1 | TABLE ACCESS BY INDEX ROWID| SYS_LOG | 309 | 24411 | 5 (0)|
| 2 | INDEX RANGE SCAN | INX_SYSLOG | 41 | | 2 (0)|
-------------------------------------------------------------------------------
位图索引
在一颗 B* 树中,通常索引条目和行之间存在一种一对一的关系:一个索引条目就指向一行。而对于位图索引,一个索引条目则使用一个
位图同时指向多行。位图索引适用于高度重复而且通常只读的数据(高度重复是指相对于表中的总行数,数据只有很少的几个不同值)。
考虑在一 个有 100 万行的表中,每个列只有 3 个可取值: Y 、 N 和 NULL 。举例来说,如果你需要频繁地统计多少行有值Y ,
这就很适合建立位图索引。不过并不是说如果这个表中某一列有 11.000 个不同的值就不能建立位图索引,这一列当然也可以建立
位图索引。在一个 OLTP 数据库中,由于存在并发性相关的问题,所以不能考虑使用位图索引(后面我们就会讨论这一点)。
--注意,位图索引要求使用 Oracle 企业版或个人版。
create bitmap index indexname on t(col1);
位图联结索引
create bitmap index emp_bm_idx on emp( d.dname ) from emp e, dept d where e.deptno = d.deptno
使其他的表的列建立一个索引。在emp上建立一个dept.dname的索引。
使类似的查询可以只读取索引而不做全表扫描。
位图联结索引有一个先决条件。联结条件必须联结到另一个表中的主键或惟一键。在前面的例子中DEPT.DEPTNO 就是DEPT 表的主键,
而且这个主键必须合适,否则就会出现一个错误。
基于函数的索引
这些就是 B* 树索引或位图索引,它将一个函数计算得到的结果存储在行的列中,而不是存储列数据本身。可以把基于函数的索引看作一个
虚拟列(或派生列)上的索引,换句话说,这个列并不物理存储在表中。基于函数的索引可以用于加快形如:
SELECT * FROM T WHERE FUNCTION(DATABASE_COLUMN) = SAME_VALUE 这样的查询,因为值 FUNCTION(DATABASE_COLUMN) 已经提前
计算并存储在索引中。
--无索引的情况下查询
SQL> select * from i_exch_info where lower(code) ='nh10237';
执行计划
----------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)|
----------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 171 | 46512 | 171 (3)|
| 1 | TABLE ACCESS FULL| I_EXCH_INFO | 171 | 46512 | 171 (3)|
----------------------------------------------------------------------
--创建基于函数的索引后的查询
create index i_exch_info_lower on i_exch_info(lower(code));
SQL> select * from i_exch_info where lower(code) ='nh10237';
执行计划
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)|
--------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 171 | 46512 | 66(0)|
| 1 | TABLE ACCESS BY INDEX ROWID| I_EXCH_INFO | 171 | 46512 | 66(0)|
| 2 | INDEX RANGE SCAN | I_EXCH_INFO_LOWER | 68 | | 1(0)|
对部分行建立索引
create index idx_exch_info on i_exch_info(case when g3e_id<50000237 then g3e_id end);
select * from i_exch_info where g3e_id=50000006;--始终没有使用索引
select /*+index(t,idx_exch_info)*/* from i_exch_info t where g3e_id=50000006;
analyze index idx_exch_info validate structure;
--查看索引
select * from user_ind_expressions
判断索引是否需要重建
途径:通过index_stats视图:index_stats视图只存储最后一次对索引分析结构的信息;
而且只能在执行 analyze index index_name validate structure 语句的session会话中看到数值,另外的会话是看不到的.
对一个索引进行结构分析后,如果该索引占用超过了一个数据块,且满足以下条件之一:B-tree树的高度大于3;使用百分比低于75%;数据删除率大于15%,就需要考虑对索引重建。
analyze index IDX_P_TILE_STREETAREA_ROWCOL validate structure;--分析索引结构
--查看该索引的相关信息
select btree_space, -- if > 8192(块的大小)
height, -- if > 3
pct_used, -- if < 75
del_lf_rows / (decode(lf_rows, 0, 1, lf_rows)) * 100 as deleted_pct -- if > 20%
from index_stats;
如果超出了if 后面的值即可能需要进行 index rebuild.