oracle index blevel 降低,Oracle reverse函数

reverse函数功能就是反向排列给定的数组元素

SQL>      create     or     replace     function     Re(s     string)     return     varchar2     is

Result     varchar2(1000);

v_s     string(1000);

begin

for     i     in     1..length(s)

loop

Result:=Result||substr(s,length(s)-i+1,1);

end     loop;

return(Result);

end     Re;

1.3.3 索引

Oracle 9i中有6种可以使用的索引:B-Tree索引(不指定任何选项的创建方法所创建)、压缩B树索引、Bitmap(位图)索引、基于函数的索引、 Reverse Key Index(RKI,反向键索引)、Index Organized Table(IOT,索引组织表)。

1.3.3.1 检查索引信息

 dba_indexes

index_type (normal-B树,normal/rev-反向键,function-based normal,bitmap,iot-top,cluster,lob)

compression

funcidx_status

 dba_segments

segment_name

segment_type

tablespace_name

 dba_tables

SQL> select table_name,iot_name,iot_type,tablespace_name from dba_tables where iot_type is not null;

就可以观察出IOT益出的情况。 Tablespace_name 为空,说明为一个索引而不是一个表。

 监视索引使用情况

如果一个索引永远得不到,应该删除:

1)消除了对被索引表DML操作时的索引维护系统开销。

2)释放表空间。

执行SQL>alter index c_unicom.idx_ne_cell monitoring usage;

一段时间后执行SQL> alter index unicom.idx_ne_cell nomonitoring usage;

此时查询v$object_usage(Oracle 9i)的used列,YES表示监视期间至少得到过一次访问。NO表示未得到访问。

1.3.3.2 B-Tree索引

 基础概念

也叫平衡树索引。

是按升序对被索引的列进行排序,同时存储一个行ID,用来指出该行的其他数据的物理存储地,Oracle以一种树型结构来存储这些数。

查询时,首先搜索该多级树结构形式组织的索引,然后按ID访问需要的表数据。

1)如果表数据行很多,只返回一个表中的少数行(Oracle建议是5%)。

2)具有高基数的列。且这些列经常被用在where条件中。

此时Oracle建议创建一个B树索引。

如:Create index idx_ne_cell on ne_cell(ne_id) tablespace unicom_dbs;

 判断是否需要重建索引

B树索引设计为总是平衡的,Oracle随着insert操作而连续的分裂索引块,但是,随着insert和delete操作,该索引会产生许多级,增加索引从根遍历的时间,降低了效率,此时需要重建索引。

Oracle建议:

1)当级别深度到4或超过4时。(增加了从根遍历的时间)

索引被分析后,执行select index_name,blevel from dba_indexes where blevel >=4;检查

2)被删除数占总数的20%以上时。(增加了访问某项所访问的index块数)

- 执行analyze index idx_ne_cell validate structure;填充表index_stats数据。

- 执行select (del_lf_rows_len/lf_rows_len)*100 “Wasted Space”

from index_stats where name=’IDX_NE_CELL’;

Column Description

LF_ROWS Number of values currently in the index

LF_ROWS_LEN Sum in bytes of the length of all values

DEL_LF_ROWS Number of values deleted from the index

DEL_LF_ROWS_LEN Length of all deleted values

 重建索引

在一个不稳定的表上建索引会影响性能,一个索引block只有完全空时才能进入free list,即使一个索引block里只含有一个条目,它也必须被维护,因此索引需要进行阶段性的重建。

- 删除该index并执行create index ...开始创建。

是最耗时的方法,也是资源密集型。但7.3前版本只能这么做。

- alter index .. rebuild tablespace ..;

使用现有索引项来重建索引,很快。同时能把索引转移到其他表空间。但创建的过程中,新旧索引同时存在,要求有额外的临时空间可用。

SQL>alter index idx_ne_cell rebuild online;

使用online来尽可能减少创建过程中出现的任何加锁问题。

- alter index .. coalesce;

只是将处于同一个索引分支内的叶块拼合起来,很快,不要求额外的磁盘空间,最大限度的减少了创建过程中出现的任何加锁问题。但此方法不能转移索引到另外一个表空间。

更多关于alter index 参考 9.0.1 A901177-01的16章。

1.3.3.3 压缩B树索引

如果B树索引非常大,此时就建议使用压缩B树索引了。

压缩B树索引:在索引列存在重复值时,只记录一个值和不同的row id,减少了重复的列值的存储(同理,基数非常大或列值都唯一的,压缩就没多少必要了)。最大限度的减少了B树索引占用的磁盘空间。同时索引扫描也会访问更少的数据库块,减少I/O。

压缩语句:

SQL>create index idx_alarminfo on alarminfo(ALARMOBJECT) tablespace unicom_dbs compress;

或:

SQL>alter index idx_alarminfo rebuild compress;

1.3.3.4 Bitmap(位图)索引

创建表行的一个二进制映像,比如是存储1,不是存储0。所以占用更少的存储空间。

1)位图索引检索、匹配的行会更快。

2)对于底基数列,工作的更好。(高基数,B树好)

3)被索引表要DML操作少、长度大、有极少不同值的表列上极有用。(DML操作会引起位图级的加锁发生,而且要求重建所有可能值的整个位图;即使发生很多行被操作,但只按一次DML进行更新)

4)适合在决策支持系统或数据仓库使用。

SQL>create bitmap index idx_ne_cell on ne_cell(related_bsc);

//加大sort_area_size和pga_aggregate_target通常会加快bitmap index的创建和操作。

1.3.3.5 基于函数的索引

函数索引适用于B树索引和bitmap索引。但必须把init.ora的query_rewrite_enabled参数设置成true才可使用。(默认是false)

在SQL语句的WHERE字句中有任一函数或操作被运用于一个索引列时,执行计划将使用全表扫描而不会使用非函数索引。

如:select last_name,first_name from employee

where upper(first_name) = ‘REGINALD’;

或:select product_id,units,price,price*units from sales

where (price*units) > 10000;

都不会使用first_name或price或units列上的索引。

如下创建函数索引后优化程序才会考虑使用索引:

SQL>create index idx_first_name_employee on employee (upper(first_name));

SQL>create index idx_sales_total on sales (price*units) tablespace ind_dbs;

1.3.3.6 Reverse Key Index

属于B树索引。

RKI:首先反向每个列键值的字节(如123,就被反为321,新数值在范围上,比原来那些列值会分布的更均匀),然后在反向后的数据上进行索引。

非常适用于含有序数的列。(因传统的B树,此时往往会产生很多级,而超过4级性能就会很低)

注意:RKI只能用于等于、不等于判断。其他如>、

SQL>create index idx_employee_iem_id on employee(emp_id)

Reverse

Tablespace idx_dbs;

SQL>alter index idx_employee_iem_id rebuild reverse;

1.3.3.7 Index Organized Table

B树、位图、反向等索引,直接指向索引基础表中对应数据行的ID,这是因为表行以一种或多或少的随机方式被分配给表内的块,因Oracle在存储行时,并不考虑行的内容。是一种堆叠方式存储的数据,叫Heap Table(堆表)。

如果希望按一种指定顺序来存储一个表数据,就要使用IOT(索引组织表)。此时把行数据全部存储在索引本身内。

好处:

1)表行按索引顺序存储。若用主键来访问表,IOT比传统表更快。

2)使用B树时,只需要读取索引,不需要读取表,减少了一次I/O。

注意:

1)IOT在将要做索引基础的那一列上必须有一个主键约束。

2)IOT不能含有唯一性约束,或被cluster。

SQL>create table employee_history

(employee_id number primary key,

last_name varchar2(20),

first_name varchar2(20),

title varchar2(30),

hire_date date,

departure_date date)

ORGANIZATION INDEX TABLESPACE idx_dbs --指定表为IOT

PCTTHRESHOLD 25 --指定真个数据块保持打开的百分比,必须在0-50之间

INCLUDEING first_name --指定行超过PCTTHRESHOLD时,按那一列把行分解成两段

OVERFLOW TABLESPACE app_of – 指定分解的行的一半存储的表空间

MAPPING TABLE; -- 在创建IOT上的位图所有时所必须的一个关联映像表的创建

位图索引可以以堆表(此时以行ID关联数据行)或IOT(利用映像表来定位被索引的IOT行)做为基础表。

映像表:把索引的物理行ID映像到索引组织表的对应的逻辑行ID,每个IOT只有一个。

物理行ID会随着数据的insert和delete而发生变化(因为排序了,IOT叶会在它们变满时像B树索引一样发生分裂;如果没有映像表记录逻辑ID,这种物理分裂会使相关位图索引不能使用)。

随着时间的推移,bitmap index可能会和IOT不一致,查找不一致范围:

SQL> select owner,index_name,pct_direct_access from dba_indexes

where pct_direct_access is not null;

Oracle建议,超过30%的bitmap index应该rebuild。

1.3.4 分区partition

分区:将表数据划分成更小的子集。

好处:

1)提高可用性。

如100GB的表,如果划分成2G的50个分区,只要当前查询的数据所处的分区online,而其他的分取offline,数据库依然工作正常。

2)减轻管理负担。

对分区数据的维护,比如删除、更新、分析、数据恢复等,可以以分区为单位进行维护。

3)提高DML和查询操作性能。

利用CBO的分区排除机制,跳过未含有相关数据的表分区,减少I/O。

分区表使用CBO,CBO具有很好的“分区意识能力”,直接排除不属于查询结果的分区。(分区键列上同样不能应用函数,否则不会使用索引)

对于分区的表,应尽可能的利用分区键作为查询条件,不然会执行full table scan,会比不分区的全表扫描花费更多的时间,失去分区的意义。

分区信息可查询:select * from user_tab_partitions;

(比如小区表,可以按小时分区,小时里再按hash分区防止分区不均匀,此时再对各分区进行truncate等维护,就快了)

1.3.4.1 创建分区

分区可分为如下几种:(范围分区,hash分区,列表分区,范围-hash分区,范围-列表分区(oracle 9i relase 2以后才提供))

 范围分区

使用列值的范围来确定一个数据行被插入到那个分区中。

1)分区键最多可16列,一个表最多可65636个分区。

2)分区范围中不能有任何空隙。

3)每个分区中,等于上限的值都是存储在上一个分区中的。

4)less then子句指定的值,必须是一个用RPAD函数填充过的值、日期(必须包含世纪)或常数。

5)分区表不能包含带有long,long raw的数据列。

6)试图插入一个无法放入任一分区的数据,都导致ORA-14400错误。

7)通过更新数据使数据在分区间移动不被允许,除非创建表的时候指定了enable row movement子局。

如果插入的数据导致分区不均匀,应考虑使用散列分区。

SQL>create table student_history

(student_id number(10),

degree varchar2(3),

gradution_date date)

PARTITION BY RANGE (graduation_date)

(PARTION p_2000 VALUES LESS THEN

(to_date(‘2000-1-1’,’yyyy-mm-dd’)) TABLESPACE hist_tab01,

PARTION p_2001 VALUES LESS THEN

(to_date(‘2001-1-1’,’yyyy-mm-dd’)) TABLESPACE hist_tab02,

PARTION p_error VALUES LESS THEN

(MAXVALUE) TABLESPACE hist_tab03

);

SQL> select * from student_history (p_2000);

 列表分区

类似范围分区,区别是它基于一组指定的值。范围分区是基于一个范围。

试图插入一个无法放入任一分区的数据,都导致ORA-14400错误。

SQL>create table student_history

(student_id number(10),

degree varchar2(3),

gradution_date date)

PARTITION BY LIST (degree)

(PARTION p_undergrad VALUES (‘BS’,’BA’,’BBA’,’BFA’)

TABLESPACE hist_tab01,

PARTION p_graduate VALUES (‘MA’,’MBA’,’MFA’,’MS’)

TABLESPACE hist_tab02,

PARTION p_doctorate VALUES (‘PHD’)

TABLESPACE hist_tab03

);

 散列分区

使用一个散列算法来分配数据被插入到那个分区中。一般分配很均匀,对于序数的列很适合。

1)分区键应具有很高基数。

2)如果是唯一键分区,效果最好。如果是范围查找,不会有性能提升。

3)通过更新数据使数据在分区间移动不被允许。

4)总分区数,应该是2的整数倍。

SQL> create table student_history

(student_id number(10),

degree varchar2(3),

gradution_date date)

PARTITION BY HASH (student_id)

PARTITION 3

STORE IN (hist_tab01, hist_tab02, hist_tab03);

drop table part_ALARMTEXTDATA;

create table part_ALARMTEXTDATA

( ALARMNUMBER VARCHAR2(16) NOT NULL ,

ALARMTEXT VARCHAR2(255) NOT NULL ,

SERIAL NUMBER(38) NOT NULL)

PARTITION BY HASH (ALARMNUMBER)

(part_ALARMTEXTDATA_01 tablespace hxj_partion01,

part_ALARMTEXTDATA_02 tablespace hxj_partion02,

part_ALARMTEXTDATA_03 tablespace hxj_partion03,

part_ALARMTEXTDATA_04 tablespace hxj_partion04);

 组合分区

创建范围分区,在该分区内又再创建散列分区。(一般用在需要范围分区,而范围分区又不均匀的情况下)

1)分区是逻辑结构,表数据被存储在子分区级上。

2)组合分区对:分区级的、历史的、日期的,查询十分好使。

3)组合分区对子分区级的并行操作也十分有用。

4)分区级的连接操作通过使用组合的局部索引支持。

SQL> create table student_history

(student_id number(10),

degree varchar2(3),

gradution_date date)

PARTITION BY RANGE (graduation_date)

SUBPARTITION BY HASH (student_id)

SUBPARTITIONS 2

STORE IN (hist_tab01, hist_tab02)

(

PARTION p_2000 VALUES LESS THEN

(to_date(‘2000-1-1’,’yyyy-mm-dd’)) TABLESPACE hist_tab01,

PARTION p_2001 VALUES LESS THEN

(to_date(‘2001-1-1’,’yyyy-mm-dd’)) TABLESPACE hist_tab02,

PARTION p_error VALUES LESS THEN

(MAXVALUE) TABLESPACE hist_tab03

);

1.3.4.2 索引分区

唯一所以必须是全局的。

分两类,全局与局部索引,前缀与非前缀索引。

 全局与局部索引:与该索引的分区结构是否与被索引基础表结构匹配有关系。

局部索引:索引中的分区与基础表的分区逐个匹配。

- 可以人任何分区上创建局部分区索引。

- 创建后,Oracle自动维护表分区与索引分区之间的关系。

- 分区上的位图索引必须是局部的索引。

SQL> create index dinya_idx_t on dinya_test(item_id)

local

(

partition idx_1 tablespace dinya_space01,

partition idx_2 tablespace dinya_space02,

partition idx_3 tablespace dinya_space03

);

Index created.

SQL>

全局索引:索引中的分区与基础表的分区数不逐个匹配。

- 可以人任何分区上创建全局分区索引,但它自身必须是范围的。

- 最高分区必须以MAXVALUE参数来定义。

- 对分区表的维护操作(drop ,truncate操作等),会导致全局索引无效。此时必须重建。

- 使用global创建与表分区一样多的索引,Oracle也不会认为是局部索引。

SQL> create index dinya_idx_t on dinya_test(item_id)

global partition by range(item_id)

(

partition idx_1 values less than (1000) tablespace dinya_space01,

partition idx_2 values less than (10000) tablespace dinya_space02,

partition idx_3 values less than (maxvalue) tablespace dinya_space03

);

Index created.

global 子句允许指定索引的范围值,这个范围值为索引字段的范围值.

SQL>

SQL> create index dinya_idx_t on dinya_test(item_id);

Index created.

SQL>

 前缀与非前缀索引:与该索引是否有分区键及分区键出现在索引结构内的位置有关系。

前缀索引:索引的最左列与分区键相同。可以是唯一的,也可以不是唯一的。

前缀局部索引:

SQL>create index student_history_lp_idx on student_history (graduation_date) local;

此时默认与基础表分区数一样。以graduation_date范围分区。

前缀全局索引:

略。

非前缀索引:索引的最左列与分区键不相同。可以是唯一的(唯一时分区键必须是索引的子集),也可以不是唯一的。

非前缀局部索引:

SQL>create index student_history_lp_idx on student_history (graduation_date) local;

此时默认与基础表分区数一样。以graduation_date范围分区。

非前缀全局索引:

略。

分区索引不能作为整体一次重建。

alter index local2_alarminfo rebuild partition l_ind2_alarminfo_050915;

1.3.4.3 管理分区

1.1.1.1.1 收集分区的统计数据

可以针对段、分区或子分区级上收集。

例(收集分区表和分区索引):

SQL>execute dbms_stats.gather_table_stats(ownname=>’APPS’,tabname=>’STUDENT_HISTORY’,partname=>’P_1998’,granularity=>’PARTITION’);

SQL>execute dbms_stats.gather_index_stats(ownname=>’SYS’,indname=>’STUDENT_HISTORY_GP_IDX’,partname=>’P_200n’);

from:http://hi.baidu.com/zting0103/blog/item/0b42b029885097fd98250a63.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值