1、选择适当的物理结构:为了达到读写尽可能快的目的,必须考虑下面的问题:
1)如果application对rows的访问是按照groups进行的,则需要考虑使用clusters的方式才存储,但clusters对于大量的DML操作会影响性能,所以要考虑application中DML和select操作的数量。
2)对于较大规模的表,使用单独的表空间。对于一个partitioned表,考虑使用多个表空间,从而平均分配磁盘的使用。
3)对于9i中可以允许在同一个DB中有多block size,因此,row size较大的可以有较大的block size。如果设置较大的block size,有助于全表扫描的应用的性能提高。
4)对于小的small transaction占用undo space的回滚信息少,大transaction占用的undo space多,所以所需的free undo space多。
5)对于较大的查询,可以考虑使用多server 进程进程并发查询。
2、数据的访问方法:为了提高性能,可以使用下面的数据访问方法:clusters;indexes:b-tree(普通和翻转关键字)、位图、Function based;索引组织表;固化视图。
1)Clusters:是将一组一个或多个因为有共享columns所以有相同数据块的表放在一起的方法。这些数据块会经常被同时访问或join。这种方法可以使DBA对数据库非规范化,而对user和programmer是透明的。
它在一定程度上降低了磁盘I/O,使用clustered table可以很好的改善join的效率。每个cluster关键字对于多行且值相同的情况下,只会存储一次,所以占用存储空间较小。
但是对于全表扫描,clustered表比nonclustered 表慢很多。
cluster的类型有:
①index cluster:它使用一个被称作cluster index的索引维持cluster中的数据。在index cluster中,对数据的维护、访问、存储cluster index必须是可用的。cluster index用于指向包含给定关键字值的rows的block位置。与普通index不同的是cluster indexes会存储null 值。对于每个cluster index中的关键字,只有一条记录。所以一个cluster index会比普通index的占用空间小。
②hash clusters:它使用hash算法(也已user定义,也可系统指定)计算row的位置。用于查询和DML操作。对于等值查找clusters key,hash cluster的性能要比index cluster的好。
不应使用clusters的情况:经常执行全表扫描的情况;如果对于所有rows的cluster key的数据超出了一到两个Oracle blocks,这样,为了访问在clustered key table中的一条row,Oracle server需要读取有相同值的所有blocks。
不应使用hash clusters的情况:如果表不断增长,并且重建新的、更大的hash cluster不可能的情况下,不应使用hash cluster;如果application经常使用full scans,并且要考虑为table的增大所必须预留的空间。
2)B-Tree indexes:
①使用B-Tree index的情况:当经常访问表中的记录占全表的不足5%时,应该考虑创建B-Tree index;如果在查询时,indexes可以包含所有要访问的字段,这个百分比可以更高些;或是对可以用于进行表的join时,也应考虑建立B- Tree index。
②indexes的增长方式:index总是平衡的,总是自下而上的增长。当rows被增加时,会添加到叶子节点的block上,如果叶子节点的 block被填满,Oracle server会将该block split成两个叶子blocks,每个保存50%的数据。因为新block的添加,叶子节点的父节点也需要添加相应的blocks索引值。如果父节点的 block被填满,父节点也会被split成两个节点,类似与刚才的子节点的split。这个过程会循环进行,直到b-tree保持平衡。index的层 次越多,其效率越低。此外,对于delete操作,会降低index的效率,特别是当有15%的rows被删除,应该考虑rebuilding index。
③为了提高b-tree index的性能,应该定期对index进行rebuild。自9i,可以online创建、rebuild indexes,并且可以并行化进行。当index被rebuild时,相关的table仍然可以被访问和进程DML操作。
ALTER INDEX i_name REBUILD ONLINE;
–ONLINE关键字表示在rebuild时,DML仍可进行。但是不允许并发的DML操作。
④压缩索引:
在创建索引时使用下面的方法可以对index进程压缩:
create index i_name on t_name(col1, col2) compress;
重建索引时可以使用:
alter index i_name rebuild compress;
压缩索引不会多次存储重复出现的关键字从而减少了存储空间的需求。
对于非唯一索引的压缩:Oracle存储重复的关键字作为前缀在index block中,唯一的row id作为后缀存储。
对于唯一索引的压缩:也是类似的,将一致的前缀只保存一次,用于区分唯一性的部分会作为后缀存储。但是这只适用于有多个字段组成的唯一索引,如果只有一个column的唯一索引没有用于share的部分。
3)位图(bitmap)索引:主要适用于distinct的values很少的字段,在其上建立索引。例如性别、工种等字段。但是对于有大量DML操作的表,bitmap index的性能不好,此情况应慎用。
① 适用bitmap index的情况:对于基数较低(low-cardinality)的column创建的索引;如果查询语句中使用多个where条件,Oracle server可以使用逻辑的bit-and或bit-or操作来合并不同columns的bitmaps。
②性能的考虑:bitmap index占用空间较小,每个distinct key的存储时以压缩的方式,bitmap被分成不同的bitmap segments;对于low-cardinality字段非常快;很适合与规模大的只读系统,如决策支持系统(DSS);但是对于DML操作性能比较 慢,不适用于OLTP应用,locking是加载在bitmap-segment上的,不是在记录上的;bitmap index是存储null值的,但b-tree不存储;并发查询、并发DML和并发的CREATE语句在bitmap indexes上是有效的。
③bitmap indexes的创建及管理:
create bitmap index i_name on t_name(col1) storage ( initial 200k next 200k pctincrease 0 maxextents 50) tablespace tsp_name;
对于每个DML操作之后,会对bitmap indexes进行相应的维护,所以对于每个DML操作,每个bitmap segment只会更新一次,既是该bitmap segment中不只一行更新数据。
4)反转关键字索引(reverse key index):在创建索引时会将索引字段按bytes进行反转(reverse)随后将结果作为索引关键字。
①对于一个不断增长的关键字,如由sequence产生的id,可以通过使用reverse key index避免索引的不断split。但是对于常使用范围查找的应用,只能使用全表扫描。
②创建reverse key index:
create index i_name on t_name(col1) reverse pctfree 30 storage( intial 200k next 200k pctincrease 0 maxextents 50) tablespace i_tspname;
或者
create index i_name on t_name(col1);
alter index i_name rebuild reverse;
5)组织索引表(IOT——index-organized table):类似与mysql中的innodb的存储结构,具体结构如下图:
适用于频繁通过primary key或primary key的前缀访问数据的情况。但是必须要求有primary key的限制。它加快了通过key查找数据的速度,并且从table和index整体上节省空间。
①在IOT中,没有常规表中的那种物理上的row id的概念,而是引入了逻辑row id的概念,它是以变长的方式存储的,其size要依靠primary key的值。
对于IOT中数据的访问有两种方法:
i)物理猜测guess,访问时间等同于物理rowid的访问时间
ii)当guess失败,则通过primary key访问IOT中的数据
(guess就是基于row所在的文件和block访问,block的地址在表建立时是精确的,但是如果leaf block进行了拆分split是,就发生了改变。如果guess失败,则通过primary key进行访问。)这里没太搞懂啊:(
②创建
CREATE TABLE countries
( country_id CHAR(2) CONSTRAINT country_id_nn NOT NULL,
country_name VARCHAR2(40),
currency_name VARCHAR2(25),
currency_symbol VARCHAR2(3),
map BLOB,
flag BLOB,
CONSTRAINT country_c_id_pk PRIMARY KEY (country_id))
ORGANIZATION INDEX
PCTTHRESHOLD 20
OVERFLOW TABLESPACE USERS;
影响IOT的行溢出的三个主要因素有:
** pctthreshold:此子句指明了在index block中容纳一行数据可使用块空间的百分比。如果one row数据超过基于此值计算的大小,所有的在including子句之后的字段将被移入overflow segment。如果overflow没有被定义,则这种row溢出转移将被拒绝。PCTTHRESHOLD默认值是50必须在0到50之间。
** including:后跟一个字段,如果数据行的长度超过了PCTTHRESHOLD指定的可用空间,从这个字段之后将数据行分为两段,后面的部分放入溢出段中;
** overflow TABLESPACE :指明当index-organized表数据超出pctthreshold时,将部分columns放入data segment。
③IOT的字典视图:
④使用mapping table
create table countries
( country_id char(2) constaint country_id_nn not null,
country_name varchar2(40),
currency_name varchar2(25),
currency_symbol varchar2(3),
constraint country_c_id_pk primary key (country_id))
organization index mapping table tablespace users;
当在索引组织表上创建位图索引同heap table上创建bitmap是类似的,只是在组织索引表中的rowid对应的不是基础表,而是相应的映射表(mapping table)。mapping table主要是维护一个逻辑row id(访问组织索引表所需的)到physical row id(访问位图索引所需的)的映射。每个组织索引表会有一个mapping table,用于全表的映射。在heap organized base table中,用key访问数据时,如果找到相应的key,bitmap记录返回的是物理row id,可以用于基础表的访问。在组织索引表中,位图索引也是用key进行搜索,当找到相应的key,bitmap返回的依然是物理row id,通过查询mapping table,获得相应的逻辑row id,再用于进入guess data block address或是用primary key访问组织索引表
组织索引表中的row发生移动,不会使其上的bitmap indexes不可用,只是使mapping table中的相应逻辑row id不可用,但仍可通过primary key对其进行访问。
对于mapping table的维护:
** 通过对IOT表进行analyze获得mapping table的统计信息
** 查询DBA_INDEXES视图得知当前mapping table的精确度
SELECT INDEX_NAME, PCT_DIRECT_ACCESS FROM DBA_INDEXES WHERE PCT_DIRECT_ACCESS IS NOT NULL;
** 如果需要,使用alter table重建mapping table
alter table t_name mapping table update block references;
6)物化视图(Materialized views)
物化视图既存储视图的定义,又存储视图创建语句的查询结果。可以将物化视图定义的结果会产生一个实际的表,可以对其做类似normal table的定义,将其指派的某个表空间,对其添加索引,进行分区等。如果通过固化视图就可以满足的查询,server会将查询转换为对物化视图的查询, 而不是对基础表的查询。这样,部分代价昂贵的如join或统计的查询就不必重复执行。
①创建:
create materialized view depart_sal_sum
tablespace data parallel (degree 4)
build immediate|deferred refresh fast
enable|disable query rewrite
as
select d.departmet_name, sum(e.salary) from departments d, employees e
where d.departmant_id=e.department_id group by d.department_name;
②refresh 物化视图:具体有两类:
i)完全的refresh:主要是通过truncate 当前的data,通过执行物化视图的创建语句重新插入数据。
ii)fast refresh方法:它只会更新自上次refresh之后发生变化的数据。具体又有两种:
** 使用materialized view logs:此方法中,所有关于视图的基础表的变化都会被捕获并记录到一个log中,将这些log data用于materialized view即可。
** 使用row id范围:此方法需要一个直接装在日志。记录了需要被重新load的row id相关信息。materialized view就利用这些row id进行直接路径的load。
一个视图的定义使用force的refresh类型时,会尽可能的使用fast refresh方法,不得已才会使用complete refresh。默认情况是使用force refresh类型。如果使用never选项,则会抑制所有materialized view的refresh。
③自动refresh可以通过下面方法设置:
** 如果为materialized view设置oncommit选项,视图会在base table每次commit操作后进行refresh。因为操作时异步的,所以不会让user察觉到性能的降低。
** 在具体的时间点:可以使用START WITH和NEXT子句定义每次refresh的具体时间。为了实现此方法,必须将参数JOB_QUEUE_PROCESSES设置为大于0的值。
④可以用DBMS_MVIEW包进行手动的refresh。
** 对具体的某个materialized view进行refresh
DBMS_MVIEW.REFRESH(…)
** 对依赖某个基础表的所有物化视图进行refresh
DBMS_MVIEW.REFRESH_DEPENDENT(…)
** 对所有的materialized view进行refresh
DBMS_MVIEW.REFRESH_ALL_MVIEWS;
为了执行手动refresh job,必须为其设置适当的JOB_QUEUE_PROCESSES和JOB_QUEUE_INTERVAL参数。
⑤物化视图的查询重写(query rewrite):这一过程是通过优化器(optimizer)完成的,对于应用而言是透明的。可以加速对基础表的部分访问。user不需要被明确的赋予 materialized view的权限,只要其有base table的权限,则其发出的相关查询就可以被重写为对物化视图的访问。materialized view也可设置为enable和disable。
进行query rewrite,必须使QUERY_REWRITE_ENABLED设置为true。对于使用query rewrite的user必须有GLOBAL QUERY REWRITE或QUERY REWRITE的权限。后者只允许user对自己schema下面的materialized view进行query rewrite,前者除此还可对其他有权限的schema进行query rewrite。
⑥物化视图在带来效率的同时也会增加占用的额外空间,并且需要refresh的开支。对此在DBMS_OLAP包的sumary advisor可以用于对代价与收益的比较从而辅助觉得materialized view的创建。
vii)对query rewrit的控制分为三个层次:
** 在初始化参数级别上:
OPTIMIZER_MODE:查询重写只有在cost-based优化模式下才能进行。可在session级别动态设置;
QUERY_REWRITE_ENABLED:可设置为true或是false,可在session级别动态设置;
QUERY_REWRITE_INTEGRITY:可设置为ENFORCED(默认值,只有server能确保一致性时——物化视图是最新的并且 query rewrite使用了有效的验证约束的情况下才进行query rewrite)、TRUSTED(物化视图是最新的,此外相信RELY的约束, 就算这个约束没有Enabled和Validated)、 STALE_TOLERATED(query rewrite允许使用没有及时refresh的物化视图)。此参数也是可以在session级别上动态设置的。
** 在sql中使用hints——REWRITE和NOREWRITE,它可以覆盖在创建或alter物化视图是设置的enable query rewrite子句。
** dimensions(这个也没太懂~~~~(>_<)~~~~ )
viii)可以使用dbms_mview包中的EXPLAIN_MVIEW和explain_rewrite对materialized view和query rewrite进行解释。
3、OLTP系统:
主要特点是:集中的insert和update操作,数据不断增长,多事务并发进行。要求高可用性、高速、高度并发、降低恢复时间。
1)空间分配:避免动态的空间分配,应该为tables、cluster、indexes明确指明占用的tablespace。此外通过观察数据增长的规律,设计extent每次分配的大小。
2)indexes:在DB中indexes的创建和维护都是占用一定开支的,所以,索引的创建必须严谨,每个索引的存在必须是实际需要的;在外键上建立 索引有助于在子表数据被修改时不会locking父表中的数据;b-tree索引在OLTP中优于位图索引,因为locking对DML的影响(当DML 操作发生时b-tree索引中只是锁某些rows,但bitmap索引,会locking整个有相同key的rows);可以考虑使用reverse index来解决b-tree中sequence columns的问题;应该定期对indexes进行rebuild。
3)hash clustering:使用hash clusters可以提高等值查询的访问速度。但是对于下面的情况则不适用它:
** 大量insert操作
** 存在大量用更大的columns values对表进行update的操作,因为会引起数据的迁移。
如果表不断增长,可能在hash key上存在大量冲突,从而是部分数据存放在overflow blocks中,为了避免这种情况,正确的评估hashkeys的值。给hash key更大的number,有助于解决冲突。
4)OLTP Application Issues:
* 对于完整性约束,应该使用DB中声明的constraints代替application中code的逻辑限制。这里主要考虑的是参照完整性和约束的check。
* 应该考虑使用Oracle中的共享code对象,如packages、procedures和Functions。
* 应该尽可能使用绑定变量
* 定义恰当的cursor_sharing参数,有助于user共享解析代码。可设置的值有:
EXACT:默认值,只在精确匹配的情况下共享cursors
SIMILAR:如果SQL语句是字面量,则只有当已有的执行计划是最佳时才使用它,如果已有执行计划不是最佳则重新对这个SQL语句进行分析来制定最佳执行计划。
FORCE:如果SQL语句是字面量,则迫使Optimizer始终使用已有的执行计划,无论已有的执行计划是不是最佳的。
4、决策支持系统(DSS/Data Warehouses)
DSS的特点是该application会提取相应的有用数组成容易理解的报表。将OLTP中的数据进行提取、整合、汇总。使用大量的全表扫描。决策者根 据相关的结果做下一步的决策。它需要有快速的响应时间,并且数据应该确保精确。并发查询的特点就是为了data warehouse环境设计的。
1)存储的分配:
* 谨慎的考虑block size和DB_FILE_MULTIBLOCK_READ_COUNT参数的设置。可以考虑适当增大block_size、DB_FILE_MULTIBLOCK_READ_COUNT。
* 确保extent的size是block_size的整数倍。
* 定期执行analyze或是dbms_stats进行表的statistics。
2)indexing:因为大量的查询是通过全表扫描完成的,所以应尽量减少index占用的空间和对其维护带来的开销。
* 可以的话,可以考虑不使用索引,只保留那些需要用于进行筛选查询的index;
* 定期的用不一致的分布数据产生直方图。
* 考虑使用bitmap indexes
* 对于需要快速用关键字查询的data可将相应的表建为IOT。
* 考虑使用index和hash cluster,特别是hash cluster。但不要在定期批量增长的表上建立cluster。
3)application issues:
在data warehouse中,sql的解析时间并不重要,所以可以适当的减小library cache的大小。应该更关注执行计划:尽量使用并发查询。Symmetric multiprocessors (SMP), clustered, or massively parallel processing (MPP)将能很好的提高性能。SQL的调节优化很重要。
有时可以弃用绑定变量,因为:当analyze后产生直方图,可以用于一定的查询优化,但是这种优化只使用在不使用绑定变量的情况。如果使用绑定变量,则optimizer就不会使用直方图了。对此要小心设置cursor_sharing参数的值。
5、混合系统(Hybrid System)