大多数Oracle DBA 连续的、每天的职责是使 Oracle 数据库获得可能的最好性能。对于“性能”可能有许多定义,但是我们把性能定义为目标和在怀疑有问题的数据库中执行一个典型操作需要的可以测量的时间。是的,这是一个太简单的定义,它忽视了其他的测量尺度,如资源使用。但是让我们正视它:我们期望数据库尽可能地快,因此为了这个目的这是一个合理的定义。
整本书都是以Oracle 性能为主题写的(参见附录“DBA 使用的资源”以查看我们认为你应该注意的内容,注1),所以我们不能在一章中就阐述完复杂的Oracle 性能优化,我们希望提供一种直截了当的性能优化方法并提供能应用到各个不同安装上的实际指南。
从物理和逻辑的实现、处理的事务类型及这些事务的性能需求方面来看,每个Oracle 安装都是不同的,认识到这点很重要。结果是虽然一些厂商(包括 Oracle) 尝试提供,但仍没有一种自动的优化方法,而且也没有单一的一套规则可以提供一种使数据库性能最优的方法。然而,我们可以提供一种方法,在适当应用并结合DBA 知识和经验的情况下,该方法将使任何给定的数据库有好的性能。
获得最大的性能
使你的Oracle数据库获得最大的性能并不是一下子就可以做到的,这通常是大量辛苦的工作、思考和计划的结果。然而,从付出努力所得到的回报来看,是非常值得的,你的数据库在最高效地运行,你的用户高兴,你也很满意。
我们使性能最大化的方法是按自然层次分类的。需要从3 个不同方面,并按照顺序来阐述。这3 个方面是:
-
● 操作系统配置
-
● Oracle 资源配置
-
● 对象创建和SQL 语句执行
这些方面不是互不相关的,实际上,对某方面的重要改变可能需要考虑其他方面。它们是顺序依赖的,也就是说,直到你已正确配置和调整了操作系统,你才能使Oracle 达到很好的性能。同样,查询的快速执行取决于是否合理地配置了Oracle 环境。
每个Oracle数据库的情况都是不同的,因此我们不能精确地告诉你该如何完成你的配置和优化目标,甚至你的目标是什么。我们要做的是为你提供一个我们已经成功的方法。
调整和配置数据库对象
要获得最大的数据库性能,数据库对象的合理大小和配置是非常重要的。对象的合理大小是一个不断进行的工作,随着不断创建对象和修改对象,也需要不断地检查对象特性并在需要时将其改变。以下与调整大小相关的问题的数值与性能成反比:
表空间碎片(tablespace fragmentation) 表空间碎片使许多无法使用的小延伸区分散在表空间中。当创建对象时,如果延伸区的INITIAL 或NEXT 的值设置不合理就会产生碎片。
行链(row chaining) 这个问题将导致单行的数据驻留在多个Oracle块中,典型情况发生在PCTFREE 设置不足且表不断进行更新时。
多个延伸区(multiple extent) 多个延伸区,可能导致一个特定对象的数据分散在一个或几个数据文件之中,这是由在创建对象时指定了不合适的INITIAL或NEXT延伸区大小而引起的。这个问题可能会在MAXEXTENTS 参数被允许为默认值时变得很严重,因为尝试分派一个超过那个数目的延伸区将导致失败。
日志等待当写日志缓冲区记录到一个日志文件或当日志文件切换时,日志等待将引起一个进程等待,这时日志等待能大大增加处理时间。这通常由日志文件数目太少和日志文件太小等原因引起。
扩展一个回滚段失败这样的失败(能引起一个事务回滚)是由于没有分配充足的回滚段数目,或者是由于分配的回滚段不够大。
下列各节讲述了可以避免这些性能问题的一些指南和建议。
表
表是 Oracle 数据库中数据存储的基本单位,因此表的配置和由此产生的性能将对数据库总体性能产生很大的影响。下面是表配置的一些指导方针:
-
● 试着估计一个表将多大,并且分配一个足够大的初始延伸区来存放整个表。然而,如果你正在使用并行查询,则应跨越不同的数据文件来分配总的空间,使分配的延伸区数目和表的并行度相等
-
● 考虑使用多个表空间,每个表空间对应于不同大小或类型的表。例如,你可能有3 个表空间:LARGE_DATA、MEDIUM_DATA 和SMALL_DATA,每个会用来存储大小不同的表。如果你使用多个表空间,要确保把每个表分配到恰当的表空间中
-
● 确保分配一个DEFAULT TABLESPACE 给每个用户。如果没有分配,Oracle 将使用SYSTEM 表空间作为默认值
-
● 如果可能,保证INITIAL和NEXT 延伸区大小总是相同大小的单元的整数倍,例如,是 512K 的整数倍。这样,延伸区将是统一的大小,而且会比较容易分配额外的延伸区,而不引起表空间碎片。如果可能,在一个表空间中可以使用大小相同的延伸区
-
● 设定PCTINCREASE参数为 0,为了防止延伸区分配失控和保持统一的延伸区大小。
-
● 设定MAXEXTENTS 参数为UNLIMITED。这将防止延伸区用完,因为多个延伸区对它们产生很小的性能影响(虽然广泛分布的延伸区对性能有负面影响)。这样做可以防止错误,但是不要把它作为INITIAL 大小的替代
-
● 如果表没有更新,则设定PCTFREE 为0。如果表有更新,则估计行的列的增长程度,并分配一个PCTFREE 来防止块链接,而在块中没有过多的未使用空间
-
● 如果有很多事务同时访问表,将INITRANS 设定为一个大于1(默认的)的数
-
● 将 MAXTRANS 设定为在预期表上同时访问的最大数目。一个较小值将会导致一个或多个事务等待前一个事务完成
索引
正确使用索引可以使性能大大提高,这是任何Oracle 单一特性所不能做到的。虽然许多性能提高获益于优化 SQL 语句(见第八章“查询优化”),但我们也提供一些配置指南:
-
● 为索引创建一个单独的表空间,并且保证这个索引表空间的数据文件与包含索引表的表空间的数据文件不在同一个磁盘上
-
● 试着去估计索引的大小而且分配一个足够的INITIAL延伸区来存储整个索引,除非你正在使用并行查询,否则在这种情况下,你应该在与索引的并行度相同的数据文件之间分配总的空间
-
● 如果可能,保证INITIAL和NEXT 延伸区大小总是相同大小的单元的整数倍,例如,是 512K 的整数倍。这样,延伸区将会是统一的大小,而且会比较容易分配额外的延伸区而不引起表空间碎片
-
● 设定 PCTINCREASE 参数为0 以防止延伸区分配失控并保持统一的延伸区大小
-
● 设定 MAXEXTENTS 参数为UNLIMITED。这将防止延伸区用完,而多个延伸区可能产生的性能影响很小(虽然广泛分布的延伸区对性能有负面影响)。这样做可以防止错误,但是不要把它作为INITIAL 大小的替代
回滚段
Oracle 用回滚段来维护数据的一致性,允许事务的取消或回滚。回滚段使用很多的输入/ 输出,下面是配置回滚段的一些指导方针:
-
● 为回滚段创建一个单独的表空间,如果可能,把这个表空间的数据文件放在一个与其他数据文件不同的磁盘上
-
● 永远不要在SYSTEM 表空间中创建回滚段(除了在数据库创建期间需要的临时回滚段以外,见第二章“安装”)
-
● 确保为回滚表空间分配了足够大的空间,以允许回滚段为了适应大的更新事务来按照需要增长空间。记住批事务容易产生很大的回滚段
-
● 总是保持回滚段的INITIAL 和NEXT 延伸区使用相同的数值(在CREATE TABLESPACE 语句中的DEFAULT STORAGE 子句中定义)。为回滚段分配大小相等的块可以防止空间碎片
-
● 记得每个回滚段必须至少有两个延伸区,因此段的初始大小实际上是INITIAL + NEXT 的总和
-
● 定义一个OPTIMAL值,以便使为了延伸适应一个大事务而增长的回滚段可以回缩到一个合理的大小。然而,不要让这个值太小,否则会浪费时间来为回滚段分配额外的延伸区
排序区
Oracle 使用INIT.ORA 参数SORT_AREA_SIZE 来为数据排序分配内存。当一个排序不能够在内存中完成时,Oracle 使用数据库中的临时段,但这非常慢。应当小心平衡SORT_AREA_SIZE,因为大的排序区可以通过减少输入/ 输出来显著增加性能,但是这将用光内存并引起分页。
注意: 记住这个参数应用到每个用户进程。每个执行排序的用户进程都将分配 SORT_AREA_ SIZE 内存。因此,如果 SORT_AREA_SIZE 被设定为/MB,而有100 个用户进程正在执行排序,那么将分配总数为100MB 的内存。
临时表空间
如果没有为执行排序的用户进程分配足够的内存,那么Oracle 将通过为用户在TEMPORARY TABLESPACE参数指定表空间中创建临时段来在磁盘上执行排序。除此之外,临时段用来执行复杂查询,如连接、UNION、MINUS 和索引创建。临时区的指南如下:
-
● 为临时段创建一个单独的表空间(通常叫做 TEMP),如果可能,把这个表空间对应的数据文件放在一个单独的磁盘上
-
● 在CREATE TABLESPACE命令的DEFAULT STORAGE子句中指定INITIAL 和NEXT 参数。把两者的值设为相等,以消除空间碎片,在 TEMP 表空间中极易产生碎片,因为在那里不断地创建并删除对象
-
● 要确保为每个用户指定一个TEMPORARY TABLESPACE。如果没有指定,Oracle 将把SYSTEM 作为默认的表空间,而这样对性能有负面的影响
重做日志
重做日志,也称联机重做日志文件,对 Oracle 的失效恢复能力至关重要。重做日
志的适当配置不但对数据库的总体性能很关键,而且对恢复数据库的能力也很重要(见第四章“防止数据丢失”)。相关指南如下:
-
● 使用Oracle 内嵌的镜像特性,把重做日志文件的多组放在不同的磁盘上
-
● 分配足够的重做日志文件以便Oracle 无须为了重复使用一个文件而等待它。Oracle 至少要求有两个重做日志文件,但是4 个或更多个是必要的
-
● 分配的重做日志文件要足够大以防止太多的日志文件切换,但又要适当的小以保证当前联机日志文件失效时很好地恢复。如果文件较小,可能恢复已经归档的所有事务,而大的日志文件使数据库有可能丢失更多的事务
-
● 设置
INIT.ORA参数 LOG_CHECKPOINT_INTERVAL值大于重做日志文件的大小,这样将避免检查点(checkpoint)进程,直到日志文件满为止(引起一个检查点进程)。这个参数以数据库块来表达
警告: 记住一个日志切换将导致从SGA 将脏缓冲区(例如有更新)写入到磁盘。
● 如果你正在运行Oracle7,考虑设定INIT.ORA 参数CHECKPOINT_PROCESS 为TRUE。这么做将创建一个执行检查点进程的单独进程,而并非由LGWR(日志写入进程)处理。见第十章“Oracle 实例”,可以了解更多信息
归档日志目的地
在配置方面一个经常需要注意的问题是要保证归档日志目的地有足够的空间。如果数据库正在归档日志模式中运行,那么当一个联机重做日志文件填满时,Oracle 的ARCH进程将复制这个文件的内容到INIT.ORA参数ARCHIVE_LOG_DEST指定的目录。如果目的地太小,ARCH 就不能复制日志文件,而一旦所有的联机日志文件满,整个数据库就会停止,直到这个问题解决。有经验的DBA 已经意识到这种情况,这种情况大多数在半夜发生,就像REM 休眠一样。
优化 Oracle
或许DBA 的工作没有哪一方面能像优化这样消耗时间。成功的Oracle 优化既要求知识又要求经验,挑战和挫败也同时存在。整卷都在写Oracle优化(参见附录“DBA 使用的资源”),但我们不能在一节中包括优化的所有方面。相反,正如我们前面提到的,我们将列出可以应用到各种情况的优化方法的大纲。
结构化优化方案
Oracle 数据库的成功优化需要仔细的、有规则的方案。像整体系统配置一样,优化一定要包括下列各项:
-
● 硬件和操作系统性能● Oracle 实例性能
● 单独的事务(SQL)性能
这些方面应该按顺序进行,因为没有硬件和操作系统的良好优化,Oracle 的性能优化是不可能的。没有数据库的有效运行,一个单独的SQL语句不可能很好地被优化。优化这些方面中的任何一方面时,都包括3 个步骤:
- 1. 测量目前的性能。
- 2. 做适当的变化。
- 3. 评估结果。
警告:对Oracle实例的一些改变可能引起对操作系统环境的改变。比如,分配附加的数据库缓冲区可能导致操作系统开始分页,而这可能要求额外的操作系统优化来消除。
优化进程几乎总是反复的。也就是说,在完成3 个步骤之后,DBA 必须回到第一步骤并且重复这个过程。这将一直持续到不会再有性能改善为止。
Oracle 实例优化
Oracle 实例层的大多数性能的提高将通过两个方面达到: 内存使用和磁盘输入/ 输出。
内存使用
基于内存的操作比磁盘操作快得多(有时成千上万倍),这一点是不值得惊讶的。结果将导致用内存访问数据来代替磁盘输入/ 输出,以使性能得到巨大的提高。相关的3 个主要方法描述如下:
分配额外的DB_BLOCK_BUFFERS 这或许是改善总体性能的单一的最有效的方法,特别是在查询上。更多的数据库缓冲区允许更多的数据块数据保持在内存中,因此可以按内存速度访问包含在这些块中的数据,而不需要磁盘输入/ 输出。缓冲区是由INIT.ORA 参数
DB_BLOCK_BUFFERS 来分配的,它的数值是要分配的数据块缓冲(block buffer)数目。因此,如果数据库块大小是8192,每个DB_BLOCK_BUFFER 将是8192 字节。注意改变DB_BLOCK_BUFFERS 值后直到下次数据库重启才生效。
注意: 注意不要分配太多的DB_BLOCK_BUFFERS以导致操作系统开始分页,分页将消除你获得的性能,而且将对整体性能产生负面影响。
分配额外的共享池共享池大小由INIT.ORA的参数SHARED_POOL_SIZE 控制,它指定了以字节为单位的共享池大小。共享池的主要内容是字典缓存区(dictionary cache)和共享SQL 区(shared SQL area)。由于字典缓存区的各部分组件由Oracle 自动分配,所以共享池的任何增加都会使字典缓存区和共享SQL 区增加。
共享SQL 区包含最近执行的SQL 语句的拷贝,连同相关信息,如它们的执行计划。共享池越大,特定SQL 语句被解析并且驻留在共享SQL 区就越有可能,因此节省了需要再次处理这个语句的时间。在相同的SQL语句被多次执行且对速度有要求的事务处理系统中,这是个特别重要的值。
分配更多的日志缓冲区空间日志缓冲区是用来存储将要写到联机重做日志文件上的数据的。日志缓冲区的大小由INIT.ORA 参数LOG_BUFFER 控制,其数值以字节表示。为日志缓冲区分配更多的内存,将减少磁盘输入/ 输出,尤其是在事务特别长或数量很多时。
磁盘输入/ 输出
磁盘访问是任何计算机系统上的最慢的操作。作为一个数据库系统,Oracle 的存储和访问数据非常依赖磁盘访问。考虑一个典型的更新一个表的一行的SQL 语句,将发生下列各项操作:
- 1. 读数据字典获得关于表和正在被操作的行的信息。
- 2. 读适当的索引来定位要更新的行。
- 3. 读包含行的数据块。
- 4. 写回滚信息到一个回滚段。
- 5. 写更新信息到联机日志文件。
- 6. 重写数据块。
- 7. 重写索引块。
虽然一些操作可以通过有效使用内存消除,正如我们前面提到的,但所有这些操作都潜在地要求磁盘输入/ 输出。通过尽可能使磁盘输入/ 输出有效,可增强总性能。使磁盘输入/ 输出最大值的基本指南如下:
-
● 只要可能,分离输入/输出操作到单独的磁盘上。这样,在执行另外一个时,不需要等待一个磁盘操作完成。例如,如果回滚段和日志文件在相同的磁盘上,需要写回滚记录,然后磁盘磁头需要移动到日志文件记录要写的那部分磁盘。这是非常耗时的
-
● 把高输入/ 输出的磁盘放在不同的控制器上。现代的控制器可以处理有限数目的并发操作,但是尽可能使用更多的控制器将消除任何控制器等候并加速性能
-
● 把最忙的文件和表空间(例如,日志文件、回滚段、一些索引)放在最快的可用磁盘上
关于RAID 的注释
磁盘技术的最新发展使 RAID(廉价磁盘冗余阵列)成为许多系统上很常用的一个选项。通常,当使用术语 RAID 时,硬件管理员会立刻想到RAID 5(或 RAID-5), 它允许多个磁盘结合成一个大的设备。通过分配一个磁盘设备来存储冗余数据,一个 RAID-5 磁盘阵列可以承受阵列中的任何单一磁盘失效,并且经常是热交换的,也就是当一个磁盘失效时,其他的磁盘继续工作的同时更换这块磁盘,而不必关闭系统。
事实上RAID-5 是非常强大且廉价的。当配置Oracle 数据库时,在大多数情况下要避免使用这种技术。这可能听起来很刺耳,但是事实上虽然RAID-5 成本较低,而且提供了很好的数据保护级别,但是它的磁盘输入/输出花费很高。尤其是在RAID5 阵列上的写操作要比在单一磁盘上的写操作慢得多。RAID-5 阵列的一个好的替代品是RAID1,就是大家都知道的磁盘镜像。虽然比RAID-5(一半磁盘用来存储冗余数据)更贵,但是RAID-1提供了完全的数据保护,而在输入/ 输出效率上没用降低。
警告: RAID-1 要求有足够的硬件资源。尤其是由于每次写操作实际都要对磁盘进行两个写操作,所以控制器上的负荷是非RAID 的两倍。
现在性能最好的RAID 是RAID-0+1,有时叫做 RAID-10。RAID 的这个级别在多个驱动器上结合了带有数据条带(RAID-0)的镜像磁盘(同RAID-1),这可以消除等待磁盘头定位的延迟。而这在其他的RAID 控制器中都没有,RAID-0+1 是值得考虑的。
操作系统条带化
许多操作系统提供了在多个磁盘设备中磁盘扇区的自动条带化。条带化允许磁盘输入/ 输出连续,而没有头定位的延迟。虽然这个技术提供了比在一个单一磁盘上更好的性能,但也有一些缺点: 结合多个磁盘为一个单一的条带单元意味着DBA不能够控制单个文件在单独磁盘设备的位置。如果你的系统上只有少数的大磁盘,你应该考虑操作系统条带化,但是多磁盘设备或多 RAID-0+1 阵列通常会从Oracle 产生更好的性能。
Oracle 条带化
作为DBA,通过小心地把数据文件分配到单个磁盘设备或 RAID-0+1阵列,你可以达到与操作系统条带化相似的结果。例如,建立跨越4 个磁盘的Oracle 条带化需做下列各项工作:
-
● 创建一个有4 个数据文件的表空间,每个位于一个不同的磁盘设备上
-
● 在表空间中创建对象,指定MINEXTENTS 4。Oracle 将把4 个延伸区分配到4个数据文件上,这样就实现了条带化。这个行动不是自动的,还需使用ALTER TABLE ... ALOCATE EXTENT 命令
Oracle 条带化技术非常强大,尤其和并行查询结合的时候,将通过多CPU 处理查询过程。
SQL 优化
假如主机服务器和操作系统正在你的站点顺利运行,而且你配置并优化了Oracle, 使其在最好状态运行,但是你的重要应用程序仍然运行很差。不幸的是这种情况经常发生。解决方法是通过检查和优化正在被执行的SQL 语句来优化应用程序。
SQL 优化这个题目值得写一本书。实际上,在市场上有很不错的书阐述得比这里更为详细。我们建议你检查附录中列出的DBA资源。在这小节中,我们将为你提供优化SQL 语句的一些概要建议和指南。
查询处理
第八章“查询最优化”描述了Oracle 如何为一个特定的SQL 语句创建一个计划。Oracle 现在用两个方法中的一个来决定该如何执行一个SQL 语句:
基于规则的方法应用一个标准的、固定的(但是经常有效的)规则集到语句中。
基于费用的方法
考虑由一个SQL语句(连同可得的索引一起)引用的对象的可用统计信息,并
基于这些统计建立一个计划。
优化一个SQL语句的关键是理解Oracle查询优化器如何工作和知道怎样改变Oracle 的行为,以便它能更有效地处理语句。
当然,在优化一个SQL 语句之前,必须知道它在做什么和如何做。今天市场上的许多工具将有助于完成这个工作,而且最有用的工具之一是SQL*Plus中的EXPLAIN PLAN 命令。通过创建一个计划表(通常为PLAN_TABLE)并且检查EXPLAIN PLAN 语句的结果,你会容易地看到Oracle 如何执行一个特定的语句。例如,SQL 语句:
SELECT ename,loc,sal,hiredate
FROM scott.emp, scott.dept
WHERE emp.deptno=dept.deptno;
可用下面的命令解释:
EXPLAIN PLAN SET STATEMENT_ID='DEMO' FOR
SELECT ename,loc,sal,hiredate
FROM scott.emp, scott.dept
WHERE emp.deptno=dept.deptno;
存储在PLAN_TABLE 中的结果可以通过下面的简单查询看到:
SELECT LPAD(' ',2*level) || operation || '' || options || ' '||
object_name EXPLAIN_PLAN
FROM plan_table
CONNECT BY PRIOR id = parent_id
START WITH id=1
看起来像这样:
EXPLAIN_PLAN
NESTED LOOPS
TABLE ACCESSFULL DEPT
TABLE ACCESSFULL EMP
这个计划表明将使用全表扫描来对DEPT 和EMP 表访问。这对像EMP 和DEPT 一样的小表很好,事实上,我们想要它们全表扫描,因为表将缓存到内存中,并且不需要磁盘输入/ 输出(至少在第一次运行之后)。然而,如果表很大,这个查询将进行很长时间,所以我们想改变查询执行的方式。
有3 个基本方法可以改变Oracle 查询优化器的行为:
-
● 在执行查询时提供一个或多个索引来用
-
● 重写SQL 来使用一个更为有效的方法
-
● 以提示(hint)的形式提供查询优化器指导
如果我们试第一选项而且在EMP(deptno)上增加一个索引,计划将改变为:
EXPLAIN_PLAN
NESTED LOOPS
TABLE ACCESSFULL DEPT
TABLE ACCESSBY ROWID EMP
INDEXRANGE SCAN EMPDEPT_IX
现在你能看见Oracle 使用索引通过ROWID 来从EMP 取回行,ROWID 是从新创建的索引中获得的,而不再需要全表扫描。通常使用SQL 会有不止一种实现一个特定功能的方法,在确定使用正确的SQL 语句之前尝试几种不同的方法(有适当的基准)是一种很好的实践方式。第八章“查询最优化”提供了关于SQL 优化的更详细信息。
其他有用的优化特性
Oracle 通过增加提高性能的新特性来不断改良数据库产品。检查即使只有很小更新的Oracle 版本注释是很重要的,因为这其中可能就包含了新的性能特性。你可能觉得有用的一些特性和工具列表如下:
分区表(partitioned table)
从Oracle8 开始分区表就允许在多个子表上创建表,每个子表包含了表数据的一个特定子集。例如,一个表可以按年分区,所有1998 年的数据在一个分区中,所有1999 年的数据在另一个分区中等等。分区对大的表特别有用,因为对包含在一个可识别的子集中的数据进行查询可以在对应的分区中操作,而不用访问其他的分区。例如,更新 1999 年的记录只要求Oracle 在1999 年的分区上执行输入/ 输出操作。可在CREATE TABLE 语句中指定分区。为了使用这个特性,你必须:
-
● 标识将要定义分区的数据字段(例如sales_year)
-
● 在CREATE TABLE ... PARTITION BY RANGE 子句中指定值的范围
-
● 为表的每个分区指定一个另外的表空间(为了得到最好的性能,把表的每个分区放置在不同的磁盘上)。注意单独的表空间不是必需的,但是这种做法可以允许表的一个分区脱机,而维持访问表的剩余部分分区表通常应该伴随着相应的分区索引,如下:
-
● 使用CREATE INDEX 命令的LOCAL 关键字来告诉Oracle 为索引表的每个分区创建一个单独的索引
-
● 使用CREATE INDEX 命令的GLOBAL 关键字,以便告诉Oracle 使用不会对应到索引表分区的值来创建一个单一索引。全局(GLOBAL)索引也可以分区
惟一索引表(index-only table)
在某些情况下,正常时存储在一个表中的所有数据可以存放在一个索引中,这样表就没必要了。从Oracle8 开始,一个惟一索引表就使数据按照主键列排序。对这种类型的对象有一些限制:
-
● 由于数据没有存储在一个表中,所以没有 ROWID 可用
-
● 必须为表定义一个主键
-
● 不能创建其他的索引,只有主键可以被创建为索引
惟一索引表通过使用CREATE TABLE命令的ORGANIZATION INDEX子句创建。
位图索引(bitmap index)
当被索引的数据有低基数(cardinality)时(也就是说索引列有相对较少的确定值时),创建位图索引可以大大改善性能。位图索引的一个好的例子就是性别(GENDER),它只有两个值“M”或“F”。对于销售总额(SALES_AMOUNT),将
不适合建立位图索引,因为它对于每行都可能有一个不同的值。
创建一个位图索引类似于创建一个标准的索引,你可以在CREATE INDEX 语句中包括关键字BITMAP。例如,在EMPLOYEE_MASTER 表的GENDER 列创建一个位图索引,指定下列语句:
CREATE BITMAP INDEX empmast_ix ON employee_master(gender);
临时表空间
Oracle7 引进了临时表空间的概念,这专门为Oracle 的排序段使用。通过消除连续不断地分配和释放排序空间的空间管理操作,当排序很大以致内存不能容纳时,所有使用排序的操作将得到性能的提高。这在运行OPS 的时候尤为重要。
注意: 一个临时表空间只能用于排序段,不要在临时表空间中创建永久对象。
要创建一个临时表空间,需要在CREATE TABLESPACE 语句中使用关键字TEMPORARY。例如,下面语句将创建一个叫做TEMP 的临时表空间:
CREATE TABLESPACE TEMP
DATAFILE '/disk99/oracle/oradata/TEST/temp01.dbf' SIZE 50M
DEFAULT STORAGE(INITIAL 64K NEXT 64K MAXEXTENTS UNLIMITED)
TEMPORARY;
一个已存在的非临时表空间可以转变为临时表空间,如果它不包含永久对象,可使用下面SQL 语句进行转换:
ALTER TABLESPACE tablespace TEMPORARY;
不能恢复的操作
由Oracle 7.2 开始,在创建表或索引时就可能不写重做日志记录。这个选项提供了较好的性能,因为需要的输入/ 输出少了很多。要利用这个特性在对象创建语句中指定UNRECOVERABLE(Oracle7语法)或 NOLOGGING(Oracle8 语法)。例如,你想使用数据库链接从另外一个数据库移动数据可使用下面这个语句:
INSERT INTO newtable
SELECT * from oldtable@oldlink;
这个方法当然会奏效,但是将为每次插入创建重做日志记录,这将浪费资源。可以用下面语句完成相同的任务:
CREATE TABLE newtable AS
SELECT * from oldtable@oldlink
NOLOGGING;
当重建索引的时候,NOLOGGING 选项将特别有用。NOLOGGING 关键字可以大大减少索引创建的时间。SQL 语句与下面语句相似:
CREATE INDEX indexname ON table(column)
NOLOGGING;
注意,如果在执行一个不能恢复的语句之后,在某点发生了系统失效,你将不能使用回滚机制来恢复这个事务,你必须意识到一个系统失效已经发生并且要重新运行语句。