Oracle 9i 整体性能优化概述草稿之三:SQL优化

4 SQL优化 25
4.1 测量SQL性能 25
4.1.1 Explain Plan 25
4.1.2 Top Sql 26
4.1.3 TKPROF 26
4.1.4 AUTOTRACE 29
4.1.5 STATSPACK 31
4.2 优化器模式 31
4.2.1 Analyze-表和索引分析 32
4.2.2 设置优化程序模式 34
4.3 优化应用程序 36
4.3.1 stored outline 36
4.3.2 物化视图 39
4.3.3 索引 40
4.3.4 分区partition 44
4.3.5 cluster 51
4.4 常见优化的SQL书写方法 52


1 SQL优化
数据库系统执行效率差,主要原因是构造不好的SQL语句和效率差的数据库设计。本节主要针对执行效率差的SQL语句的优化进行描述。

1.1 测量SQL性能
1.1.1 Explain Plan
1.1.1.1 获取explain
查找SQL效率差的具体原因。
获得Explain Plan,可通过:
tkprof,explain plan for命令(不会执行SQL操作),autotrace命令(会实际执行SQL操作)。

SQL>@$ORACLE_HOME/rdbms/admin/utlxplan.sql
SQL>explain plan for
Select * from tab;
SQL>select lpad(‘ ‘,4*(level-2))||operation||’ ‘||options||’ ‘||
Object_name “EXECUTION_PLAN”
From plan_table
Start with id = 0
Connect by prior id = parent_id;
(也可通过两个脚本输出$ORACLE_HOME/rdbms/admin/utlxpls.sql---不包含parallel query信息,utlxplp.sql----包含parallel query信息)

1.1.1.2 翻译explain
1)关心是否使用了索引,是否全表扫描。
2)关心执行计划的先后顺序,执行过程中发生了什么事情。


1.1.2 Top Sql
OEM Diagnostics Pack的Top Sql工具。

1.1.3 TKPROF
TKPROF(Trace Kernel Profile),格式化$ORACLE_HOME/admin/$ORACLE_SID/udump(USER_DUMP_DEST目录)里,设置的用户会话跟踪技巧所生成的跟踪文件(含有该跟踪期间该用户的所有活动SQL的相关信息)。

1.1.3.1 设置SQL跟踪
 当前会话级跟踪
SQL>alter session set sql_trace=true; --开启跟踪
SQL>alter session set sql_trace=false; --结束跟踪
这期间当前用户的所有 SQL相关信息都会记录。
 跟踪其他会话
SQL>exec sys.dbms_system.set_sql_trace_in_session(sid,serial#,true); --开启跟踪
SQL>exec sys.dbms_system.set_sql_trace_in_session(sid,serial#,false); --结束跟踪
这期间该sid用户的所有 SQL相关信息都会记录。
Select sid,serial# from v$session;
 实例级跟踪
修改init.ora文件的SQL_TRACE=TRUE;
此时对所有连接数据库的用户都会启动跟踪,需要特别小心,因该操作会在系统产生大量的开销,默认值是FALSE。(?态参数)
查找用户的跟踪文件:
SQL> select s.username,p.spid from v$session s,v$process p
where s.paddr=p.addr and p.background is null and s.sid = &sid;
----跟着文件包含p.spid的编号。
Init.ora文件的max_dump_file_size参数指定文件大小:可设置=10M或=1000(表示1000个OS块大小)或默认unlimited。

1.1.3.2 跟踪文件的分析方法

cqdb% tkprof
Usage: tkprof tracefile outputfile [explain= ] [table= ]
[print= ] [insert= ] [sys= ] [sort= ]
table=schema.tablename Use 'schema.tablename' with 'explain=' option.
explain=user/password Connect to ORACLE and issue EXPLAIN PLAN.
print=integer List only the first 'integer' SQL statements.
aggregate=yes|no
insert=filename List SQL statements and data inside INSERT statements.
sys=no TKPROF does not list SQL statements run as user SYS.
record=filename Record non-recursive statements found in the trace file.
waits=yes|no Record summary for any wait events found in the trace file.
sort=option Set of zero or more of the following sort options:
prscnt number of times parse was called
prscpu cpu time parsing
prsela elapsed time parsing
prsdsk number of disk reads during parse
prsqry number of buffers for consistent read during parse
prscu number of buffers for current read during parse
prsmis number of misses in library cache during parse
execnt number of execute was called
execpu cpu time spent executing
exeela elapsed time executing
exedsk number of disk reads during execute
exeqry number of buffers for consistent read during execute
execu number of buffers for current read during execute
exerow number of rows processed during execute
exemis number of library cache misses during execute
fchcnt number of times fetch was called
fchcpu cpu time spent fetching
fchela elapsed time fetching
fchdsk number of disk reads during fetch
fchqry number of buffers for consistent read during fetch
fchcu number of buffers for current read during fetch
fchrow number of rows fetched
userid userid of user that parsed the cursor


For exemple:
%tkprof cqdb_ora_20127.trc tk.txt insert=trace.sql sort=fchrow
%tkprof cqdb_ora_20127.trc tk.txt print=10 record=sql.txt
%tkprof cqdb_ora_20127.trc tk.txt sys=no explain=c_perf/c_perf@cqdb
充分利用explain、排序、insert等功能进行选择性的观察。

1.1.3.3 跟踪文件的分析结果

********************************************************************************
count = number of times OCI procedure was executd
cpu = cpu time in seconds executing
elapsed = elapsed time in seconds executing
disk = number of physical reads of buffers from disk
query = number of buffers gotten for consistent read
current = number of buffers gotten in current mode (usually for update)
rows = number of rows processed by the fetch or execute call
********************************************************************************


可以直接观察生成的分析文件,也可使用insert选项,插入数据库观察。如果是insert到数据库,则CPU和ELAP的时间,将从秒换算成10的6次方变成微秒。

寻找含有下列一个或多个缺点的SQL语句:
1)占用过多的CPU资源。
2)parse、execute、fetch消费时间过长。
3)从物理磁盘读取太多的数据块,而从SGA读取太少的块。
4)访问许多块,而只返回几行。

例:
********************************************************************************
select *
from
c_unicom.adp_data_num where ne_id = '1006000300000000' and table_name =
'adp_o_c_perf_bts' and start_time = to_date('2005-06-20 09:00:00',
'yyyy-mm-dd hh24:mi:ss') and stop_time = to_date('2005-06-20 09:30:00',
'yyyy-mm-dd hh24:mi:ss')

call count cpu elapsed disk query current rows
------- ------ -------- ---------- ---------- ---------- ---------- ----------
Parse 1 0.00 0.00 0 0 0 0
Execute 1 0.00 0.00 0 0 0 0
Fetch 1 0.00 0.00 0 3 0 0
------- ------ -------- ---------- ---------- ---------- ---------- ----------
total 3 0.00 0.00 0 3 0 0

Misses in library cache during parse: 1
Optimizer goal: CHOOSE
Parsing user id: 55 (C_UNICOM)

Rows Row Source Operation
------- ---------------------------------------------------
0 TABLE ACCESS BY INDEX ROWID ADP_DATA_NUM
0 INDEX UNIQUE SCAN IDX_ADP_DATA_NUM (object id 1892001)

Rows Execution Plan
------- ---------------------------------------------------
0 SELECT STATEMENT GOAL: CHOOSE
0 TABLE ACCESS (BY INDEX ROWID) OF 'ADP_DATA_NUM'
0 INDEX (UNIQUE SCAN) OF 'IDX_ADP_DATA_NUM' (UNIQUE)
********************************************************************************

1.1.4 AUTOTRACE
Autotrace在生存explain 前,会实际执行那条被查询的SQL语句。
1)首先需要使用$HOME_HOME/rdbms/admin/utlplan.sql创建plan_table表。
2)使用$HOME_HOME/rdbms/admin/plustrce.sql脚本创建plustrace角色,把该角色赋予将使用autotrace的用户。

只能在SQL*plus中使用。如下:
SQL> set autotrace on
(同时还提供了如下选项:
SET AUTOT[RACE] {OFF | ON | TRACE[ONLY]} [EXP[LAIN]] [STAT[ISTICS]]
On statistics 只显示结果和统计,不包括计划
On explain 只显示结果和计划,不包括统计数据
Traceonly 只显示计划和统计,不包括结果
Traceonly statistics 仅显示统计
Off 关闭autotrace

SQL> select * from c_unicom.adp_data_num where ne_id = '1006000300000000' and table_name = 'o_c_perf_cellcircuit' and start_time = to_date('2005-06-20 09:00:00','yyyy-mm-dd hh24:mi:ss') and stop_time = to_date('2005-06-20 09:30:00','yyyy-mm-dd hh24:mi:ss');
Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT ptimizer=CHOOSE
1 0 TABLE ACCESS (BY INDEX ROWID) OF 'ADP_DATA_NUM'
2 1 INDEX (UNIQUE SCAN) OF 'IDX_ADP_DATA_NUM' (UNIQUE)


Statistics
----------------------------------------------------------
0 recursive calls
0 db block gets
4 consistent gets
1 physical reads
0 redo size
1418 bytes sent via SQL*Net to client
655 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
1 rows processed


 recursive calls:在用户级和系统级产生的递归调用的数目。
Oracle数据库维护用于内部处理的表。当它需要改变那些表时,Oracle数据库生成一个内部SQL语句,该语句反过来产生一个递归调用。
简而言之,递归调用就是代表你的SQL执行的SQL语句。因此,如果你必须解析该查询,例如,你可能必须运行一些其他的查询来得到数据字典的信息。这就是递归调用。空间管理、安全性检查、从SQL中调用PL/SQL--所有这些都会引起递归SQL调用。
 db block gets:当前块被请求的次数。
当存在时,当前模式块将被立即检索,而不会以一致读的方式检索。通常,查询检索的块如果在查询开始时存在,它们就被检索。当前模式块如果存在就立即被检索,而不是从一个以前的时间点检索。在一个SELECT期间,你可以看到当前模式检索,因为对于需要进行全面扫描的表来说,需要读数据字典来找到范围信息(因为你需要"立即"信息,而不是一致读)。在修改期间,为了向块中写入内容,你要以当前模式访问块。

 consistent gets:对于一个块一致读被请求的次数。
这是以"一致读"模式处理的块数。为了回滚一个块,这将包括从回滚段读取的块的数目。例如,这是你在SELECT语句中读取块的模式。当你进行一个指定的UPDATE/DELETE操作时,你也以一致读模式读取块,然后以当前模式获得块以便实际进行修改
 physical reads:从磁盘读取的数据块的总数。
这个数等于"physical reads direct"(物理上直接读取的块数)的值加上读入缓存区的所有块数。
 redo size:所产生的以字节为单位的redo(重做日志)总数。
 bytes sent via SQL*Net to client:从前台进程发送到客户端的字节总数。
一般来说,这是结果集的整体大小。
 bytes received via SQL*Net from client:通过网络从客户端收到的字节总数。  
一般来说,这是通过网络传输的你的查询的大小。
 SQL*Net roundtrips to/from client:发送到客户端和从客户端接收的网络消息总数。  
一般来说,这是为了得到回答在你和服务器间发生的交互次数。当你在SQL*Plus中增加ARRAYSIZE设置值时,你将看到对于返回多条记录的SELECT语句,这个数字会下降(更少的来回交互,因为每获取N条记录是一个来回)。当你减少你的ARRAYSIZE值时,你将看到这个数字增加。
 sorts (memory):完全在内存中执行、且不需要任何磁盘写的排序操作的数目。  
没有比在内存中排序更好的排序了,除非根本没有排序。排序通常是由表连接SQL操作的选择条件设定所引起的。
 sorts (disk):至少需要一次磁盘写的排序操作的次数。
需要磁盘输入/输出的排序操作需要耗费大量资源。
 rows processed:这是由SELECT语句所返回的或是由INSERT、UPDATE或DELETE语句修改的总行数。


1.1.5 STATSPACK
参考:
A87503-02
21章 Using STATSPACK

1.2 优化器模式
一条SQL语句会有很多执行计划,但只有一个是最佳的。找到最佳的就是优化的任务。

Oracle9i有两种优化器模式可以选择:
• Rule-based:
– Uses a ranking system,使用一组预定义的“经验法则”。
– Syntax- and data dictionary–driven
• Cost-based:
– Chooses least-cost path
– Statistics-driven
Rule-based模式满足向后兼容,而Cost-based模式中的成本大部分来自于逻辑读的次数,Oracle现在推荐使用Cost-based模式。
使用RBO可能会导致过多的I/O,比如一张小表,如果选择RBO有索引在上面,则至少产生索引和数据两次I/O。
基数-cardinality(列里不同的数据越多,表示基数越高),RBO也是无法判断使用的,可能导致更多的I/O。
而CBO,会 考虑许多执行计划,然后选择最低执行代价的执行计划执行。为了确定这些代价,CBO主要依赖存储在数据库字典中的表和索引的相关统计数据,该字典含有:
- 每个表或索引的大小,含有的行数,所使用的数据库块数量。
- 每个表行的长度。
- 索引列中列数据的基数。
默认下,这些统计数据在数据库中是不存在的,他们是在表或索引被分析时收集和存储在数据库中的。

1.2.1 Analyze-表和索引分析
(11i前,Oracle自己的企业资源规划ERP应用程序包被明确的采用使用了RBO,如果切换到CBO通常会引起性能下降)
由于递归数据字典查询严重依赖具体的访问路径才能更好的运行,所以sys模式的对象不应该分析,若已经分析,则应该使用dbms_utility.analyze_schema(‘sys’,’delete’)命令删除。

1.2.1.1 对象Analyze
 全扫描型分析
SQL>analyze index idx3_ne_cell compute statistics;
//收集索引idx3_ne_cell的统计数据。
SQL>analyze table o_c_perf_cell compute statistics;
//通过资源密集型的检查表o_c_perf_cell的每一行,来统计表o_c_perf_cell及其上所有索引的统计数据。

 样本型分析
使用默认样本:
如果是一个大表,避免占用资源,可使用:
SQL>analyze table o_c_perf_cell estimate statistics;

SQL>analyze index idx3_o_c_perf_cell estimate statistics;
//这样会使用表或索引的一个样本来估算表或索引的统计数据。默认样本为1064行。统计数据乎和compute一样准确。
指定样本:
也可通过如下方法指定样本大小:
SQL>analyze table o_c_perf_cell estimate statistics
Sample 35 percent;
//如果percent超过50%,则使用compute代替estimate。

SQL>analyze index idx3_o_c_perf_cell estimate statistics
Sample 500 rows;
其他选项:
如SQL>analyze table c_perf_tch estimate statistics
for columns ne_id size 200;
//取代检查所有列
//size范围:1~254,默认75,指定该表被划分为多少个片段检查基数,划分越多计算越准确;否则数据库会记录该列的最大值和最小值,假设数据为正态分布,而事实如果是这样,曾经有查询17个小时的案例;如果指定size,分别记录下这些片段直方图的最大最小,不做其他修改,可以优化成3分钟。(查询直方图:dba_histograms)
//如果没有具体指定,则CBO假设数据是正态分布的,计算误差会更大。
还可以使用的选项:
for table 只收集表统计,不收集列统计
for columns 只收集指定列的列统计
for all columns 只收集所有列的列统计
for all indexes 只收集表上所有索引的统计,而不收集表的统计
for all indexed columns 只收集已索引列的统计
for all local indexes 收集谋个已知分区表的所有本地索引的列统计数据

删除分析数据:
SQL>analyze table c_perf_sdcch delete statistics;

1.2.1.2 模式Analyze
Oracle 提供了DBMS_UTILITY(旧,8i或没有新的包可用时才用)和DBMS_STATS(新,Oracle强烈建议9i后使用)PL/SQL包来分析用户模式中的每个表和索引。
使用DBMS_STATS包。

 DBMS_UTILITY包例:
SQL>execute dbms_utility.analyze_schema(‘scott’,’estimate’,0,40,’for all indexed columns size 40’);
//用户模式分析
//0:估算的样本行数;如果为0,则适用40作为比例;如果非0,则40失效。
完整数据库分析:
SQL> execute dbms_utility.analyze_database(‘estimate’,0,40,’for all indexed columns size 40’);
//由于递归数据字典查询严重依赖具体的访问路径才能更好的运行,所以sys模式的对象不应该分析,若已经分析,则应该使用dbms_utility.analyze_schema(‘sys’,’delete’)命令删除。

 DBMS_STATS包例:
(具体参考:A89852-02-63章)
新功能:
- 新统计数据生成前备份旧统计数据,允许恢复旧的统计数据。
- 估算统计数据时,采用块作为随机样本,不再使用行做为随机样本。
- 通过并行执行收集统计数据。
- 自动收集易变表的统计数据,绕过静态表。
参考的过程:
gather_table_stats
gather_index_stats
gather_schema_stats
gather_database_stats
gather_system_stats //收集服务器的I/O和CPU性能统计数据
1)收集某用户的某表统计数据
例:SQL>execute dbms_stats.gather_table_stats(‘JOE’,’EMPLOYEE’);
1) 收集用户模式的统计数据
gather_schema_stats的选项:
gather stale:在已使用alter table .. monitoring的模式中,每个表都有自己的以收集统计数据。
gather empty:以前没有分析过的对象,都将有自己的统计数据。
gather auto:根据对象活动情况,Oracle自动使用恰当的分析方法分析确定的对象。(还有REPEAT-使用相同数量的直方图段做为原始直方图,SKEWONLY-任何列数据发生变化时立即生成直方图统计数据)
例:SQL>execute dbms_stats.gather_schema_stats(ownname=>'LOOP_TEST',
estimate_percent=>DBMS_STATS.AUTO_SAMPLE_SIZE,
method_opt=>'for all columns size AUTO');
2) 收集服务器统计数据
以便在同等I/O密集和CPU密集型执行计划中,如果受I/O,而不是CPU束缚,则 Oracle选择一个低I/O的执行计划。
- 创建一个表来存储服务器统计数据,否则要求该用户具有 SYSDBA权限存储在数据字典里。
SQL>execute dbms_stats.create_stat_table(‘SYSTEM’,’SYSTEM_STATISTICS’,’TOOLS’);

- 收集统计数据
SQL>execute dbms_stats.gather_system_stats(interval=>180,stattab=>’SYSTEM_STATISTICS’,statid=>’05-MAR-02’);
//interval选项要求init.ora的job_queue_processes设置成非0值。
手工指定:
SQL>execute dbms_stats.gather_system_stats(gathering_mode=>’START’,stattab=>’SYSTEM_STATISTICS’);
SQL>execute
Dbms_stats.gather_system_stats(gathering_mode=>’STOP’);

1.2.1.3 查看分析数据
各类统计数据的位置:
表:dba_tables;
索引:dba_indexes;
列:user_tab_col_statistics;
柱状图(histogram)保存在dba_histogram/dba_tab_histograms中。

1.2.1.4 分析数据的导入导出
由于CBO是根据统计数据判断使用最佳的执行计划,所以在生产线上的数据库,可以把他们的统计数据导入到开发库里,这样就可以在开发环境中得到与生产线上同样的执行计划了。
1)在生产数据库和开发数据,TOOLS表空间创建JOE模式的STATS表。
SQL>execute dbms_stats.create_stat_table(‘JOE’,’STATS’,’TOOLS’);
2)获取 生产数据库JOE模式的统计数据,并放入STATS表。
SQL>execute dbms_stats.export_schema_stats(‘JOE’,’STATS’);
3)使用export方式,把表STATS从生产数据库导出,并ftp到开发数据库
%exp joe/Sidney@prod file=stats.dmp tables=(STATS) log=stats.log
3) 使用import方式,把表STATS统计数据导入到开发数据库
%imp joe/Sidney@devl file=stats.dmp log=stats.log full=y
4) 把导入到开发数据库的STATS的统计数据,移到数据字典中
SQL>execute dbms_stats.import_schema_stats(‘JOE’,’STATS’);

1.2.2 设置优化程序模式
可以在三个级别设置优化程序模式(按优先级):实例级 < 会话级 < 语句级。
(从9i开始,可以通过init.ora的optimizer_features_enable参数指定要CBO的版本)

 实例级
修改init.ora的optimizer_mode参数指定,一共可设置5个值。
- RULE :该模式下,不管是否有统计数据,将对所有会话使用BRO的优化模式。除非SQL语句得到了CBO的模式提示。
- CHOOSE :如果执行的操作中包含的某个表或某个表的索引有统计数据,则都使用CBO的方式(没有统计数据的对象,Oracle飞快的估计其统计数据),如果都没有统计数据,则使用RBO的方式。
此时CBO默认的优化方式是ALL_ROWS。
注意,以下的结构不管怎么管理,都会使用CBO:
 已分区的表和索引
 索引组织表
 反向键索引
 基于函数的索引
 位图索引
 查询重写
 物化视图

- FIRST_ROWS :类似使用CHOOSE,只是在使用CBO时,尽可能快的返回一个查询所获得的若干行。
- FIRST_ROWS_n :类似使用CHOOSE,只是在使用CBO时,尽可能快的返回一个查询所获得的1-10-100-1000等所指定的n行。
- ALL_ROWS :类似使用CHOOSE,只是在使用CBO时,尽可能快的返回一个查询所获取的所有的行。用来改进查询总的吞吐量。
它是默认的CBO优化模式选项。

 会话级
使用alter session set optimizer_mode = xxxxx;
来修改当前SQL*PLUS的会话默认优化模式。可使用的值与实例级可使用的5个值一样。

 语句级
通过使用提示的方式来指定语句的优化模式。如果语法写错,则SQL把它当成一个注释,不会提示错误。
常见提示:
/*+ RULE */
/*+ FIRST_ROWS */
/*+ FIRST_ROWS_n */
/*+ ALL_ROWS */
/*+ FULL */ 如:/*+ FULL NE_MSC */
/*+ INDEX */ 如:/*+ INDEX PK_NE_CELL */
/*+ REWRITE */ 如:迫使优化程序动态重写该查询,以便利用一个物化视图(如果她是可用的)。
/*+ PARALLEL */ 如:使指定操作并行的执行

所有提示可参考:A87503-02第5章

1.3 优化应用程序
通过测量的SQL性能数据,和了解的优化器默认的工作方式,我们就可以通过两种技巧来改善其性能:
1)改进执行计划的执行路径:
- 固定存储最佳计划 stored outline。
- 使用物化视图。
2)最大限度的减少I/O次数:
- 索引
- 分区
- 聚镞cluster

1.3.1 stored outline
对于每一个查询,optimizer都会准备一个定义了操作执行顺序和方法的操作树(执行计划),oracle server根据这个执行计划执行语句。通过固定执行计划,可以强制应用通过一种理想的方式访问数据,并且一个稳定的执行计划可以经历数据库的变化而保持不变(不管是否重新统计数据,修改了init.ora参数等)。固定执行计划通过创建stored outline实现,outline使用cost-based的optimizer,因为其由一系列的hints组成。
执行计划的固定依赖于当判定一个查询是否存在stored outline时查询语句是否完全一致,与判定shared pool里一个执行计划是否可以重用时的匹配方式是一致的(即要求两条语句完全一样,哪怕大小写都要保持一致)。
Outline被保存在outln schema中。

alter table outln.ol$ move lob(sql_text) store as (tablespace tools); alter table outln.ol$ move tablespace tools lob(sql_text) store as(tablesapce tools);
能移动blob,但不能移动long。

1.3.1.1 创建stored outline
 准备工作:
1)确定需要使用outline的SQL语句。
报表分析的语句可考虑使用+动态变量。
2)确定能否这些大纲分成不同的类别。
不应该把init.ora 中的CREATE_STORED_OUTLINES参数设置成true(9.2版已取消改参数),因不是所有语句都适合把执行计划固定。
3)更改outln模式。
- 修改outln用户的密码,并设置缺省和临时表空间设置成非SYSTEM表空间。
- 使用exp或move方法,把存储大纲的表从SYSTEM表空间移到其他表空间。
(select owner,segment_name,segment_type,tablespace_name from dba_segments where wner='OUTLN';
有:OL$,OL$HINTS,OL$NODES)

 创建存储大纲:
c_unicom : 大纲类别
adp_data_num_outline :大纲名称

SQL> create or replace outline adp_data_num_outline
for category c_unicom on
select /*+ all_rows */ * from c_unicom.adp_data_num
where ne_id = '1006000300000000' and table_name = 'o_c_perf_cellcircuit'
and start_time = to_date('2005-06-20 09:00:00','yyyy-mm-dd hh24:mi:ss')
and stop_time = to_date('2005-06-20 09:30:00','yyyy-mm-dd hh24:mi:ss');

create or replace outline ne_cell
for category c_unicom on
select ne_id from c_unicom.ne_cell;

create or replace outline a_y_plan_deliver
for category eoms on
SELECT y_plan_class_id, user_id, user_name, dept_no, dept_name,
read_date, advice,deliver_dept_no,deliver_dept_name,deliver_user_id,deliver_user_name,deliver_date
FROM eoms.a_y_plan_deliver
where y_plan_class_id in(:1);

或如果已知类别c_unicom,在该类别创建大纲,可以使用如下方法创建:
SQL> alter session set CREATE_STORED_OUTLINES=c_unicom;

SQL> select /*+ all_rows */ * from c_unicom.adp_data_num
where ne_id = '1006000300000000' and table_name = 'o_c_perf_cellcircuit'
and start_time = to_date('2005-06-20 09:00:00','yyyy-mm-dd hh24:mi:ss')
and stop_time = to_date('2005-06-20 09:30:00','yyyy-mm-dd hh24:mi:ss');

SQL> alter session set CREATE_STORED_OUTLINES=false;
 启活存储大纲:
SQL>alter session set USE_STORED_OUTLINES=c_unicom;

SQL> alter system set USE_STORED_OUTLINES=true;

1.3.1.2 使用stored outline
1) 执行一条SQL,Oracle首先把该SQL和会话或实例级大纲类别与share pool中缓存的语句做比较,如果找到,则就用该执行计划执行。如果找不到,则检查是否存在该语句的类别和大纲。若有大纲,则使用,若没有,则动态生成一个执行计划执行。
2) 如果该SQL语句的大纲在default中,即使没有激活,也是可以使用的。

1.3.1.3 管理stored outline
dba_outline_hints
dba_outlines


1)outln_pkg包
SQL>exec outln_pkg.drop_unused;--删除自创建以来未使用过的大纲
SQL> exec outln_pkg. drop_by_cat (‘c_unicom’);--删除该指定类别及其所有大纲
SQL> exec outln_pkg.update_by_cat(‘default’,’dss_queries’);--创建新类别,并把旧类别的所有大纲转移到新类别中

2)alter outline ..
- 重建大纲:alter outline adp_outline rebuild;
- 给大纲改名:alter outline adp_outline rename to adp_data_num_outline02;
- 修改大纲所属类别:alter outline adp_outline change category to test;
- 删除大纲:drop outline adp_outline;

1.3.1.4 私有stored outline
Private outline是当前保存的stored outline的副本,可以被编辑而不影响正在运行的系统,一个private outline只能被当前session看到,它的数据被保存在当前被解析的schema里。
当USE_PRIVATE_OUTLINES=TRUE时,一个已有outline的sql被提交时,optimizer会检查是否存在private outline,如果不存在,optimizer就不使用optimizer编译语句,而不会去检查公布的stored outline。

由于创建的大纲属于公有大纲,一旦修改,会影响所有使用的用户,如下创建该用户会话下的私有大纲,前提:
1)创建的用户必须拥有该查询所涉及的表上的select和create any outline权限。
2)在该用户下创建表来保存公有大纲的副本。可使用:dbms_outline_edit.create_edit_tables来创建。

创建
1)create private outline private_ol from public_ol;
2)更改私有大纲。然后使用create private outline private_ol from private private_ol;同步。
3)在会话中激活大纲:alter session set use_private_outline=true;
4)执行大纲的查询,然后使用explian或tkprof来查看其有效性。
5)贡献私有大纲为公有:create or replace public_ol from private private_ol;
6)停止使用私有大纲:alter session use_private_outline=false;

1.3.2 物化视图
(可在报表组应用)

物化视图是包括一个查询结果的数据库对像,它是远程数据的的本地副本,或者用来生成基于数据表求和的汇总表。物化视图存储基于远程表的数据,也可以称为快照。
物化视图可以查询表,视图和其它的物化视图。主要用在数据仓库和决策支持系统。
通常情况下,物化视图被称为主表(在复制期间)或明细表(在数据仓库中)。
对于复制,物化视图允许你在本地维护远程数据的副本,这些副本是只读的。如果你想修改本地副本,必须用高级复制的功能。当你想从一个表或视图中抽取数据时,你可以用从物化视图中抽取。
对于数据仓库,创建的物化视图通常情况下是聚合视图,单一表聚合视图和连接视图。

物化视图把他的物理结构存储在自己的段中,该段可以被索引和分区。
查询不必完全匹配用来创建物化视图的SQL语句,优化程序可以动态重写一个与原定义相近的查询,以便物化视图用来代替实际的表,这种查询重写自动发生,对用户是透明的。(9.0.1 A89852-02的29章详述了跟踪是否使用了物化视图的过程)

 使用物化视图前的几个配置步骤
1)确定那些语句要创建物化视图。(Oracle Summary Advisor工具,9.0.1 A90237-01 第16章)
2)决定是否要保持视图与基础表数据同步。
如果不同步,可选择如下三种刷新方式:
- COMPLETE:刷新启动时,先truncate物化视图,再从基础表重新插入填充数据。
- FAST:只刷新基础表上次刷新以来改变了的数据。使用视图的日志数据或ROWID完成。
- FORCE:默认的方式。先使用FAST,不行就使用COMPLETE方式。
3)设置init.ora的参数:
- JOB_QUEUE_PROCESSES,必须设置大于 1。
- QUERY_REWRITE_ENABLED,设置为TRUE时,允许动态重写查询。
- QUERY_REWRITE_INTEGRITY,确定访问物化视图时数据一致性要遵守的程度。
- OPTIMIZER_MODE,必须设置成CBO的某种方式。

使用一个物化视图,用户只需在基础表上拥有权限即可。

 创建物化视图
SQL>create materialized view emp_by_district
Tablespace mview_data
Build immediate
Refresh fast
Enable query rewrite
As
Select d.id,count(e.last_name) from distributor dist,district d,employee e
Where e.id = dist.manager_id
And d.id dist.district_id
Group by d.id;

Build immediate一共有三个选项:
1) Build immediate:建立物化视图,并使用当前命令执行的数据马上填充视图数据。
2) Build deferred:只建立物化视图,在第一次刷新之间不填充数据。
3) No prebuilt table,使用事先已存在的,已含有视图定义中有现有数据的表,而不是建立一个新结构来保存数据。

如果是refresh fast on commit或refresh complete on commit创建的,则在基础表提交的时候都会得到刷新。

 启用或禁用物化视图,需要有query rewrite或global query rewrite权限。

 刷新物化视图
- 自动刷新
1) 使用commit选项。
2) 使用dbms_mview安排自动刷新时间。
- 手工刷新
SQL>execute dbms_mview.refresh(‘EMP_BY_DISTRICT’); --刷新指定的物化视图
SQL>execute dbms_mview.refresh_defresh_dependent(‘EMPLOYEE’);――刷新利用了该表的所有物化视图
SQL>execute dbms_mview.refresh_all_mviews;――刷新该模式中,自上次刷新以来,未得到刷新的所有物化视图。

 禁用物化视图
 - 修改init.ora参数的query_rewrite_enabled参数设置成flase,重启实例。
 - 使用alter system set query_rewrite_enabled = flase;动态修改。
 - 使用alter session set query_rewrite_enabled = flash;修改会话内。
 - 使用 norewrite提示。

 删除物化视图
SQL>drop materialized view emp_by_district;

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)通过更新数据使数据在分区间移动不被允许,除非创建表的时候指定了enablerow 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’);

1.1.1.1.2 查询分区信息的视图
DBA_IND_PARTITIONS
DBA_IND_SUBPARTITIONS
DBA_LOB_PARTITIONS
DBA_LOB_SUBPARTITIONS
DBA_PART_COL_STATISTICS
DBA_PART_HISTOGRAMS
DBA_PART_INDEXES
DBA_PART_KEY_COLUMNS
DBA_PART_LOBS
DBA_PART_TABLES
DBA_SUBPART_COL_STATISTICS
DBA_SUBPART_HISTOGRAMS
DBA_SUBPART_KEY_COLUMNS
DBA_TAB_PARTITIONS
DBA_TAB_SUBPARTITIONS

1.1.1.1.3 增加分区
例:给范围分区增加分区
SQL>alter table C_PERF_CELLCIRCUIT
add partition part25 VALUES LESS THAN 25
tablespace D_PF_CELL_DBS25;

注意:可以不断的增加分区,但values less than () 的值不能比已经存在的分区的值小。
可以用maxvalue关键字指定列最大值。

1.1.1.1.4 truncate分区
例:
SQL>alter table C_PERF_CELLCIRCUIT
truncate partition part25;

将分区数据清空。不同于delete。

1.1.1.1.5 丢弃分区
例:
SQL>alter table C_PERF_CELLCIRCUIT
Drop partition part25;

将丢弃此分区的数据,不会影响其他分区。

1.1.1.1.6 交换分区
(可应用于大量数据插入中,先把数据临时插到一个临时表,再把该临时表与一个分区交换,需要考虑执行时间,未测试)
注意:
1)是将某一个分区于某一个表的数据交换。
2)临时表结构和分区表结构必须一样。
3)临时表的数据必须符合分区规则。
4)若分区里有局部分区索引,此时将不可用,必须重建。(除数据外,包括索引一起交换的除外---includeing indexes)
alter index p_nor_mcbtss2_idx rebuild partition p_nor_mcbtss2_part04 tablespace index_dbs;
例:
SQL>create table p_nor_mcbtss2_temp tablespace cqcookdb
as select * from p_nor_mcbtss2 where 1=2;
SQL> insert into p_nor_mcbtss2_temp values (……………………….);
SQL>commit;

SQL>alter table p_nor_mcbtss2 exchange partition
p_nor_mcbtss2_part04 with table p_nor_mcbtss2_temp;


1.1.1.1.7 移动分区
例:
SQL>alter table p_nor_mcbtss2 move partition p_nor_mcbtss2_part04 tablespace another_DBS;
注意:此时索引需要重建。

1.1.1.1.8 修改分区
例:
SQL>alter table p_nor_mcbtss2 modify partition p_nor_mcbtss2_part04 storage(pctincrease 20);
修改分区存储参数。

1.1.1.1.9 重命名分区
例:
SQL>alter table p_nor_mcbtss2 rename partition p_nor_mcbtss2_part04 to p_nor_mcbtss2_part05;


1.1.1.1.10 分割分区
例:
创建一个分区
SQL>alter table C_PERF_CELLCIRCUIT
add artition part25 VALUES LESS THAN 25
tablespace D_PF_CELL_DBS25;

分割原来的分区
SQL>alter table C_PERF_CELLCIRCUIT
split partition part26
at (25)
into (partition part25,
(partition part26);

前一个分区小于at 指定的值,后一个分区大于at 指定的值。
At指定的值不能等于本分区和上一个分区的上限值。
如果被分割的分区有数据,则local索引需要重建。

1.1.1.1.11 分区的逻辑备份与恢复
%exp username/passwd file=xxxx.dmp tables=( p_nor_mcbtss2: p_nor_mcbtss2_part04, p_nor_mcbtss2: p_nor_mcbtss2_part05)

%imp username/passwd file=xxxx.dmp tables=( p_nor_mcbtss2: p_nor_mcbtss2_part04, p_nor_mcbtss2: p_nor_mcbtss2_part05) ignore=y

1.3.5 cluster
Oracle 9i提供了两种:索引聚镞(index cluster)和散列聚镞(hash cluster)。
Cluster:是一个 由一个或多个 其数据 被一起存储在相同块中的 表 所组成的组。这样,通过一个表连接来利用这些表的查询就不必读两组数据块来得到它们的结果了。
可知,表是建在cluster上而非直接建在表空间上的。而cluster本身是表空间的一个段。
Cluster应用在非常具体的业务需求的地方。

 Index cluster
被index cluster的表,应具有如下特征:
1)总是被一起查询,极少被单独查询。
2)初始化数据后,cluster上极少发生或根本不发生DML操作。
3)每个父键都有约相同的子键。
SQL>create cluster teacher_student
(teacher_id number)
size 1000
storage (initial 500K next 500K pctincrease 0)
tablespace apps_clst;
SQL>create index teacher_student_idx
On cluster teacher_student
Tablespace apps_idx;
SQL>create table teacher
(teacher_id number,
last_name varchar2(20),
first_name varchar(20),
room_number number)
cluster teacher_student
( teacher_id);
SQL>create table student
(student_id number,
last_name varchar2(20),
first_name varchar2(20),
teacher_id number)
cluster teacher_student
(teacher_id);

 Hash cluster
被hash cluster的表,应具有如下特征:
1)初始化数据后,cluster上极少发生或根本不发生DML操作。
2)在被索引列中,有一个均匀值的分布。
3)在被索引列中有可预知数量的值。
4)where子句中,利用了被索引列的相等匹配。

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/24032200/viewspace-673992/,如需转载,请注明出处,否则将追究法律责任。

转载于:http://blog.itpub.net/24032200/viewspace-673992/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值