对于js 全局变量 global索引来说,这个UPDATE GLOBAL INDEXES 会影响性能吗

找好工作,快人一步&&&&& 表可以按range、hash、list分区,表分区后,其上的索引和普通表上的索引有所不同,oracle对于分区表上的索引分为2类,即局部索引和全局索引,下面分别对这2种索引的特点和局限性做个总结。
局部索引local index
1.&&&&&&& 局部索引一定是分区索引,分区键等同于表的分区键,分区数等同于表的分区数,一句话,局部索引的分区机制和表的分区机制一样。
2.&&&&&&& 如果局部索引的索引列以分区键开头,则称为前缀局部索引。
3.&&&&&&& 如果局部索引的列不是以分区键开头,或者不包含分区键列,则称为非前缀索引。
4.&&&&&&& 局部索引只能依附于分区表上。
5.&&&&&&& 前缀和非前缀索引都可以支持索引分区消除,前提是查询的条件中包含索引分区键。
6.&&&&&&& 局部索引只支持分区内的唯一性,无法支持表上的唯一性,因此如果要用局部索引去给表做唯一性约束,则约束中必须要包括分区键列。
7.&&&&&&& 局部分区索引是对单个分区的,每个分区索引只指向一个表分区;全局索引则不然,一个分区索引能指向n个表分区,同时,一个表分区,也可能指向n个索引分区,对分区表中的某个分区做truncate或者move,shrink等,可能会影响到n个全局索引分区,正因为这点,局部分区索引具有更高的可用性。
8.&&&&&&& 位图索引只能为局部分区索引。
9.&&&&&&& 局部索引多应用于数据仓库环境中。
全局索引global index
1.&&&&&&& 全局索引的分区键和分区数和表的分区键和分区数可能都不相同,表和全局索引的分区机制不一样。
2.&&&&&&& 全局索引可以分区,也可以是不分区索引,全局索引必须是前缀索引,即全局索引的索引列必须是以索引分区键作为其前几列。
3.&&&&&&& 全局索引可以依附于分区表;也可以依附于非分区表。
4.&&&&&&& 全局分区索引的索引条目可能指向若干个分区,因此,对于全局分区索引,即使只截断一个分区中的数据,都需要rebulid若干个分区甚至是整个索引。
5.&&&&&&& 全局索引多应用于oltp系统中。
6.&&&&&&& 全局分区索引只按范围或者散列分区,hash分区是10g以后才支持。
7.&&&&&&& oracle9i以后对分区表做move或者truncate的时可以用update global indexes语句来同步更新全局分区索引,用消耗一定资源来换取高度的可用性。
8.&&&&&&& 表用a列作分区,索引用b做局部分区索引,若where条件中用b来查询,那么oracle会扫描所有的表和索引的分区,成本会比分区更高,此时可以考虑用b做全局分区索引。
分区索引字典
DBA_PART_INDEXES 分区索引的概要统计信息,可以得知每个表上有哪些分区索引,分区索引的类型(local/global)
Dba_ind_partitions& 每个分区索引的分区级统计信息
Dba_indexes/dba_part_indexes 可以得到每个表上有哪些非分区索引
Alter index idx_name rebuild partition index_partition_name [online nologging]
需要对每个分区索引做rebuild,重建的时候可以选择online(不会锁定表),或者nologging建立索引的时候不生成日志,加快速度。
Alter index rebuild idx_name [online nologging]
对非分区索引,只能整个index重建
阅读(...) 评论()1807人阅读
ORACLE(3)
http://www.itpub.net/thread--1.html我们知道,如果要在一个table partition上做DDL时,是可能会invalidate global index的。但是,如果我们加上update global indexes,或update indexes语句,那么Oracle会自动帮我们update global index,使其继续保持valid状态,而且在其间global index可以继续使用。当我们需要定期清除有global index的partition table的一个partition时,一般有两种办法。其一是exchange partition,其二是truncate partition。这两种办法,加不加update global indexes也是有区别的。我下面就主要对这两种办法讨论update global indexes。建表SQL(其中,HAOPART2和HAOPART是一样的结构):create table haopart (id number not null,c1 char(100),c2 char(200),c3 char(300))PARTITION BY RANGE(id)(PARTITION PART01 VALUES LESS THAN (100),PARTITION PART02 VALUES LESS THAN (200),PARTITION PART03 VALUES LESS THAN (500),PARTITION PART04 VALUES LESS THAN (1000),PARTITION PARTMAX VALUES LESS THAN (MAXVALUE))tablespace USERS;create index haolocal_1 on haopart(c1) local tablespace USERS;create index haolocal_2 on haopart(c2) local tablespace USERS;create index haolocal_3 on haopart(c3) local tablespace USERS;create index haoglobal on haopart(id,c1,c2,c3) global tablespace USERS ;insert into haopartselect rownum,object_name,object_name,object_namefrom dba_这样HAOPART就有3个local indexes和1个global index。临时表建表SQL(其中,HAOTMP和HAOTMP2是一样的结构):create table haotmp(id number not null,c1 char(100),c2 char(200),c3 char(300))create index tmphao_1 on haotmp(c1) tablespace USERS;create index tmphao_2 on haotmp(c2) tablespace USERS;create index tmphao_3 on haotmp(c3) tablespace USERS;一.以exchange partition为例,不加update global indexes时:& & 1. 如果partiton里有数据,global index则会失效SQL& select count(*) from haopart2 partition(part04);&&COUNT(*)----------& && & 500SQL& select count(*) from haotmp2;&&COUNT(*)----------& && && &0SQL& alter table haopart2 exchange partition part04 with table haotmp2&&2&&including indexeTable altered.SQL& select INDEX_NAME,STATUS,PARTITIONED from dba_indexes where&&2&&TABLE_NAME='HAOPART2' and PARTITIONED='NO';INDEX_NAME& && && && && && && &STATUS& &PAR------------------------------ -------- ---HAOGLOBAL2& && && && && && && &UNUSABLE NO& & 2.&&如果partition里没有任何数据,新的临时表有数据,global index也会失效。SQL& select count(*) from haotmp2;&&COUNT(*)----------& && & 500SQL&&&select count(*) from haopart2 partition(part04);&&COUNT(*)----------& && && &0SQL& alter index haoglobal2Index altered.SQL& select INDEX_NAME,STATUS,PARTITIONED from dba_indexes where&&2&&TABLE_NAME='HAOPART2' and PARTITIONED='NO';INDEX_NAME& && && && && && && &STATUS& &PAR------------------------------ -------- ---HAOGLOBAL2& && && && && && && &VALID& & NOSQL& alter table haopart2 exchange partition part04 with table haotmp2&&2&&including indexeTable altered.SQL& select INDEX_NAME,STATUS,PARTITIONED from dba_indexes where&&2&&TABLE_NAME='HAOPART2' and PARTITIONED='NO';INDEX_NAME& && && && && && && &STATUS& &PAR------------------------------ -------- ---HAOGLOBAL2& && && && && && && &UNUSABLE NO& & 3.即使partition和临时表都没有数据,也会使global index失效。SQL&&&alter table haopart2 truncate partition part04;Table truncated.SQL& truncate table haotmp2;Table truncated.SQL& alter index haoglobal2Index altered.SQL& select INDEX_NAME,STATUS,PARTITIONED from dba_indexes where&&2&&TABLE_NAME='HAOPART2' and PARTITIONED='NO';INDEX_NAME& && && && && && && &STATUS& &PAR------------------------------ -------- ---HAOGLOBAL2& && && && && && && &VALID& & NOSQL& alter table haopart2 exchange partition part04 with table haotmp2&&2&&including indexeTable altered.SQL& select INDEX_NAME,STATUS,PARTITIONED from dba_indexes where&&2&&TABLE_NAME='HAOPART2' and PARTITIONED='NO';INDEX_NAME& && && && && && && &STATUS& &PAR------------------------------ -------- ---HAOGLOBAL2& && && && && && && &UNUSABLE NO二.以exchange partition为例,加上update global indexes时:& & 1. 无论任何时候,global index都不会失效。SQL& select count(*) from haopart2 partition(part04);&&COUNT(*)----------& && & 500SQL& select count(*) from haotmp2;&&COUNT(*)----------& && &&&56SQL& select INDEX_NAME,STATUS,PARTITIONED from dba_indexes where&&2&&TABLE_NAME='HAOPART2' and PARTITIONED='NO';INDEX_NAME& && && && && && && &STATUS& &PAR------------------------------ -------- ---HAOGLOBAL2& && && && && && && &VALID& & NOSQL& alter table haopart2 exchange partition part04 with table haotmp2&&2&&including indexes without validation&&3&&uTable altered.SQL& select INDEX_NAME,STATUS,PARTITIONED from dba_indexes where&&2&&TABLE_NAME='HAOPART2' and PARTITIONED='NO';INDEX_NAME& && && && && && && &STATUS& &PAR------------------------------ -------- ---HAOGLOBAL2& && && && && && && &VALID& & NO& & 2. 会对原表加Mode=3 TM lock,会对原表做ddl的partition加Mode=6 TM lock。select o.OBJECT_ID,o.OBJECT_NAME,o.SUBOBJECT_NAME,o.OBJECT_TYPE,l.LMODEfrom dba_objects o,v$lock lwhere o.OBJECT_ID=l.ID1and l.TYPE='TM'and l.sid=1094;OBJECT_ID OBJECT_NAM SUBOBJECT_ OBJECT_TYPE& && && && &&&LMODE---------- ---------- ---------- ------------------- ----------& &&&10597 HAOPART& & PART04& &&&TABLE PARTITION& && && && &&&6& &&&10593 HAOPART& && && && && &TABLE& && && && && && && && &3& &&&10604 HAOTMP& && && && && & TABLE& && && && && && && && &6& & 3. exchange partition update global indexes不会block使用global index的select语句,但是由于大量的update index操作(全局索引需要维护),所以会使得查询大量走undo,所以查询会变慢。在如下exchange partition update global indexes命令进行时:alter table haopart exchange partition part04 with table haotmpincluding indexes without validationu在另一个session执行如下走global index的select:select count(*) from haopart where id &=1000;-------------------------------------------------------------------------------| Id&&| Operation& && && &| Name& && &| Rows&&| Bytes | Cost (%CPU)| Time& &&&|-------------------------------------------------------------------------------|& &0 | SELECT STATEMENT&&|& && && &&&|& &&&1 |& &&&4 |&&2902& &(1)| 00:00:35 ||& &1 |&&SORT AGGREGATE& &|& && && &&&|& &&&1 |& &&&4 |& && && && &|& && && & ||*&&2 |& &INDEX RANGE SCAN| HAOGLOBAL | 31744 |& &124K|&&2902& &(1)| 00:00:35 |-------------------------------------------------------------------------------Predicate Information (identified by operation id):---------------------------------------------------& &2 - access("ID"&=1000)Statistics----------------------------------------------------------& && && & 0&&recursive calls& && && & 0&&db block gets& && & 2914&&consistent gets& && && & 0&&physical reads& && && & 0&&redo size&&& && &516&&bytes sent via SQL*Net to client& && &&&469&&bytes received via SQL*Net from client& && && & 2&&SQL*Net roundtrips to/from client& && && & 0&&sorts (memory)& && && & 0&&sorts (disk)& && && & 1&&rows processedStatistics----------------------------------------------------------& && && & 0&&recursive calls& && && & 0&&db block gets& && & 4095&&consistent gets& && && & 0&&physical reads& & &&27052&&redo size& && &&&516&&bytes sent via SQL*Net to client& && &&&469&&bytes received via SQL*Net from client& && && & 2&&SQL*Net roundtrips to/from client& && && & 0&&sorts (memory)& && && & 0&&sorts (disk)& && && & 1&&rows processedStatistics----------------------------------------------------------& && && & 0&&recursive calls& && && & 0&&db block gets& && & 5130&&consistent gets& && && & 0&&physical reads& && &49140&&redo size& && &&&516&&bytes sent via SQL*Net to client& && &&&469&&bytes received via SQL*Net from client& && && & 2&&SQL*Net roundtrips to/from client& && && & 0&&sorts (memory)& && && & 0&&sorts (disk)& && && & 1&&rows processed可见,执行计划是不变的,但是逻辑读不断上升,也产生大量的redo。明显查询了undo。& & 4. exchange partition update global index会阻碍该partition上的dml,但不会阻碍其他partition上的dml。根据第二点,由于这条语句会对该partition加Mode=6 TM lock,所以很显然,该partition是无法做dml的。我们会看到等待事件:enq: TM - contention:TM-3:2:三. 以truncate partition为例,不加update global index时:& & 1.如果partition里有数据,global index会失效。SQL& select count(*) from haopart partition(part04);&&COUNT(*)----------& && & 500SQL& alter table haopart truncate partition part04;Table truncated.SQL& select INDEX_NAME,STATUS,PARTITIONED from dba_indexes where&&2&&TABLE_NAME='HAOPART' and PARTITIONED='NO';INDEX_NAME& && && && && && && &STATUS& &PAR------------------------------ -------- ---HAOGLOBAL& && && && && && && & UNUSABLE NO& & 2. 如果partition里没有数据,global index不会失效。SQL& delete from haopart partition(part04);<span style="color: # rows deleted.SQL&Commit complete.SQL& alter table haopart truncate partition part04;Table truncated.SQL& select INDEX_NAME,STATUS,PARTITIONED from dba_indexes where&&2&&TABLE_NAME='HAOPART' and PARTITIONED='NO';INDEX_NAME& && && && && && && &STATUS& &PAR------------------------------ -------- ---HAOGLOBAL& && && && && && && & VALID& & NO&&& 另外,无论走exchange还是truncate,由于Oracle都需要FTS整个partition来判断一下,这里面到底有没有数据。所以,整个过程会持续比较长。这样就必然对其他查询SQL造成长时间的library cache lock。这点需要注意。
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:69523次
积分:1059
积分:1059
排名:千里之外
原创:31篇
转载:41篇
(1)(1)(7)(2)(1)(1)(1)(38)(1)(1)(9)(10)<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
您的访问请求被拒绝 403 Forbidden - ITeye技术社区
您的访问请求被拒绝
亲爱的会员,您的IP地址所在网段被ITeye拒绝服务,这可能是以下两种情况导致:
一、您所在的网段内有网络爬虫大量抓取ITeye网页,为保证其他人流畅的访问ITeye,该网段被ITeye拒绝
二、您通过某个代理服务器访问ITeye网站,该代理服务器被网络爬虫利用,大量抓取ITeye网页
请您点击按钮解除封锁&ORALCE开发(10)
一.索引介绍
&1.1&索引的创建语法:&
CREATE&UNIUQE&|&BITMAP&INDEX&&schema&.&index_name&
&&&&&&ON&&schema&.&table_name&
&&&&&&&&&&&(&column_name&&|&&expression&&ASC&|&DESC,
&&&&&&&&&&&&&column_name&&|&&expression&&ASC&|&DESC,...)
TABLESPACE&&tablespace_name&
STORAGE&&storage_settings&
LOGGING&|&NOLOGGING
COMPUTE&STATISTICS
NOCOMPRESS&|&COMPRESS&nn&
NOSORT&|&REVERSE
PARTITION&|&GLOBAL&PARTITION&partition_setting&
1)&UNIQUE&|&BITMAP:指定UNIQUE为唯一&#20540;索引,BITMAP为位图索引,省略为B-Tree索引。
2)&column_name&&|&&expression&&ASC&|&DESC:可以对多列进行联合索引,当为expression时即“基于函数的索引”
3)TABLESPACE:指定存放索引的表空间(索引和原表不在一个表空间时效率更高)
4)STORAGE:可进一步设置表空间的存储参数
5)LOGGING&|&NOLOGGING:是否对索引产生重做日志(对大表尽量使用NOLOGGING来减少占用空间并提高效率)
6)COMPUTE&STATISTICS:创建新索引时收集统计信息
7)NOCOMPRESS&|&COMPRESS&nn&:是否使用“键压缩”(使用键压缩可以删除一个键列中出现的重复&#20540;)
8)NOSORT&|&REVERSE:NOSORT表示与表中相同的顺序创建索引,REVERSE表示相反顺序存储索引&#20540;
9)PARTITION&|&NOPARTITION:可以在和未分区表上对创建的索引进行分区
1.2&索引特点:&
第一,通过创建唯一性索引,可以保证数据库表中每一行数据的唯一性。&
第二,可以大大加快数据的检索速度,这也是创建索引的最主要的原因。&
第三,可以加速表和表之间的连接,特别是在实现数据的参考完整性方面特别有意义。&
第四,在使用分组和排序子句进行数据检索时,同样可以显著减少查询中分组和排序的时间。&
第五,通过使用索引,可以在查询的过程中,使用优化隐藏器,提高系统的性能。&
1.3&索引不足:
第一,创建索引和维护索引要耗费时间,这种时间随着数据量的增加而增加。&
第二,索引需要占物理空间,除了数据表占数据空间之外,每一个索引还要占一定的物理空间,如果要建立聚簇索引,那么需要的空间就会更大。&
第三,当对表中的数据进行增加、删除和修改的时候,索引也要动态的维护,这样就降低了数据的维护速度。&
1.4&应该建索引列的特点:
1)在经常需要搜索的列上,可以加快搜索的速度;&
2)在作为主键的列上,强制该列的唯一性和组织表中数据的排列结构;&
3)在经常用在连接的列上,这些列主要是一些外键,可以加快连接的速度;&
4)在经常需要根据范围进行搜索的列上创建索引,因为索引已经排序,其指定的范围是连续的;&
5)在经常需要排序的列上创建索引,因为索引已经排序,这样查询可以利用索引的排序,加快排序查询时间;&
6)在经常使用在WHERE子句中的列上面创建索引,加快条件的判断速度。&
1.5&不应该建索引列的特点:
第一,对于那些在查询中很少使用或者参考的列不应该创建索引。这是因为,既然这些列很少使用到,因此有索引或者无索引,并不能提高查询速度。相反,由于增加了索引,反而降低了系统的维护速度和增大了空间需求。&
第二,对于那些只有很少数据&#20540;的列也不应该增加索引。这是因为,由于这些列的取&#20540;很少,例如人事表的性别列,在查询的结果中,结果集的数据行占了表中数据行的很大比例,即需要在表中搜索的数据行的比例很大。增加索引,并不能明显加快检索速度。&
第三,对于那些定义为blob数据类型的列不应该增加索引。这是因为,这些列的数据量要么相当大,要么取&#20540;很少。&
第四,当修改性能远远大于检索性能时,不应该创建索引。这是因为,修改性能和检索性能是互相矛盾的。当增加索引时,会提高检索性能,但是会降低修改性能。当减少索引时,会提高修改性能,降低检索性能。因此,当修改性能远远大于检索性能时,不应该创建索引。&
1.6&限制索引
限制索引是一些没有经验的开发人员经常犯的错误之一。在SQL中有很多陷阱会使一些索引无法使用。下面讨论一些常见的问题:
&&&1.6.1&&使用不等于操作符(&&、!=)&&&&&&
&&&下面的查询即使在cust_rating列有一个索引,查询语句仍然执行一次全表扫描。&&&&&
&&&select&cust_Id,cust_name&from&customers&where&&cust_rating&&&&'aa';&&&&&&&&
把上面的语句改成如下的查询语句,这样,在采用基于规则的优化器而不是基于代价的优化器(更智能)时,将会使用索引。&&&&&&&&
&&select&cust_Id,cust_name&from&customers&where&cust_rating&&&'aa'&or&cust_rating&&&'aa';
&&特别注意:通过把不等于操作符改成OR条件,就可以使用索引,以避免全表扫描。
&&&1.6.2&使用IS&NULL&或IS&NOT&NULL
&&&使用IS&NULL&或IS&NOT&NULL同样会限制索引的使用。因为NULL&#20540;并没有被定义。在SQL语句中使用NULL会有很多的麻烦。因此建议开发人员在建表时,把需要索引的列设成&NOT&NULL。如果被索引的列在某些行中存在NULL&#20540;,就不会使用这个索引(除非索引是一个位图索引,关于位图索引在稍后在详细讨论)。
&&&1.6.3&使用函数
&&&如果不使用基于函数的索引,那么在SQL语句的WHERE子句中对存在索引的列使用函数时,会使优化器忽略掉这些索引。&下面的查询不会使用索引(只要它不是基于函数的索引)
&select&empno,ename,deptno&from&emp&&where&&trunc(hiredate)='01-MAY-81';
&&&把上面的语句改成下面的语句,这样就可以通过索引进行查找。
select&empno,ename,deptno&from&emp&where&&hiredate&(to_date('01-MAY-81')&#43;0.9999);
&&1.6.4&比较不匹配的数据类型&&&&&&&
也是比较难于发现的性能问题之一。&注意下面查询的例子,account_number是一个VARCHAR2类型,在account_number字段上有索引。
下面的语句将执行全表扫描:
&select&bank_name,address,city,state,zip&from&banks&where&account_number&=&990354;
Oracle可以自动把where子句变成to_number(account_number)=990354,这样就限制了索引的使用,改成下面的查询就可以使用索引:
&select&bank_name,address,city,state,zip&from&banks&where&account_number&='990354';
特别注意:不匹配的数据类型之间比较会让Oracle自动限制索引的使用,即便对这个查询执行Explain&Plan也不能让您明白为什么做了一次“全表扫描”。
1.7&查询索引
查询DBA_INDEXES视图可得到表中所有索引的列表,注意只能通过USER_INDEXES的方法来检索模式(schema)的索引。访问USER_IND_COLUMNS视图可得到一个给定表中被索引的特定列。
1.8&组合索引
当某个索引包含有多个已索引的列时,称这个索引为组合(concatented)索引。在&Oracle9i引入跳跃式扫描的索引访问方法之前,查询只能在有限条件下使用该索引。比如:表emp有一个组合索引键,该索引包含了empno、&ename和deptno。在Oracle9i之前除非在where之句中对第一列(empno)指定一个&#20540;,否则就不能使用这个索引键进行一次范围扫描。
&&&特别注意:在Oracle9i之前,只有在使用到索引的前导索引时才可以使用组合索引!
1.9&ORACLE&ROWID
通过每个行的ROWID,索引Oracle提供了访问单行数据的能力。ROWID其实就是直接指向单独行的线路图。如果想检查重复&#20540;或是其他对ROWID本身的引用,可以在任何表中使用和指定rowid列。
1.10&选择性
&&&使用USER_INDEXES视图,该视图中显示了一个distinct_keys列。比较一下唯一键的数量和表中的行数,就可以判断索引的选择性。选择性越高,索引返回的数据就越少。
1.11&群集因子(Clustering&Factor)
&&Clustering&Factor位于USER_INDEXES视图中。该列反映了数据相对于已建索引的列是否显得有序。如果Clustering&Factor列的&#20540;接近于索引中的树叶块(leaf&block)的数目,表中的数据就越有序。如果它的&#20540;接近于表中的行数,则表中的数据就不是很有序。
1.12&二元高度(Binary&height)
&&索引的二元高度对把ROWID返回给用户进程时所要求的I/O量起到关键作用。在对一个索引进行分析后,可以通过查询DBA_INDEXES的B-&level列查看它的二元高度。二元高度主要随着表的大小以及被索引的列中&#20540;的范围的狭窄程度而变化。索引上如果有大量被删除的行,它的二元高度也会增加。更新索引列也类&#20284;于删除操作,因为它增加了已删除键的数目。重建索引可能会降低二元高度。
1.13&快速全局扫描
&&从Oracle7.3后就可以使用快速全局扫描(Fast&Full&Scan)这个选项。这个选项允许Oracle执行一个全局索引扫描操作。快速全局扫描读取B-树索引上所有树叶块。初始化文件中的&DB_FILE_MULTIBLOCK_READ_COUNT参数可以控制同时被读取的块的数目。
1.14&跳跃式扫描
&&从Oracle9i开始,索引跳跃式扫描特性可以允许优化器使用组合索引,即便索引的前导列没有出现在WHERE子句中。索引跳跃式扫描比全索引扫描要快的多。
下面的比较他们的区别:
SQL&&set&timing&on
SQL&&create&index&TT_index&on&TT(teamid,areacode);
索引已创建。
已用时间:&&00:&02:&03.93
SQL&&select&count(areacode)&from&
COUNT(AREACODE)
---------------
已用时间:&&00:&00:&08.31
SQL&&select&/*&#43;&index(tt&TT_index&)*/&count(areacode)&from&
COUNT(AREACODE)
---------------
已用时间:&&00:&00:&07.37
1.15&索引的类型
B-树索引&&&&位图索引&&&HASH索引&&&&&索引编排表&&
反转键索引&基于函数的索引&&分区索引&&&本地和全局索引
二.&索引分类
Oracle提供了大量索引选项。知道在给定条件下使用哪个选项对于一个应用程序的性能来说非常重要。一个错误的选择可能会引发死锁,并导致数据库性能急剧下降或进程终止。而如果做出正确的选择,则可以合理使用资源,使那些已经运行了几个小时甚至几天的进程在几分钟得以完成,这样会使您立刻成为一位英雄。下面就将简单的讨论每个索引选项。
下面讨论的索引类型:
B树索引(默认类型)
索引组织表索引
反转键(reverse&key)索引
基于函数的索引
分区索引(本地和全局索引)
位图连接索引
2.1&&B树索引&(默认类型)
&B树索引在Oracle中是一个通用索引。在创建索引时它就是默认的索引类型。B树索引可以是一个列的(简单)索引,也可以是组合/复合(多个列)的索引。B树索引最多可以包括32列。
在下图的例子中,B树索引位于雇员表的last_name列上。这个索引的二元高度为3;接下来,Oracle会穿过两个树枝块(branch&block),到达包含有ROWID的树叶块。在每个树枝块中,树枝行包含链中下一个块的ID号。
树叶块包含了索引&#20540;、ROWID,以及指向前一个和后一个树叶块的指针。Oracle可以从两个方向遍历这个二叉树。B树索引保存了在索引列上有&#20540;的每个数据行的ROWID&#20540;。Oracle不会对索引列上包含NULL&#20540;的行进行索引。如果索引是多个列的组合索引,而其中列上包含NULL&#20540;,这一行就会处于包含NULL&#20540;的索引列中,且将被处理为空(视为NULL)。
&&&&&&&&&&&&&&&&&&&&&&&&
技巧:索引列的&#20540;都存储在索引中。因此,可以建立一个组合(复合)索引,这些索引可以直接满足查询,而不用访问表。这就不用从表中检索数据,从而减少了I/O量。
)操作符的查询;
2.2&&位图索引
位图索引非常适合于决策支持系统(Decision&Support&System,DSS)和数据仓库,它们不应该用于通过事务处理应用程序访问的表。它们可以使用较少到中等基数(不同&#20540;的数量)的列访问非常大的表。尽管位图索引最多可达30个列,但通常它们都只用于少量的列。
例如,您的表可能包含一个称为Sex的列,它有两个可能&#20540;:男和女。这个基数只为2,如果用户频繁地根据Sex列的&#20540;查询该表,这就是位图索引的基列。当一个表内包含了多个位图索引时,您可以体会到位图索引的真正威力。如果有多个可用的位图索引,Oracle就可以合并从每个位图索引得到的结果集,快速删除不必要的数据。
适合与决策支持系统;
做UPDATE代价非常高;
非常适合OR操作符的查询;
基数比较少的时候才能建位图索引;
技巧:对于有较低基数的列需要使用位图索引。性别列就是这样一个例子,它有两个可能&#20540;:男或女(基数仅为2)。位图对于低基数(少量的不同&#20540;)列来说非常快,这是因为索引的尺寸相对于B树索引来说小了很多。因为这些索引是低基数的B树索引,所以非常小,因此您可以经常检索表中超过半数的行,并且仍使用位图索引。
当大多数条目不会向位图添加新的&#20540;时,位图索引在批处理(单用户)操作中加载表(插入操作)方面通常要比B树做得好。当多个会话同时向表中插入行时不应该使用位图索引,在大多数事务处理应用程序中都会发生这种情况。
下面来看一个示例表PARTICIPANT,该表包含了来自个人的调查数据。列Age_Code、Income_Level、Education_Level和Marital_Status都包括了各自的位图索引。下图显示了每个直方图中的数据平衡情况,以及对访问每个位图索引的查询的执行路径。图中的执行路径显示了有多少个位图索引被合并,可以看出性能得到了显著的提高。
&&&&&&&&&&&&&&&&&&&&&
如上图图所示,优化器依次使用4个单独的位图索引,这些索引的列在WHERE子句中被引用。每个位图记录指针(例如0或1),用于指示表中的哪些行包含位图中的已知&#20540;。有了这些信息后,Oracle就执行BITMAP&AND操作以查找将从所有4个位图中返回哪些行。该&#20540;然后被转换为ROWID&#20540;,并且查询继续完成剩余的处理工作。注意,所有4个列都有非常低的基数,使用索引可以非常快速地返回匹配的行。
技巧:在一个查询中合并多个位图索引后,可以使性能显著提高。位图索引使用固定长度的数据类型要比可变长度的数据类型好。较大尺寸的块也会提高对位图索引的存储和读取性能。
下面的查询可显示索引类型。
SQL&&select&index_name,&index_type&from&user_
INDEX_NAME&&&&&&&&&INDEX_TYPE
------------------------------&----------------------
TT_INDEX&&&&&&&&&&&&NORMAL
IX_CUSTADDR_TP&&&&NORMAL
B树索引作为NORMAL列出;而位图索引的类型&#20540;为BITMAP。
技巧:如果要查询位图索引列表,可以在USER&_INDEXES视图中查询index_type列。
建议不要在一些联机事务处理(OLTP)应用程序中使用位图索引。B树索引的索引&#20540;中包含ROWID,这样Oracle就可以在行级别上锁定索引。位图索引存储为压缩的索引&#20540;,其中包含了一定范围的ROWID,因此Oracle必须针对一个给定&#20540;锁定所有范围内的ROWID。这种锁定类型可能在某些DML语句中造成死锁。SELECT语句不会受到这种锁定问题的影响。
位图索引的使用限制:
基于规则的优化器不会考虑位图索引。
当执行ALTER&TABLE语句并修改包含有位图索引的列时,会使位图索引失效。
位图索引不包含任何列数据,并且不能用于任何类型的完整性检查。
位图索引不能被声明为唯一索引。
位图索引的最大长度为30。
技巧:不要在繁重的OLTP环境中使用位图索引
2.3&&HASH索引
使用HASH索引必须要使用HASH集群。建立一个集群或HASH集群的同时,也就定义了一个集群键。这个键告诉Oracle如何在集群上存储表。在存储数据时,所有与这个集群键相关的行都被存储在一个数据库块上。如果数据都存储在同一个数据库块上,并且将HASH索引作为WHERE子句中的确切匹配,Oracle就可以通过执行一个HASH函数和I/O来访问数据——而通过使用一个二元高度为4的B树索引来访问数据,则需要在检索数据时使用4个I/O。如下图所示,其中的查询是一个等价查询,用于匹配HASH列和确切的&#20540;。Oracle可以快速使用该&#20540;,基于HASH函数确定行的物理存储位置。
HASH索引可能是访问数据库中数据的最快方法,但它也有自身的缺点。集群键上不同&#20540;的数目必须在创建HASH集群之前就要知道。需要在创建HASH集群的时候指定这个&#20540;。低估了集群键的不同&#20540;的数字可能会造成集群的冲突(两个集群的键&#20540;拥有相同的HASH&#20540;)。这种冲突是非常消耗资源的。冲突会造成用来存储额外行的缓冲溢出,然后造成额外的I/O。如果不同HASH&#20540;的数目已经被低估,您就必须在重建这个集群之后改变这个&#20540;。
ALTER&CLUSTER命令不能改变HASH键的数目。HASH集群还可能浪费空间。如果无法确定需要多少空间来维护某个集群键上的所有行,就可能造成空间的浪费。如果不能为集群的未来增长分配好附加的空间,HASH集群可能就不是最好的选择。如果应用程序经常在集群表上进行全表扫描,HASH集群可能也不是最好的选择。由于需要为未来的增长分配好集群的剩余空间量,全表扫描可能非常消耗资源。
在实现HASH集群之前一定要小心。您需要全面地观察应用程序,保证在实现这个选项之前已经了解关于表和数据的大量信息。通常,HASH对于一些包含有序&#20540;的静态数据非常有效。
技巧:HASH索引在有限制条件(需要指定一个确定的&#20540;而不是一个&#20540;范围)的情况下非常有用。
&&&&&&&&&&&&&&&&&&&&&&&&
2.4&&索引组织表
索引组织表会把表的存储结构改成B树结构,以表的主键进行排序。这种特殊的表和其他类型的表一样,可以在表上执行所有的DML和DDL语句。由于表的特殊结构,ROWID并没有被关联到表的行上。
对于一些涉及精确匹配和范围搜索的语句,索引组织表提供了一种基于键的快速数据访问机制。基于主键&#20540;的UPDATE和DELETE语句的性能也同样得以提高,这是因为行在物理上有序。由于键列的&#20540;在表和索引中都没有重复,存储所需要的空间也随之减少。
如果不会频繁地根据主键列查询数据,则需要在索引组织表中的其他列上创建二级索引。不会频繁根据主键查询表的应用程序不会了解到使用索引组织表的全部优点。对于总是通过对主键的精确匹配或范围扫描进行访问的表,就需要考虑使用索引组织表。
技巧:可以在索引组织表上建立二级索引。
2.5&&反转键索引
当载入一些有序数据时,索引肯定会碰到与I/O相关的一些瓶颈。在数据载入期间,某部分索引和磁盘肯定会比其他部分使用频繁得多。为了解决这个问题,可以把索引表空间存放在能够把文件物理分割在多个磁盘上的磁盘体系结构上。
为了解决这个问题,Oracle还提供了一种反转键索引的方法。如果数据以反转键索引存储,这些数据的&#20540;就会与原先存储的数&#20540;相反。这样,数据1234、1235和1236就被存储成4321、5321和6321。结果就是索引会为每次新插入的行更新不同的索引块。
技巧:如果您的磁盘容量有限,同时还要执行大量的有序载入,就可以使用反转键索引。
不可以将反转键索引与位图索引或索引组织表结合使用。因为不能对位图索引和索引组织表进行反转键处理。
2.6&&基于函数的索引
可以在表中创建基于函数的索引。如果没有基于函数的索引,任何在列上执行了函数的查询都不能使用这个列的索引。例如,下面的查询就不能使用JOB列上的索引,除非它是基于函数的索引:
select&*&from&emp&where&UPPER(job)&=&'MGR';
下面的查询使用JOB列上的索引,但是它将不会返回JOB列具有Mgr或mgr&#20540;的行:
select&*&from&emp&where&job&=&'MGR';
可以创建这样的索引,允许索引访问支持基于函数的列或数据。可以对列表达式UPPER(job)创建索引,而不是直接在JOB列上建立索引,如:
create&index&EMP$UPPER_JOB&on&emp(UPPER(job));
尽管基于函数的索引非常有用,但在建立它们之前必须先考虑下面一些问题:
能限制在这个列上使用的函数吗?如果能,能限制所有在这个列上执行的所有函数吗
是否有足够应付额外索引的存储空间?
在每列上增加的索引数量会对针对该表执行的DML语句的性能带来何种影响?
基于函数的索引非常有用,但在实现时必须小心。在表上创建的索引越多,INSERT、UPDATE和DELETE语句的执行就会花费越多的时间。
注意:对于优化器所使用的基于函数的索引来说,必须把初始参数QUERY&_REWRITE&_&ENABLED设定为TRUE。
select&&count(*)&from&&sample&where&ratio(balance,limit)&&.5;
Elapsed&time:&20.1&minutes
create&index&ratio_idx1&on&sample&(ratio(balance,&limit));
select&&count(*)&from&&sample&where&ratio(balance,limit)&&.5;
Elapsed&time:&7&seconds!!!
2.7&&分区索引
分区索引就是简单地把一个索引分成多个片断。通过把一个索引分成多个片断,可以访问更小的片断(也更快),并且可以把这些片断分别存放在不同的磁盘驱动器上(避免I/O问题)。B树和位图索引都可以被分区,而HASH索引不可以被分区。可以有好几种分区方法:表被分区而索引未被分区;表未被分区而索引被分区;表和索引都被分区。不管采用哪种方法,都必须使用基于成本的优化器。分区能够提供更多可以提高性能和可维护性的可能性
有两种类型的分区索引:本地分区索引和全局分区索引。每个类型都有两个子类型,有前缀索引和无前缀索引。表各列上的索引可以有各种类型索引的组合。如果使用了位图索引,就必须是本地索引。把索引分区最主要的原因是可以减少所需读取的索引的大小,另外把分区放在不同的表空间中可以提高分区的可用性和可靠性。
在使用分区后的表和索引时,Oracle还支持并行查询和并行DML。这样就可以同时执行多个进程,从而加快处理这条语句。
2.7.1.本地分区索引(通常使用的索引)
可以使用与表相同的分区键和范围界限来对本地索引分区。每个本地索引的分区只包含了它所关联的表分区的键和ROWID。本地索引可以是B树或位图索引。如果是B树索引,它可以是唯一或不唯一的索引。
这种类型的索引支持分区独立性,这就意味着对于单独的分区,可以进行增加、截取、删除、分割、脱机等处理,而不用同时删除或重建索引。Oracle自动维护这些本地索引。本地索引分区还可以被单独重建,而其他分区不会受到影响。
2.7.1.1&有前缀的索引
有前缀的索引包含了来自分区键的键,并把它们作为索引的前导。例如,让我们再次回顾participant表。在创建该表后,使用survey_id和survey_date这两个列进行范围分区,然后在survey_id列上建立一个有前缀的本地索引,如下图所示。这个索引的所有分区都被等价划分,就是说索引的分区都使用表的相同范围界限来创建。
&&&&&&&&&&&&&&&&
技巧:本地的有前缀索引可以让Oracle快速剔除一些不必要的分区。也就是说没有包含WHERE条件子句中任何&#20540;的分区将不会被访问,这样也提高了语句的性能。
2.7.1.2&无前缀的索引
无前缀的索引并没有把分区键的前导列作为索引的前导列。若使用有同样分区键(survey_id和survey_date)的相同分区表,建立在survey_date列上的索引就是一个本地的无前缀索引,如下图所示。可以在表的任一列上创建本地无前缀索引,但索引的每个分区只包含表的相应分区的键&#20540;。
&&&&&&&&&&&&&&&&&&&&&&&&
如果要把无前缀的索引设为唯一索引,这个索引就必须包含分区键的子集。在这个例子中,我们必须把包含survey和(或)survey_id的列进行组合(只要survey_id不是索引的第一列,它就是一个有前缀的索引)。
技巧:对于一个唯一的无前缀索引,它必须包含分区键的子集。
2.7.2.&全局分区索引
全局分区索引在一个索引分区中包含来自多个表分区的键。一个全局分区索引的分区键是分区表中不同的或指定一个范围的&#20540;。在创建全局分区索引时,必须定义分区键的范围和&#20540;。全局索引只能是B树索引。Oracle在默认情况下不会维护全局分区索引。如果一个分区被截取、增加、分割、删除等,就必须重建全局分区索引,除非在修改表时指定ALTER&TABLE命令的UPDATE&GLOBAL&INDEXES子句。
2.7.2.1&有前缀的索引
通常,全局有前缀索引在底层表中没有经过对等分区。没有什么因素能限制索引的对等分区,但Oracle在生成查询计划或执行分区维护操作时,并不会充分利用对等分区。如果索引被对等分区,就必须把它创建为一个本地索引,这样Oracle可以维护这个索引,并使用它来删除不必要的分区,如下图所示。在该图的3个索引分区中,每个分区都包含指向多个表分区中行的索引条目。
&&&&&&&&&&&&&&&&&&&&&&&
&&&&&&&&&分区的、全局有前缀索引
技巧:如果一个全局索引将被对等分区,就必须把它创建为一个本地索引,这样Oracle可以维护这个索引,并使用它来删除不必要的分区。
2.7.2.2&无前缀的索引
Oracle不支持无前缀的全局索引。
2.8&&位图连接索引
位图连接索引是基于两个表的连接的位图索引,在数据仓库环境中使用这种索引改进连接维度表和事实表的查询的性能。创建位图连接索引时,标准方法是连接索引中常用的维度表和事实表。当用户在一次查询中结合查询事实表和维度表时,就不需要执行连接,因为在位图连接索引中已经有可用的连接结果。通过压缩位图连接索引中的ROWID进一步改进性能,并且减少访问数据所需的I/O数量。
创建位图连接索引时,指定涉及的两个表。相应的语法应该遵循如下模式:
create&bitmap&index&FACT_DIM_COL_IDX&on&FACT(DIM.Descr_Col)&from&FACT,&DIM
where&FACT.JoinCol&=&DIM.JoinC
位图连接的语法比较特别,其中包含FROM子句和WHERE子句,并且引用两个单独的表。索引列通常是维度表中的描述列——就是说,如果维度是CUSTOMER,并且它的主键是CUSTOMER_ID,则通常索引Customer_Name这样的列。如果事实表名为SALES,可以使用如下的命令创建索引:
create&bitmap&index&SALES_CUST_NAME_IDX
on&&SALES(CUSTOMER.Customer_Name)&&from&SALES,&CUSTOMER
where&&SALES.Customer_ID=CUSTOMER.Customer_ID;
如果用户接下来使用指定Customer_Name列&#20540;的WHERE子句查询SALES和CUSTOMER表,优化器就可以使用位图连接索引快速返回匹配连接条件和Customer_Name条件的行。
位图连接索引的使用一般会受到限制:
1)只可以索引维度表中的列。
2)用于连接的列必须是维度表中的主键或唯一约束;如果是复合主键,则必须使用连接中的每一列。
3)不可以对索引组织表创建位图连接索引,并且适用于常规位图索引的限制也适用于位图连接索引。&
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:46273次
积分:1591
积分:1591
排名:第17538名
原创:113篇
转载:17篇

我要回帖

更多关于 全局global 的文章

 

随机推荐