Oracle数据库中的索引详解

<p><strong>一、 ROWID的概念</strong>
</p>
<p>  <a class="channel_keylink" href="http://www.storworld.com/" target="_blank">存储</a>
了row在数据文件中的具体位置:64位编码的数据,A-Z, a-z, 0-9, +, 和 /,</p>
<p>  row在数据块中的<a class="channel_keylink" href="http://www.storworld.com/" target="_blank">存储</a>
方式</p>
<p>  SELECT ROWID, last_name FROM hr.employees WHERE department_id = 20;</p>
<p>  比如:OOOOOOFFFBBBBBBRRR</p>
<p>  OOOOOO:data object number, 对应dba_objects.data_object_id</p>
<p>  FFF:file#, 对应v$datafile.file#</p>
<p>  BBBBBB:block#</p>
<p>  RRR:row#</p>
<p>  Dbms_rowid包</p>
<p>  SELECT dbms_rowid.rowid_block_number('AAAGFqAABAAAIWEAAA') from dual;</p>
<p>  具体到特定的物理文件</p>
<p>  <strong>二、 索引的概念</strong>
</p>
<p>  1、 类似书的目录结构</p>
<p>  2、 <a class="channel_keylink" href="http://oracle.chinaitlab.com/" target="_blank">Oracle</a>
的“索引”对象,与表关联的可选对象,提高SQL查询语句的速度</p>
<p>  3、 索引直接指向包含所查询值的行的位置,减少磁盘I/O</p>
<p>  4、 与所索引的表是相互独立的物理结构</p>
<p>  5、 <a class="channel_keylink" href="http://oracle.chinaitlab.com/" target="_blank">Oracle</a>
自动使用并维护索引,插入、删除、更新表后,自动更新索引</p>
<p><span style="color: #ff0000;">--工作感觉中 所谓oracle自动维护在插入后,其实好像并非如此!不是oracle 独立的进程在 插入后开始维护</span>
</p>
<p><span style="color: #ff0000;">而是在插入这个SESSION中维护,在insert into commit; 语句后维护。</span>
</p>
<p>  6、 语法:CREATE INDEX index ON table (column[, column]...);</p>
<p>  7、 B-tree结构(非bitmap):</p>
<p>  [一]了解索引的工作原理:</p>
<p>  表:emp</p>
<p>  <img src="http://oracle.chinaitlab.com/UploadFiles_7269/200906/20090604001747850.jpg" alt="" width="535" height="190"></p>
<p>  目标:查询Frank的工资salary</p>
<p>  建立索引:create index emp_name_idx on emp(name);</p>
<p><span style="color: #ff0000;"><br>
以下图说明节点和叶节点的关系,节点负责二叉树的路径,如同书目录左边的目录列表 ;</span>
</p>
<p><span style="color: #ff0000;">叶节点就是目录列表右边的页码</span>
</p>
<div id="div6388732" style="text-align: center;"><img id="img6388732" src="http://oracle.chinaitlab.com/UploadFiles_7269/200906/20090604001747314.jpg" border="0" alt=""></div>

<p>
<img id="img9418757" src="http://oracle.chinaitlab.com/UploadFiles_7269/200906/20090604001747158.jpg" border="0" alt=""></p>
<p><span style="color: #ff0000;">索引也会很大化 因为它也要存储些字段和字段的值</span>
</p>

<p><strong>三、 唯一索引</strong>
</p>
<p>  1、 何时创建:当某列任意两行的值都不相同</p>
<p>  2、 当建立Primary Key(主键)或者Unique constraint(唯一约束)时,唯一索引将被自动建立</p>
<p>  3、 语法:CREATE UNIQUE INDEX index ON table (column);</p>
<p>  4、 演示</p>
<p>  <strong>四、 组合索引</strong>
</p>
<p>  1、 何时创建:当两个或多个列经常一起出现在where条件中时,则在这些列上同时创建组合索引</p>
<p>  2、 组合索引中列的顺序是任意的,也无需相邻。但是建议将最频繁访问的列放在列表的最前面</p>
<p>  3、 演示(组合列,单独列)</p>
<p> <strong> 五、 位图索引</strong>
</p>
<p>  1、 何时创建:</p>
<p>  列中有非常多的重复的值时候。例如某列保存了 “性别”信息。</p>
<p>  Where 条件中包含了很多OR操作符。</p>
<p>  较少的update操作,因为要相应的跟新所有的bitmap</p>
<p>  2、 结构:位图索引使用位图作为键值,对于表中的每一数据行位图包含了TRUE(1)、FALSE(0)、或NULL值。</p>
<p>  3、 优点:位图以一种压缩格式存放,因此占用的磁盘空间比标准索引要小得多</p>
<p>  4、 语法:CREATE BITMAP INDEX index ON table (column[, column]...);</p>
<p>  5、 掩饰:</p>
<p>  create table bitmaptable as select * from indextable where owner in('SYS','PUBLIC');</p>
<p>  分析,查找,建立索引,查找</p>
<p> <strong> 六、 基于函数的索引</strong>
</p>
<p>  1、 何时创建:在WHERE条件语句中包含函数或者表达式时</p>
<p>  2、 函数包括:算数表达式、PL/SQL函数、程序包函数、SQL函数、用户自定义函数。</p>
<p>  3、 语法:CREATE INDEX index ON table (FUNCTION(column));</p>
<p>  4、 演示</p>
<p>  必须要分析表,并且query_rewrite_enabled=TRUE</p>
<p>  或者使用提示/*+ INDEX(ic_index)*/</p>
<p><strong>七、 反向键索引</strong>
</p>
<p>  目的:比如索引值是一个自动增长的列:</p>
<div id="div8585510" style="text-align: center;"><img id="img8585510" src="http://oracle.chinaitlab.com/UploadFiles_7269/200906/20090604001748837.jpg" border="0" alt=""></div>
<p>  多个用户对集中在少数块上的索引行进行修改,容易引起资源的争用,比如对数据块的等待。此时建立反向索引。</p>
<p>  性能问题:</p>
<p>  语法:</p>
<p>  重建为标准索引:反之不行</p>
<p> <strong> 八、 键压缩索引</strong>
</p>
<p>  比如表landscp的数据如下:</p>
<p>  site feature job</p>
<p>  Britten Park, Rose Bed 1, Prune</p>
<p>  Britten Park, Rose Bed 1, Mulch</p>
<p>  Britten Park, Rose Bed 1,Spray</p>
<p>  Britten Park, Shrub Bed 1, Mulch</p>
<p>  Britten Park, Shrub Bed 1, Weed</p>
<p>  Britten Park, Shrub Bed 1, Hoe</p>
<p>  ……</p>
<p>  查询时,以上3列均在where条件中同时出现,所以建立基于以上3列的组合索引。但是发现重复值很多,所以考虑压缩特性。</p>
<p>  Create index zip_idx</p>
<p>  on landscp(site, feature, job)</p>
<p>  compress 2;</p>
<p>  将索引项分成前缀(prefix)和后缀(postfix)两部分。前两项被放置到前缀部分。</p>
<p>  Prefix 0: Britten Park, Rose Bed 1</p>
<p>  Prefix 1: Britten Park, Shrub Bed 1</p>
<p>  实际所以的结构为:</p>
<p>  0 Prune</p>
<p>  0 Mulch</p>
<p>  0 Spray</p>
<p>  1 Mulch</p>
<p>  1 Weed</p>
<p>  1 Hoe</p>
<p>  特点:组合索引的前缀部分具有非选择性时,考虑使用压缩。减少I/O,增加性能。</p>
<p><strong>  九、 索引组织表(IOT)</strong>
</p>
<p>  将表中的数据按照索引的结构存储在索引中,提高查询速度。</p>
<p>  牺牲插入更新的性能,换取查询性能。通常用于数据仓库,提供大量的查询,极少的插入修改工作。</p>
<p>  必须指定主键。插入数据时,会根据主键列进行B树索引排序,写入磁盘。</p>
<p> <strong> 十、 分区索引</strong>
</p>
<h3 class="head">语法:</h3>
<pre><em>Table Index<br><br></em>
<br>
CREATE [UNIQUE|BITMAP] INDEX [schema.]<em>index_name</em>
<br><br><br>
ON [schema.]<em>table_name</em>
<br>
[tbl_alias]<br><br>
(<strong>col</strong>
<br>
[ASC | DESC]) <em><strong><span style="font-size: 12pt;">index_clause</span>
<br></strong>
<br>
index_attribs<br><br></em>
<br></pre>
<p><span class="body" style="font-size: 12pt;"><strong><em>index_clauses:<br></em>
</strong>
<span style="font-size: 10pt;">分以下两种情况</span>
</span>
</p>
<h4>1. Local Index</h4>
<pre> 就是索引信息的存放位置依赖于父表的Partition信息,换句话说创建这样的索引必须保证父表是Partition</pre>
<pre>1.1 索引信息存放在父表的分区所在的表空间。但是仅可以创建在父表为HashTable或者composite分区表的。</pre>
<pre> LOCAL STORE IN (<em>tablespace</em>
<br>
)</pre>
<pre>1.2 仅可以创建在父表为HashTable或者composite分区表的。并且指定的分区数目要与父表的分区数目要一致<br><br><span style="color: #0000ff;">LOCAL STORE IN</span>
<br>
(tablespace)<br><br>
(<span style="color: #0000ff;">PARTITION</span>
<br>
[partition<br><br>
[<span style="color: #0000ff;">LOGGING|NOLOGGING</span>
<br>
]<br><br>
[<span style="color: #0000ff;">TABLESPACE</span>
<br>
{tablespace|DEFAULT}]<br><br>
[<span style="color: #0000ff;">PCTFREE</span>
<br>
int]<br><br>
[<span style="color: #0000ff;">PCTUSED</span>
<br>
int]<br><br>
[<span style="color: #0000ff;">INITRANS</span>
<br>
int]<br><br>
[<span style="color: #0000ff;">MAXTRANS</span>
<br>
int]<br><br>
[<span style="color: #0000ff;">STORAGE</span>
<br>
storage_clause]<br><br>
[<span style="color: #0000ff;">STORE IN</span>
<br>
{tablespace_name|<span style="color: #0000ff;">DEFAULT</span>
<br>
]<br><br>
[<span style="color: #0000ff;">SUBPARTITION</span>
<br>
[subpartition [<span style="color: #0000ff;">TABLESPACE</span>
<br>
tablespace]]]])</pre>
<pre></pre>
<pre>1.3 索引信息存放在父表的分区所在的表空间,这种语法最简单,也是最常用的分区索引创建方式。</pre>
<pre> <span style="color: #0000ff;">Local<br><br></span>
<br><br><br>
1.4 并且指定的Partition 数目要与父表的Partition要一致<br><br><span style="color: #0000ff;">LOCAL (PARTITION</span>
<br>
[<em>partition</em>
<br><br><br>
[<span style="color: #0000ff;">LOGGING|NOLOGGING</span>
<br>
]<br><br>
[<span style="color: #0000ff;">TABLESPACE</span>
<br>
{<em>tablespace</em>
<br>
|DEFAULT}]<br><br>
[<span style="color: #0000ff;">PCTFREE</span>
<br><em>int</em>
<br>
]<br><br>
[<span style="color: #0000ff;">PCTUSED</span>
<br><em>int</em>
<br>
]<br><br>
[<span style="color: #0000ff;">INITRANS</span>
<br><em>int</em>
<br>
]<br><br>
[<span style="color: #0000ff;">MAXTRANS</span>
<br><em>int</em>
<br>
]<br><br>
[<span style="color: #0000ff;">STORAGE</span>
<br><a href="http://www.ss64.com/ora/clause_storage.html">storage_clause</a>
<br>
]<br><br>
[<span style="color: #0000ff;">STORE IN</span>
<br>
{<em>tablespace_name</em>
<br>
|<span style="color: #0000ff;">DEFAULT</span>
<br>
]<br><br>
[<span style="color: #0000ff;">SUBPARTITION</span>
<br>
[<em>subpartition</em>
<br>
[TABLESPACE <em>tablespace</em>
<br>
]]]])<br><br></pre>
<h4>Global Index</h4>
<pre> 索引信息的存放位置与父表的Partition信息完全不相干。甚至父表是不是分区表都无所谓的。语法如下:<strong style="color: #0000ff;"><br><br></strong>
<br>
GLOBAL PARTITION BY RANGE (col_list)<br><br>
( PARTITION <em>partition</em>
<br>
VALUES LESS THAN (<em>value_list</em>
<br>
)<br><br>
[LOGGING|NOLOGGING]<br><br>
[TABLESPACE {<em>tablespace</em>
<br>
|DEFAULT}]<br><br>
[PCTFREE <em>int</em>
<br>
]<br><br>
[PCTUSED <em>int</em>
<br>
]<br><br>
[INITRANS <em>int</em>
<br>
]<br><br>
[MAXTRANS <em>int</em>
<br>
]<br><br>
[STORAGE <a href="http://www.ss64.com/ora/clause_storage.html">storage_clause</a>
<br>
] )</pre>
<pre>但是在这种情况下,如果父表是分区表,要删除父表的一个分区都必须要更新Global Index ,否则索引信息不正确<br><br><pre><span style="font-size: 10.5pt; color: blue; font-family: Courier;">ALTER TABLE</span>
<br><span style="font-size: 10.5pt; font-family: Courier;"> <span style="font-family: Times New Roman; font-size: x-small;">TableName</span>
<br></span>
<br><span style="font-size: 10.5pt; font-family: Courier;"> <span style="color: blue;">DROP PARTITION</span>
<br>
PartitionName</span>
<br><span style="font-size: 10pt; color: black; font-family: 'Times New Roman';"> </span>
<br><strong style="color: #0000ff;">Update Global Indexes</strong>
<br></pre>
<br>
分区表、分区索引和全局索引:<br></pre>
<p>  在一个表的数据超过过2000万条或占用2G空间时,建议建立分区表。</p>
<table style="border: 1px dotted #cccccc; width: 95%;" border="0" cellspacing="0" cellpadding="6" align="center"><tbody><tr>
<td>
createtableta(c1int,c2varchar2(16),c3varchar2(64),c4intconstraintpk_taprimarykey(c1))partitionbyrange(c1)(partitionp1valueslessthan(10000000),partitionp2valueslessthan(20000000),partitionp3valueslessthan(30000000),partitionp4valueslessthan(maxvalue));</td>
</tr></tbody></table>
<p>  分区索引和全局索引:</p>
<p>  分区索引就是在所有每个区上单独创建索引,它能自动维护,在drop或truncate某个分区时不影响该索引的其他分区索引的使用,也就是索引不会失效,维护起来比较方便,但是在查询性能稍微有点影响。</p>
<table style="border: 1px dotted #cccccc; width: 95%;" border="0" cellspacing="0" cellpadding="6" align="center"><tbody><tr>
<td>
createindexidx_ta_c2onta(c2)local(partitionp1,partitionp2,partitionp3,partitionp4);或
者createindexidx_ta_c2onta(c2)local;</td>
</tr></tbody></table>
<p>  另外在create unique index idx_ta_c2 on ta(c2) local
;系统会报ORA-14039错误,这是因为ta表的分区列是c1,oracle不支持在分区表上创建PK主键时主键列不包含分区列,创建另外的约束
(unique)也不可以。</p>
<p>  全局索引就是在全表上创建索引,它可以创建自己的分区,可以和分区表的分区不一样,也就是它是独立的索引。在drop或truncate某个分
区时需要创建索引alter index idx_xx rebuild,也可以alter table table_name drop
partition partition_name update global
indexes;实现,但是要花很长时间在重建索引上。可以通过查询user_indexes、user_part_indexes和
user_ind_partitions视图来查看索引是否有效。</p>
<table style="border: 1px dotted #cccccc; width: 95%;" border="0" cellspacing="0" cellpadding="6" align="center"><tbody><tr>
<td> createindexidx_ta_c3onta(c3);</td>
</tr></tbody></table>
<p>  或者把全局索引分成多个区(注意和分区表的分区不一样):</p>
<table style="border: 1px dotted #cccccc; width: 95%;" border="0" cellspacing="0" cellpadding="6" align="center"><tbody><tr>
<td>
createindexidx_ta_c4onta(c4)globalpartitionbyrange(c4)(partitionip1valueslessthan(10000),partitionip2valueslessthan(20000),partitionip3valueslessthan(maxvalue));</td>
</tr></tbody></table>
<p>  注意索引上的引导列要和range后列一致,否则会有ORA-14038错误。</p>
<p>  oracle会对主键自动创建全局索引</p>
<p>  如果想在主键的列上创建分区索引,除非主键包括分区键,还有就是主键建在两个或以上列上。</p>
<p>  在频繁删除表的分区且数据更新比较频繁时为了维护方便避免使用全局索引。</p>
<pre></pre>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值