下载
第8章 数据库调整
调整是每一个数据库应用中必不可少的一部分。如前面几章所述,大多数性能问题并不
是一种孤立的现象,而可能是系统设计上存在问题。调整的重点应当放在识别并解决这些潜
在的缺陷上。
调整是四个处理步骤中的最后一步,规划 (见第3、4章)、实现(见5章)和监控(见第6章)都
应当在调整之前完成。若只是为了调整而调整,就会无法进行整个活动循环,并很有可能无
法解决造成性能问题的那些潜在隐患。
大多数可进行调整的数据库对象,均在本书其他部分进行了讨论。例如第 7章已详细讨论
了回滚段;本章只讨论那些与调整活动有关的对象,而规划和监控活动则在其他章节论述。
本章将讨论以下几方面的调整活动:
• 应用程序设计。
• SQL。
• 内存使用。
• 数据存储。
• 数据处理。
• 物理存储。
• 逻辑存储。
• 网络流量。
8.1 调整应用程序设计
为什么要用整整一节来讲述数据库管理人员对应用程序设计的调整呢?并且还要将它放
在第一节?作为一个数据库管理人员,应当知道没有什么能比应用程序设计对系统的性能影
响更大。在第5章中已经讲到,应让数据库管理人员参与应用程序开发。在设计一个应用程序
时,可以采取若干步骤,以便正确而有效地运用下面几节所讲到的技巧。
8.1.1 高效的表设计
“没有任何应用程序会以第三范式 (Third Normal Form)运行。”
G e o rge Koch
—
O r a c l e 8完全参考手册
无论数据库设计得多么好,但糟糕的表设计会导致糟糕的性能。不仅这样,过分呆板地
遵守相关的表设计,也会使性能得不到充分发挥。这是因为完全的相关型表设计 (即符合第三
范式)虽然逻辑上可行,但实际使用时却行不通。
这种设计的问题是,虽然那些表设计能够准确反映应用程序数据与其他数据的相关方式,
却不能反映用户访问这些数据所采用的访问路径。一旦评估了用户的访问要求,则会发现整
个相关型表设计对许多大型查询将会无效。一般来说,主要问题将出现在返回大量列的查询
上。这些列通常分散在几个表中,在查询过程中会迫使这些表连结在一起。如果这些表中有
第8章 数据库调整 195
下载
一个大型表,整个查询的性能就会受到损失。
在为应用程序设计表时,开发人员必须考虑非正规化的数据
—
例如,从一些大型静态
表中生成一些小型的汇总表。这些数据是否能根据命令从大型静态表中动态生成?答案是肯
定的。但是如果用户频繁请求而数据不发生较大变动,那么按用户要求的格式定期存储这些
数据就有意义。
以用户为中心的表设计不同于以理论为中心的表设计,它将产生一个能较好满足用户需
求的系统。设计选项包括将一个表分成几个表,也同样包括将几个表合并成一个表。重点应
放在向用户提供一个能按他们要求的格式访问数据的最直接路径。
8 .1.2 分配C P U 请求
在完成有效设计并充分配置好硬件后,O r a c l e数据库的应用程序的性能表现将取决于 C P U 。
也就是说,制约应用程序性能的因素将是 C P U 资源的有效性。如果没有为服务器另外配置足
够的C P U,就要采用下面这些管理C P U 资源的选项。
首先,必须安排好C P U 的负载。这个问题在第 7章中已经提到。通常,冗长的批查询或更
新程序都是安排在非峰值期间运行。联机用户在执行事务时,不是以较低的操作系统优先级
运行它们,而是在一个合适时间以正常的操作系统优先级运行它们。这将把潜在的锁定、回
滚段及C P U冲突降至最低限度。
第二,由于分布式计算已经相当广泛,因此可以将 C P U 请求从一个服务器移到另一个服
务器。只要可能,就应将数据库服务器与应用程序的 C P U 请求分开。本书第三部分提到的数
据分布技巧将会使数据存储在合适的地方,并且可以将应用程序对 C P U 的请求与对数据库的
I / O请求分开进行。
第三,可以用 O r a c l e 8 i 中引入的数据库资源管理功能。可以使用 Database Resource
M a n a g e r (数据库资源管理器 )建立资源分配计划和资源用户组。可以利用 O r a c l e 的性能来变更
对用户组的有效资源分配。有关通过 Database Resource Manager创建并实现资源用户组的细
节,请参见第5章。
第四,可以用Parallel Query Option(PQO,并行查询选项),在多个C P U 间分配S Q L语句的
处理请求。几乎任何 S Q L 命令都可以使用并行性,其中包括 s e l e c t ( 选择 )、create table as
s e l e c t (创建选择表)、create index(创建索引)、r e c o v e r (恢复)和SQL *Loader Direct Path装载选项。
事务并行处理的并行程度取决于对事务并行度的定义。每一个表都有一个定义的并行度
(见附录A中的create table及alter table命令),一个查询通过使用 PA R A L L E L提示,就可以重设
缺省的并行度。在 O r a c l e 7 . 3中,数据库对服务器上可用的 C P U 数量和存储表数据的磁盘数量
进行判定,以确定并行度的缺省值。
最大的可用并行值设置在实例级。 i n i t . o r a参数PA R A L L E L _ M A X _ S E RVERS 设置任意时
刻数据库中所有进程可以使用的并行查询服务器进程的最大值。例如,如果为你的实例将
PA R A L L E L _ M A X _ S E RV E R S设置为3 2,并运行一个查询,这个查询为其查询及排序操作使用
3 0个并行查询服务器进程,这样,将只有 2个并行服务器进程对数据库的其他所有用户可用。
因此,需要仔细管理查询和批处理操作所需要的并行值。在 O r a c l e 7 . 3中,可以使用 i n i t . o r a参
数PA R A L L E L _ A D A P T I V E _ M U LT I _ U S E R 来限制多用户环境中操作的并行性。如果将
PA R A L L E L _ A U TO M AT I C _ T U N I N G 设置为T R U E ,就自动打开 PA R A L L E L _ A D A P T I V E _
M U LT I _ U S E R特性。在O r a c l e 8 i 中,可以限制对数据库中定义的资源用户组有效的并行性。有
关实施Database Resource Manager和资源规划的细节,请参见第 5章。
可以借助于create table及alter table命令中的p a r a l l e l 选项,为每一个表设置一个缺省的并
行度。该并行度告诉 O r a c l e,将会有多少个并行查询服务器进程用于这个操作中的每一部分。
例如,如果一个执行表扫描和数据排序操作的查询并行值为 5,就会有1 0 个并行查询服务器进
程被使用
—
5个用于扫描,另 5个用于排序。也可以在创建索引时通过 create index命令中
P a r a l l e l子句来设置它的并行度。
最小数量的并行查询服务器进程通过 i n i t . o r a 参数PA R A L L E L _ M I N _ S E RV E R S来设置。通
常,应将这个参数设置成一个非常小的数值 (小于5 ) 。这样将迫使 O r a c l e 反复启动新的查询服
务器进程,但它会减少空闲的并行查询服务器进程占据的内存。倘若为 PA R A L L E L _ M I N _
S E RV E R S 设置一个高值,就会在服务器中频繁出现空闲的查询服务器进程;这些进程会占据
已获得的内存,而不执行任何功能。可以设置一个空闲时间参数来通知 O r a c l e,一个并行查询
服务器进程在被数据库终止之前,可以空闲多长时间。
并行操作在多个 C P U间分配它们的处理请求;然而必须小心使用这些功能。如果为一个
大型查询而将并行值设置为 5,那么将有5个不同的进程来访问这一数据。若有许多进程访问
该数据,存储该数据的磁盘就可能发生冲突,这对性能会大有影响。使用 P Q O 时,对已经向
许多物理设备较好分配了数据的表,应当有选择地应用 P Q O。还应当避免对所有的表都使用
P Q O 。如前面所述,一个查询有可能消耗掉所有可用的并行查询服务器进程,并干扰数据库
中其他全部事务的并行处理。
8.1.3 高效地进行应用设计
除本章后面将要描述的应用程序设计之外,还有一些通用的 O r a c l e应用程序设计准则。
首先,应当使应用程序向数据库请求数据的次数最小化。有关这方面的选项包含队列及
P L / S Q L 块的使用。本章前面已经讨论过的表的非标准化事项,在这里依然可以使用。可以使
用快照和显形图(在O r a c l e 8 i中)等分布式数据库对象,来帮助减少查询数据库的次数。
第二,同一个应用程序的不同用户,应当以非常类似的方式查询数据库。这将使他们的
查询已被分析并存储于 S G A 的可能性得到增加。这样的数据共享不仅包括被检索的表和行,
也包括被使用的实际查询。如果查询完全相同,一个查询的语法分析版本就可能已在 S Q L 共
享池中,这会大大缩短处理这个查询所需的时间。
第三,应限制使用动态 S Q L ,动态S Q L 使用D B M S _ S Q L 软件包,即使在 S Q L 共享池中存
在一个完全相同的查询值,也总是要重新进行语法分析。动态 S Q L虽然是一个很有用的功能,
但是不应把它运用于应用程序数据库中的大多数访问。
存储过程可以在应用程序的开发中使用。使用它们时,很有可能同样的代码被多次执行。
因此,可以充分利用 S Q L 共享池。也可以手工编译这些过程、函数及软件包,以避免运行时
编译。例如,可以用create procedure命令来创建一个过程,如下所示:
196 第二部分 数据库管理
下载
当创建一个过程时, O r a c l e会自动对它进行编译。若该过程以后变得无效,数据库必
须在执行它之前重新编译。为避免运行时引起编译,可以使用下面所示的 alter procedure命
令:
通过D B A _ S O U R C E 视图中的Te x t ( 文本)列,可以查看一个数据库中所有过程的 S Q L 文本。
U S E R _ S O U R C E 视图将显示用户所拥有的过程。这些视图引用 S Y S . S O U R C E $表。由于这个表
是数据字典的一部分,所以过程代码就存储在 S Y S T E M 表空间中。因此,如果使用这些对象,
就必须确保给S Y S T E M 表空间分配更多的空间
—
一般是它的两倍。
要讨论的两种设计原则
—
限制用户的访问次数和调整他们的请求
—
要求应用程序开
发人员尽可能多地知道数据的使用方式和涉及的访问路径。因此,用户同时参与应用程序设
计和表设计是十分重要的。如果用户花过多的时间用数据模型去做表图,而用很少时间与开
发人员讨论访问路径的话,做出来的应用程序就很难满足用户的需要。
8.2 调整S Q L
与应用程序设计一样,对 S Q L 语句的调整似乎与数据库管理人员的责任毫不相干。然而,
数据库管理人员应参与检查被写成应用程序一部分的 S Q L 。一个良好设计的应用程序,如果
使用的S Q L 结构不理想,仍然会遇到性能问题。在一个正确设计的数据库中,应用程序设计
及S Q L 问题会引发大多数的性能问题。
在一个关系型数据库中,应用程序设计中的数据物理位置不如它的逻辑位置重要。然而,
数据库必须查找数据,以便将其返回执行查询的用户。所以,调整 S Q L 的关键是使数据库寻
找数据的路径最简化。
在大多数O r a c l e表中,每个行都有与行相关的 R o w I D (行标志)。R o w I D 含有关于行的物理
位置信息(行的文件、文件中的数据块、数据块中的行 )。O r a c l e 7和O r a c l e 8 中的R o w I D 格式截
然不同。
当执行一个不带w h e r e 子句的查询时,数据库通常将执行全表扫描 (full table scan),从表
中读取每一个数据块。要做全表扫描,数据库先定位表中的第一个数据块,而后按顺序读取
表中的其他所有数据块。对于大型表,这将会是一个漫长的过程。
当查询一个特定行时,数据库可以使用一个索引值来帮助加快检索需要的数据行。一个
索引把表中的逻辑值映射到它们的 R o w I D ,R o w I D 再映射到指定的物理位置。索引可以是唯
一的
—
每一个值出现的次数不超过一次,也可以不是唯一的。索引只为其值为 N O T N U L L
的被索引列存储R o w I D。
可以同时索引多个列,这称为连锁索引。如果这个连锁索引中的头一列用于查询的 w h e r e
子句中,就使用这个索引。如果只是对查询简单地指定一个索引,并不一定使查询的速度加
快,因为索引必须适合所需的访问路径。
假设一种3列连锁索引的情况。如下面例子所示,这个连锁索引被创建在 E M P L O Y E E 表
的C i t y 、S t a t e 和Z i p 列上:
第8章 数据库调整 197
下载
如果执行如下格式的查询:
该连锁索引将不被使用,因为它的头一列 ( C i t y )没有用在w h e r e 子句中。如果用户频繁运
行这种查询,应重新安排连锁索引的列让 S t a t e作为第一列,以反映实际的使用情况。
使表的数据尽可能有序化也十分重要。虽然这在相关理论中并不重要,但在为查询检索
数据时,却起着至关重要的作用。如果用户频繁执行范围查询 (即,选择指定范围内的值),则
在解决查询问题时,将数据排序会使读取的数据块很少,从而改进操作性能。索引中的有序
化条目,将指向表中相邻的数据块,而不是指向散布于数据文件中的数据块。
例如,下面是一个范围查询的示例:
如果E M P L O Y E E 表中的物理记录按 E m p n o列进行排序,那么此查询将会读取很少的数据
块。这将改进查询的性能。为确保表中的行正确排序,可以提取记录到一个平面文件,将文
件中的这些记录排序,然后删除旧的记录并从已排序的文件中重新装载它们。
作为提取数据到平面文件的一种替代方案,可以使用 O r a c l e的内部排序过程来排序数据。
理论上讲,可以通过用 create table as select命令创建另一个表来记录一个表的数据行。不过,
create table as select和insert as select命令并不允许你指定一个 order by子句。
若回避这个限制,可在基表上创建一个视图。这个视图应按该表的全部列及 R o w N u m 伪
列分组。下面程序段中示出的视图按 E M P L O Y E E表中的全部列选择和分组:
查询时,group by子句将强制使用 O r a c l e 内部的排序操作,从 E M P L O Y E E _ V I E W 中选择
的数据行将按E m p n o的顺序排序。这样可以使你能创建一个从E M P L O Y E E _ V I E W 中选择的表。
结果将是:创建一个E M P L O Y E E的副本,数据行被正确排序。
在上面的例子中,根据E m p n o 值对数据进行排序。可能经常需要用一个属性列 (例如N a m e
198 第二部分 数据库管理
下载