当前位置:文档之家› 索引存储及使用原理

索引存储及使用原理

clustering_factor 是表征表中数据的存储顺序和某索引字段顺序的符合程度。

一、索引的存储结构索引是一种允许直接访问数据表中某一数据行的树型结构,为了提高查询效率而引入,是一个独立于表的对象,可以存放在与表不同的表空间中。

索引记录中存有索引关键字和指向表中数据的指针(地址)。

对索引进行的I/O 操作比对表进行操作要少很多。

索引一旦被建立就将被Oracle系统自动维护,查询语句中不用指定使用哪个索引。

分类可以按逻辑设计和物理实现来分类。

索引逻辑分类单列索引:基于一列的操作多列索引:组合索引,最多为32列。

组合索引的列不一定与表中列顺序相同。

惟一索引:列的值各不相同。

非惟一索引:列的值允许相同。

基于函数的惟一索引:利用表中一列或多列基于函数表达式所创建的索引。

既可以是B-树,也可以是位图索引。

索引物理分类分区或非分区索引,非分区既可以是B-树,也可以是位图索引。

B-树:包括正常或反转关键字索引,反转关键字在数据库优化中介绍。

位图索引B-树索引索引的存储方式虽然所有索引都使用B 树结构,但术语“B 树索引”通常与存储每个关键字的行标识列表的索引关联。

B 树索引结构至上而下,是根结点、分枝结点及叶子结点,叶子结点中有指向表中数据行的索引行。

叶子结点被双向链表在一起,以方便按索引关键字升序或降序扫描。

索引的顶部为根,其中包含指向索引中下一级的项,下一级为分枝块,分枝块又指向索引中下一级的块,最低一级为叶节点,其中包含指向表行的索引项。

叶块为双重链接,有助于按关键字值的升序和降序扫描索引。

索引项叶节点的格式索引项由以下三部分组成:? 项标题(entry header),存储列数和锁定信息? 关键字列的“长度- 值”(length-value pairs) ,必需成对出现,定义了列长度,紧跟在列长度之后的就是列的值。

? 行的行标识(RowID),包含关键字值。

索引项叶结点的特征在非分区表上的B 树索引中:? 如果多行具有相同的关键字值,并且索引没有被压缩,则关键字值重复存放。

? 没有索引项与所有关键字列都为NULL 的行对应,即如果某列值为Null,则不存储相应的索引项。

如果Where子句中索引的所在列值为null,Oracle将不使用索引进行全表扫描。

? 因为所有行都属于同一段,所以使用受限行标识指向表中的行,使用RowID可以节省索引存储空间。

DML 操作对索引的影响当在表上执行DML 操作时,Oracle 服务器将自动维护所有的索引,下面解释DML命令对索引的影响:? 插入(Insert)操作导致在适当的块中插入索引项。

? 删除(Delete)行只导致逻辑删除索引项,删除的行所用的空间不能用于新项,直到删除块中的所有项。

? 更新(Update)操作将选删除,再插入,除了在创建时,其它任何时候PCTFREE 设置对索引都没有影响,即使索引块空间少于PCTFREE 指定的空间,仍可以向索引块添加新项。

二、查询使用索引探索:§1.1 简介本文简要介绍了CBO成本计算的基本原理,并初步解释了初始化参数optimizer_index_cost_adj和db_file_multiblock_read_count对CBO的影响。

数据库版本为Oracle 9.0.1平台为Windows2000system@FXSB01> select *from v$version;BANNER----------------------------------------------------------------Oracle9i Enterprise Edition Release 9.0.1.1.1 - ProductionPL/SQL Release 9.0.1.1.1 - ProductionCORE 9.0.1.1.1 ProductionTNS for 32-bit Windows: Version 9.0.1.1.0 - ProductionNLSRTL Version 9.0.1.1.1 – Production§1.2 建立测试数据system@FXSB01> @conn test/test@test已连接。

test@FXSB01> -- 建立执行计划表test@FXSB01> @%ORACLE_HOME%\rdbms\admin\utlxplan.sql 表已创建test@FXSB01>test@FXSB01> -- 建立测试表test@FXSB01> -- 表1,2除索引列外有其他列,表3没有其他列test@FXSB01> drop table test12 /表已丢弃。

test@FXSB01> create table test12 (3 n1 number(10),4 c1 char(100)5 )6 /表已创建。

test@FXSB01> drop table test22 /表已丢弃。

test@FXSB01> create table test22 (3 n1 number(10),4 c1 char(100)5 )6 /表已创建。

test@FXSB01> drop table test32 /表已丢弃。

test@FXSB01> create table test32 (3 n1 number(10)4 )5 /表已创建。

test@FXSB01> -- 插入test1唯一值test@FXSB01> begin2 for i in 1..5000 loop3 insert into test1 values(i,'test');4 end loop;5 end;6 /PL/SQL 过程已成功完成。

test@FXSB01> declare2 i number;3 begin4 i := 1;5 for j in 1..5000 loop6 i := mod(j,250);7 insert into test2 values(i,'test');8 insert into test3 values(i);9 end loop;10 end;11 /PL/SQL 过程已成功完成。

test@FXSB01> commit2 /提交完成。

test@FXSB01> -- 建立索引test@FXSB01> create index idx_test1_n1 on test1(n1)2 /索引已创建。

test@FXSB01> create index idx_test2_n1 on test2(n1)2 /索引已创建。

test@FXSB01> create index idx_test3_n1 on test3(n1)2 /索引已创建。

test@FXSB01> analyze table test1 compute statistics2 /表已分析。

test@FXSB01> analyze table test2 compute statistics2 /表已分析。

test@FXSB01> analyze table test3 compute statistics2 /表已分析。

§1.3 计算Cost初探CBO的成本计算主要由物理I/O组成,实际公式为:IO + CPU/1000 + NetIO*1.5IO表示物理I/O请求,’CPU’表示逻辑I/O请求,’NetI/O’表示通过数据库连接访问远程数据库的逻辑I/O请求.CBO会尝试计算所有可能执行计划的物理I/O,保留只需要最小物理I/O的计划.n 通过以下简单的例子,初步探究CBO是如何计算cost的.n 下面是表统计信息和索引统计信息test@FXSB01> select table_name,blocks,num_rows2 from user_tables3 /TABLE_NAME BLOCKS NUM_ROWS------------------------------ ---------- ----------PLAN_TABLETEST1 158 5000TEST2 158 5000TEST3 20 5000test@FXSB01> select2 table_name ,3 num_rows ,4 avg_leaf_blocks_per_key l_blocks,5 avg_data_blocks_per_key d_blocks,6 clustering_factor cl_fac7 from user_indexes8 /TABLE_NAME NUM_ROWS L_BLOCKS D_BLOCKS CL_FAC------------------------------ ---------- ---------- ---------- ----------TEST1 5000 1 1 157TEST2 5000 1 20 5000TEST3 5000 1 15 3875各列的粗略解释:avg_leaf_blocks_per_key:每个索引值的平均叶块数目avg_data_blocks_per_key:每个索引值的平均数据块数目clustering_factor:B树叶块和表数据之间的关系称为CLUSTERINT_FACTOR.索引叶子块指向的数据块越多,该参数值越小,在范围扫描使用索引的性能越好.如果该值与表的块数相接近,表示表行顺次按索引排序;如果该值与表的行数接近,表示表行不是按索引排序.该值很高的索引通常在范围扫描中不使用.通常的规律,如果cl_fac与num_rows接近,那么低于7%的数据扫描,索引仍然有优势。

test@FXSB01> set autotrace trace exptest@FXSB01> select *from test1 where n1 = 1002 /Execution Plan----------------------------------------------------------0 SELECT STATEMENT Optimizer=CHOOSE (Cost=2 Card=1 Bytes=103)1 0 TABLE ACCESS (BY INDEX ROWID) OF 'TEST1' (Cost=2 Card=1 Bytes=103)2 1 INDEX (RANGE SCAN) OF 'IDX_TEST1_N1' (NON-UNIQUE) (Cost=1 Card=1)cost计算:从t1的索引统计信息中得知,idx_test1_n1的l_blocks,d_blocks均为1,cost=1+1=2,索引叶块物理读取cost为1,数据块物理读取cost为1test@FXSB01> select *from test2 where n1 = 1002 /已选择20行。

相关主题