5.1 调整设计:最佳实践
保守估计,在一个应用程序中至少50%的时间存在性能问题。在应用程序和相关数据库结构的设计过程中,随着时间的推移,应用程序体系结构可能并不知道业务使用应用程序数据的所有方法。因此可能有一些组件在初始版本中性能较差,而随着应用程序的业务利用率发生改变或增加,以后又出现其他问题。
有些情况下,修正起来相对简单:改变初始参数、添加索引或重新安排在非高峰时段执行大型操作。在其他情况下,无法在不改变应用程序体系结构的情况下修正问题。例如,应用程序可能被设计为对所有数据访问都大量地重用函数,从而使函数调用其他的函数,而被调用的函数又调用另外的函数,甚至执行最简单的数据库操作也要调用函数。结果,单个数据库调用可能产生数以万计的函数调用和数据库访问,这种应用程序通常无法很好地扩展。随着更多的用户被添加到系统中,每个用户大量地执行操作所带来的CPU负担将降低单个用户的性能。调整作为应用程序一部分执行的SQL语句对改善性能没多大帮助,因为这些SQL语句自身可能已经很好地调整过。相反,纯粹是因为执行操作数量太多导致了性能问题。
下面的最佳实践规则看起来十分简单,但它们在数据库应用程序中常被违背,这些违背直接导致性能问题。规则总有例外情形:对软件或环境的下一个改动可能允许违反规则,而不会影响性能。一般来说,下面这些规则允许在应用程序利用率增加时满足性能需求。
5.1.1 做尽可能少的工作
一般来说,终端用户并不关心底层的数据库结构是否完全标准化为第五范式,或者是否按照面向对象的标准进行设计。用户希望执行业务过程,并且数据库应用程序应该是帮助业务过程尽快完成的工具。设计关注的焦点不应是取得理论性的设计完善性,而应该关注终端用户执行工作的能力。因此,应该简化应用程序每个步骤所涉及的过程。
与应用程序开发团队协商可能是一件难事。如果应用程序开发团队或企业设计师坚持使用完全标准化的数据模型,则DBA应指出:即使是最简单的事务,也会涉及多少个数据库操作步骤。例如,复杂事务(如发货单的行式项)的插入可能涉及许多代码表查询和多次插入。对于单个用户,这可能不会带来问题;但对于许多并发用户,这种设计就可能导致性能问题或锁定问题。从性能计划的观点看,插入(INSERT)应涉及尽可能少的表,查询应该检索已经以某种格式存储的数据,这种格式应该尽量接近用户请求的最终格式。完全标准化的数据库和面向对象的设计倾向于在复杂查询期间需要大量连接。虽然应该努力维护可管理的数据模型,但首先强调的重点应该是应用程序的功能及其满足业务性能需求的能力。
1.在应用程序设计中,努力消除逻辑读
过去都是重点关注消除物理读。虽然这是一个好想法,但只有在需要逻辑读时才会进行物理读。
下面举一个简单示例。使用SYSDATE函数从DUAL中选择当前时间。如果选择降至秒级,该值将每天改变86 400次。即使如此,仍有应用程序设计人员在重复执行这个查询,每天执行数百万次。这种查询很可能一天只执行很少的物理读。因此,如果只关注调整物理I/O,则很可能会忽视它。然而,它可能严重影响应用程序的性能。解决方法是通过使用可用的CPU资源,每次执行查询都强制Oracle执行工作,使用处理能力来找出并返回正确数据。当越来越多的用户重复执行该命令时,可能就会使该查询使用的逻辑读数量超出其他所有查询使用的逻辑读数量。一些情况下,服务器上的多个处理器专门服务于这种重复的小型查询。如果多个用户需要读取相同的数据,应将数据存储在表中或程序包变量中。
注意:
从Oracle Database 10g开始,DUAL表是一个内部表(基于内存),因此,只要引用DUAL的查询中的列列表不使用*,访问它就不会产生consistent gets。
考虑下面的实际示例。程序员希望在程序中实现暂停,迫使程序在两个步骤完成之间等待30秒。因为环境的性能无法一直保持一致性,所以程序员用下面的格式编码例程(以伪代码的形式显示):
perform Step 1 select SysDate from DUAL into a StartTime variable begin loop select SysDate from DUAL in a CurrentTime variable; Compare CurrentTime with the StartTime variable value. If 30 seconds have passed, exit the loop; Otherwise repeat the loop, calculating SysDate again. end loop Perform Step 2.
这是合理方法吗?绝对不是!它将完成开发人员所希望的工作,但对应用程序有很大影响。更重要的是,DBA无法改进其性能。这种情况下,付出的代价将不是来自于I/O活动——DUAL表停留在实例的内存区域——而是来自CPU活动。每个用户每次运行该程序时,数据库将花费30秒来使用系统可以支持的、尽可能多的CPU资源。在这种特定情况下,SELECT SYSDATE FROM DUAL查询占用了应用程序40%以上的CPU时间。所有这些CPU时间都浪费了。调整数据库初始参数无法解决这个问题。调整单个SQL语句也没有任何帮助,必须修改应用程序设计,以消除不必要的命令执行。例如,这种情况下,开发人员可在操作系统级别使用SLEEP命令,或在PL/SQL程序中使用DBMS_LOCK.SLEEP()过程来实施相同的行为,而不需要访问数据库。
对于赞成根据缓冲区缓存命中率进行调整(在11g和12c中,最好使用基于等待的调整)的人来说,这个数据库几乎有100%的命中率,这是由于具有大量完全不必要的逻辑读,而没有相关的物理读。缓冲区缓存命中率来自于逻辑读的数量和物理读的数量的比较,如果10%的逻辑读需要物理读,缓冲区缓存命中率就是90%。低命中率可标识执行大量物理读的数据库,极高的命中率(如本例中的情况)可标识执行过多数量逻辑读的数据库。必须看一看生成逻辑读和物理读的命令的缓冲区缓存命中率。
2.在应用程序设计中,努力避免对数据库的往返访问
记住,现在正在调整应用程序而不是查询。在调整数据库操作时,可能需要将多个查询结合到一个过程中,从而可以只访问一次数据库,而不是针对每个屏幕多次访问数据库。这种绑定查询方法尤其与依赖于多个应用程序层的“瘦客户端”应用程序相关。查看基于返回值而相互关联的查询,并查看是否有可能将它们转换到单独的代码块中。目标不是建立永远无法完成的整体式查询,而是避免做一些不需要的工作。这种情况下,在数据库服务器、应用程序服务器和终端用户的计算机之间的来回通信就是应该调整的目标。
这种问题在复杂的数据项表单上很常见,通过单独的查询来填充显示在屏幕上的每个字段。每个查询都要单独访问数据库。和前面的示例一样,迫使数据库执行大量相关的查询。即使调整了每个查询,来自于大量命令的负荷(乘以大量用户)也将消耗服务器上不少可用的CPU资源。这种设计可能也会影响网络利用率,但网络很少会成为问题:问题在于访问实例的次数。
在程序包和过程中,应努力消除不必要的数据库访问。在本地变量中存储经常需要的值,而不是重复查询数据库。如果不需要访问数据库来查询信息,则不要建立这种访问。这听起来很简单,但应用程序开发人员经常没有考虑到这种建议。
没有任何初始参数可以使这种改动生效。这是一种设计问题,需要开发人员、设计人员、DBA和应用程序用户在应用程序性能的计划和调整过程中积极参与。
3.对于报告系统,按照用户查询的方式存储数据
如果了解将要执行哪些查询,如通过参数化的报告,则应该努力存储数据,从而使Oracle以尽可能少的工作将表中数据的格式转换为提供给用户的格式。这可能需要创建或维护物化视图或报告表。当然,这种维护是数据库和DBA要执行的额外工作,但以批量模式执行这种维护,不会直接影响终端用户。另一方面,终端用户可从更快执行查询的能力中受益。作为整体的数据库,将执行较少的逻辑读和物理读,因为和针对物化视图的终端用户查询相比,很少执行对基表的访问来填充和刷新物化视图。
4.避免重复连接到数据库
打开数据库连接可能比在这个连接中执行命令花费的时间更多。如果需要连接到数据库,则保持连接为打开状态,并重复使用该连接。关于Oracle Net和优化数据库连接的更多信息,参见第17章。
某个应用程序设计人员过分注重标准化,并将所有代码表移到自己的数据库中。结果,订单处理系统中的大多数操作反复打开数据库链接以访问代码表,因此严重妨碍了应用程序的性能。再次提出,调整数据库初始参数不会产生最大的性能收益,应用程序仍会由于设计不当而变得缓慢。
5.使用正确的索引
在消除物理读的努力中,有些应用程序开发人员在每个表上创建大量的索引。除了在数据加载次数方面的影响外,要支持查询并不需要其中的许多索引。在OLTP应用程序中,不应使用位图索引。如果某列具有非常少的不同值,应考虑不在其上建立任何索引。优化器支持“跳跃扫描”索引访问,因此它可以选择一组列上的一个索引,即使索引中最主要的列不是查询的限制条件。对于诸如Oracle Exadata等平台,可能基本不需要索引,由于不再需要在DML操作期间维护索引,将可以尽量快地运行查询。
5.1.2 做尽可能简单的工作
现在已消除了不必要的逻辑读、不需要的数据库往返访问、难以管理的连接和不适当的索引所造成的性能降低,下面讨论其余需要考虑的事项。
1.在原子级执行
可使用SQL将许多步骤组合到一个大型查询中。某些情况下,这可能给应用程序带来优势:可创建存储过程并重用代码,从而减少执行数据库往返访问的数量。然而,也可能组合了过多内容,因此创建了无法尽快完成的大型查询。这些查询通常包括多个分组操作集、内联视图以及针对数百万行的复杂多行计算。
如果正在执行批处理操作,就能将这种查询分解为它的原子级组成部分,创建临时表以存储每个步骤中的数据。如果有需要耗费数小时才能完成的操作,则几乎总可以找到方法,将这种操作分解为较小的组成部分。分而治之能解决性能问题。
例如,批处理操作可能组合多个表中的数据,执行连接和排序,然后将结果插入到表中。如果只是较小的规模,这可以令人满意地执行。如果是较大规模,则可能不得不将该操作划分为多个步骤:
(1)创建工作表(可能作为Oracle全局临时表)。从查询的某个源表中将一些行插入到工作表中,在此过程中只选择以后要关注的行和列。
(2)创建第二个工作表,其中的行和列来自于第二个源表。
(3)在工作表上创建需要的索引。注意,此时所有的步骤可以并行执行:插入、源表的查询及索引的创建。
(4)执行连接,再次并行执行。连接输出可加入到另一个工作表中。
(5)执行所需要的任何排序。排序尽可能少的数据。
(6)将数据插入目标表中。
遍历所有这些步骤的原因何在?因为这可以单独调整它们,相对于Oracle作为单个命令完成它们的速度,能调整它们使其更快速地完成。对于批处理操作,应考虑使这些步骤尽可能简单。需要管理分配给工作表的空间,但这种方法可极大地改进批处理的性能。
2.消除不必要的排序
作为上述示例的一部分,最后执行了排序操作。一般来说,排序操作不适合于OLTP应用程序。在对整个行集完成排序操作之前,并不会向用户返回任何行。但是,一旦这些行可用,则行操作将行返回给用户。
考虑下面的简单测试:对大型表执行完整表扫描。只要查询开始执行,则显示第一行。现在执行相同的完整表扫描,但在没有索引的列上添加一个ORDER BY子句。此时不会显示任何行,直到对所有的行完成排序。发生这种情况的原因何在?因为对于第二个查询,Oracle在完整表扫描的结果上执行了SORT ORDER BY操作。因为这是一个集合操作,在执行下一个操作之前必须完成该集合。
现在,设想一个应用程序,其中在一个过程中执行了许多查询。每个查询都有一个ORDER BY子句。这将变成一系列嵌套查询:直到前一个操作完成,后面的操作才可以开始。
注意,UNION操作也执行排序。如果适合于业务逻辑,则使用UNION ALL操作替代UNION操作,因为UNION ALL操作并不执行排序。
注意:
UNION ALL操作没有消除结果集中具有重复数据的行,因此它可能生成比UNION操作更多的行,两者可能有不同的结果。
3.消除使用撤消的需求
执行查询时,Oracle将需要维护被查询行的读一致性映像。如果另一个用户修改了某一行,则数据库需要查询撤消段,以查看查询开始时该行的情况。如果应用程序设计要求查询频繁地访问某些数据,而其他人可能会同时改变这些数据,则这种应用程序设计就强制数据库做更多的工作:为得到一条数据,它不得不查看多个位置。再次指出,这是设计问题。DBA能配置撤消段区域以减少查询遇到“快照太旧”错误的可能性,但改正这种基础性的问题需要改变应用程序的设计。
5.1.3 告诉数据库需要知道的内容
在执行查询期间,Oracle的优化器根据统计信息来评估采用的数以千计的可能路径。管理这些统计信息的方式可能严重影响查询的性能。
1.保持更新统计
应该每隔多长时间收集一次统计信息呢?在每次对表中的数据进行重要改动时,都应该收集这些表的统计信息。如果对表进行了分区,则可以逐个分区地分析它们。从Oracle Database 10g开始,可使用自动统计信息收集(Automatic Statistics Gathering)特性来自动完成统计信息的收集。默认情况下,该过程在每晚10点到第二天早6点以及周末全天的维护窗口期间收集统计信息。当然,在白天删除易失性表时,或者批量加载的表的大小增加了10%以上时,仍可手动完成统计信息的收集工作。对于Oracle Database 11g或12c上的分区表,在创建或更新分区级别的统计信息时,“增量统计信息”将使全局统计信息保持最新。Oracle Database 12c允许在模式的表中或表的分区中并行收集统计信息,从而将收集统计信息的能力提升到新水平。另外,Oracle Database 12c中新的混合柱状图类型将基于高度的柱状图与频率柱状图结合起来。
因为分析工作通常是耗费数个小时执行的批处理操作,通过在会话级中改进排序和完整表扫描性能,可以调整分析工作。如果正在手动执行分析,则在收集统计之前,在会话级增加DB_FILE_MULTIBLOCK_READ_COUNT参数的设置,或在系统级增加PGA_AGGREGATE_ TARGET参数的设置。如果没有使用PGA_AGGREGATE_TARGET,或不想修改系统范围的设置,则增加SORT_AREA_SIZE(它在会话级可修改)。这些调整将增强分析执行的排序和完整表扫描的性能。
警告:
当跨连接传输太多的数据块时,在RAC数据库环境中增加DB_FILE_MULTIBLOCK_ READ_COUNT参数会产生性能问题。该值与平台相关,但在大多数平台上都是1MB。
2.在需要的地方使用提示
大多数情况下,基于成本的优化器(CBO)选择最有效的查询执行路径。然而,可能有关于更好路径的信息。可给Oracle提供能够影响连接操作、整体的查询目标、使用的特定索引或并行化查询的提示。
5.1.4 最大化环境中的吞吐量
在理想环境中,绝对不会需要查询缓冲区缓存外部的信息;所有数据一直停留在内存中。然而,除非使用非常小的数据库,否则这并不现实,因此本小节将介绍最大化环境吞吐量的指导原则。
1.使用适当的数据库块大小
应为所有表空间使用8KB的块大小,以下情况除外:Oracle支持部门建议使用其他块大小,或行的平均长度超长,超过8KB。所有Oracle开发和测试,特别是Exadata等数据库一体机,都应使用8KB块大小。
2.设计吞吐量,而不是设计磁盘空间
假设原来是运行在8个256GB磁盘上的应用程序,现在将其移动到一个2TB的磁盘上,该应用程序运行得更快还是更慢呢?一般来说,它将运行得较慢,因为单个磁盘的吞吐量不可能等同于8个单独磁盘结合起来的吞吐量。不应该根据可用空间来设计磁盘布局(常见的方法),而应根据可用磁盘的吞吐量来设计布局。可决定只使用每个磁盘的一部分。生产级应用程序将不会使用磁盘上剩余的空间,除非磁盘的可用吞吐量得以改进。
3.避免使用临时段
无论何时,尽可能在内存中执行所有排序。写入到临时段中的任何操作都会潜在地浪费资源。当SORT_AREA_SIZE参数(或PGA_AGGREGATE_TARGET参数,如果使用该参数的话)没有分配足够的内存来支持操作的排序需求时,Oracle就会使用临时段。排序操作包括索引创建、ORDER BY子句、统计信息收集、GROUP BY操作和一些连接。本章前面介绍过,应该努力对尽可能少的行排序。在执行剩余的排序时,在内存中执行。
5.1.5 分开处理数据
如果必须在数据库上使用对性能有很大影响的操作,可尝试将工作划分到更便于管理的组块中。通常可严格限制操作处理的行数量,从而可以实实在在地改善性能。
1.使用分区
分区可使终端用户、DBA和应用程序支持人员受益。对于终端用户,有两个潜在优点:改善查询性能和改进数据库的可用性。分区排除(partition elimination)技术可改善查询性能。优化器知道哪些分区可能包含查询请求的数据。因此,会从查询过程中排除不会参与该过程的分区。由于只需要较少的逻辑读和物理读,因此查询可以更快地完成。
注意:
分区选项是数据库软件企业版中需要额外成本的选项。
分区可为DBA和应用程序支持人员带来好处,从而改进数据库的可用性。可在单个分区上执行许多管理性的函数,并且不会影响表的剩余部分。例如,可截取表的一个分区。可划分一个分区,将其移到不同的表空间,或使用已有的表切换它(这样前面的独立表将被认为是一个分区)。可每次收集一个分区上的统计信息。所有这些功能缩小了管理性函数的范围,从而减少了它们在整体上对数据库可用性的影响。
2.使用物化视图
可使用物化视图来划分用户对表执行的操作类型。创建物化视图时,可指示用户直接查询物化视图,或者依赖于Oracle的查询重写功能将查询重定向到物化视图。这种情况下可得到数据的两个副本:一个用于服务新事务数据的输入,另一个(物化视图)用于服务查询。由此,可将一个数据副本进行脱机维护,而且不会影响另一个数据副本的可用性。同时,物化视图可预先连接表并预先生成聚集,从而使用户查询可执行尽可能少的工作。
3.使用并行化
几乎每个主要操作都可以并行化,包括查询、插入、对象创建和数据加载。并行选项允许将多个处理器和I/O通道用于一个命令的执行,从而有效地将该命令划分为多个较小的协同命令。因此,命令可更好地执行。可在对象级中指定并行化程度,并通过在查询中添加提示来重写。
5.1.6 正确测试
在大多数开发方法学中,应用程序测试有多个阶段,包括模块测试、完整的系统测试和性能压力测试。很多时候,由于应用程序接近交付期限而带来时间约束,并没有充分地执行完整的系统测试和性能压力测试。其结果是应用程序发布为产品时,无法保证应用程序的整体功能和性能可满足用户的需求。这是重大缺陷,应用程序的任何用户都不会容忍这一点。用户不仅需要应用程序的一个组成部分可以正常工作,而且需要整个应用程序都可以正常工作,以支持业务过程。如果他们不能在一天中做完应做的业务量,就表示应用程序失败。
下面是需要考虑调整应用程序的一条关键原则:如果应用程序减慢了业务过程的速度,则应该调整它。执行的测试必须能确定在期望的产品负载下应用程序是否会妨碍业务过程的速度。
1.使用大量数据测试
本章前面介绍过,数据库中的对象在使用一段时间后会有不同的运行状态。例如,表的PCTUSED设置可能使块只使用了一半或产生了行链接。无论哪种情况,都会造成性能问题,只有在使用应用程序一段时间后才会看到这种问题。
数据卷的更进一步的问题与索引相关。当B-树索引增长时,它可能在内部分离:索引中添加了额外层。因此,可将新的层设想为索引中的索引。索引中额外的层会增加索引对数据加载速率的负面影响。只有在分离索引后才会看到这种影响。对于前一两个星期在生产环境中工作良好的应用程序,如果在数据量达到临界水平后突然运行不稳定,则该应用程序不支持业务需求。在测试中,没有以产品速率加载的产品数据的替代物,尽管表已经包含了大量的数据。拆分叶块和维护索引时,Oracle不得不锁定叶上的所有分支块,包括根块。在维护操作期间,其他需要访问索引的会话将发生争用。
2.使用许多并发用户测试
使用一个用户进行测试并不能反映大多数数据库应用程序预期的产品利用率。必须能够确定并发用户是否会遇到死锁、数据一致性问题或性能问题。例如,假设一个应用程序模块在其处理期间使用工作表。将行插入到工作表中,对其进行操作,然后查询。另一个应用程序模块进行类似的处理,并使用相同的表。在同时执行时,两个过程尝试彼此使用对方的数据。除非正在使用同时执行多个应用程序功能的多个用户进行测试,否则就可能无法发现这种问题和它将产生的业务数据错误。
使用大量并发用户进行测试也可帮助标识应用程序中用户频繁使用撤消段来完成查询的某些区域,从而影响性能。
3.测试索引对加载次数的影响
索引列的每个INSERT、 UPDATE或DELETE操作可能都比针对未建索引的表的相同事务要慢。虽然也有一些例外情况,例如排序数据就具有较小的影响,但这一规则通常都是正确的。影响取决于操作环境、涉及的数据结构及数据排序的程度。
在当前环境中,每秒可插入多少行?下面执行一系列简单测试。创建没有任何索引的表,并在其中插入大量行。重复该测试,减少物理读对定时结果的影响。计算每秒钟插入行的数量。在大多数环境中,可以每秒将数以万计的行插入到数据库中。在其他数据库环境中执行相同的测试,从而可标识具有明显区别的地方。
现在考虑应用程序。能否通过应用程序,在任何位置都以接近刚才计算的速率将行插入表中?许多应用程序以比环境所支持的速率低5%的速率运行。这些应用程序会由于不需要的索引或本章前面介绍的各种代码设计问题而停顿。如果应用程序加载速率降低,假设从每秒40行降到每秒20行,则调整重点应不仅是速率降低的原因,而且是在支持每秒插入数千行的环境中,应用程序每秒只能插入40行的原因。添加另一个索引很简便,但在DML操作期间(INSERT、DELETE、UPDATE、MERGE)会增加三倍开销。
4.使所有的测试可重复
许多管理严格的行业都有测试的标准。它们的标准非常合理,所有测试工作都应遵循这些标准。其中一条标准是所有测试必须可重复。为遵循这些标准,必须能重新创建使用的数据集、执行的额外动作、预期的准确结果以及看见并记录的准确结果。必须在产品硬件上执行用于验证应用程序的产品前测试。将应用程序移到不同的硬件需要重新测试这个应用程序。测试者和企业用户必须签字确认所有的测试。
在听到这些限制后,大多数人都会认同它们是任何测试过程中采取的良好步骤。实际上,企业用户可能期望开发应用程序的人遵循这些标准,即使特定的行业不需要这些标准。但是否遵循了这些标准?如果没有遵循,原因何在?没有遵循这些标准的两个常见原因是时间和成本。这些测试需要计划、员工资源、企业用户的参与以及执行和文档化的时间。对产品规模硬件的测试可能需要购买额外的服务器。这些是最明显的成本,但无法执行这些测试而消耗的企业成本又是多少呢?在一些医疗保健行业中,必须实现验证系统的测试需求,因为这些系统直接影响到关键产品的完整性,如血液供给中心的安全设施。如果企业具有由应用程序所服务的关键组成部分(如果没有,则构建这个应用程序的原因何在?),则必须考虑不充分的、草率的测试所消耗的成本,并将这些潜在浪费的成本告知企业用户。对不正确数据或不满意的低性能的风险评估必须有企业用户的参与。当然,这可能导致延长期限以支持适当的测试。
许多情况下,从项目的开始就没有遵循测试标准,从而产生匆忙的测试周期。在项目开始时,如果在企业级中有一致的、彻底的、良好归档的测试标准,那么测试周期在最终执行时就会较短。测试者提前很久就会知道需要可重复数据集。可以使用测试模板。如果有测试结果中存在问题,或需要根据改动而重新测试应用程序,则可重复测试。同时,应用程序用户将知道,测试必须足够健壮,可以模仿应用程序的产品利用率。另外,测试环境必须可以自动完成在产品中自动化完成的任务,尤其是当开发人员在开发环境中使用了很多手动过程的情况下。如果系统由于性能原因而测试失败,原因可能就来自一个设计问题(前面已经介绍过),或者是单个查询的问题。
5.1.7 标准的可交付成果
如何知道应用程序是否已经准备好迁移到产品环境?应用程序开发方法学必须清楚地在格式和细节级别方面定义生命周期每个阶段所要求的可交付成果。这些可交付成果应该包括下列每一项的规范:
●实体关系图
●物理数据库图
●空间需求
●查询和事务处理的调整目标
●安全性需求
●数据需求
●查询执行计划
●验收测试过程
下面将描述每一项。
1.实体关系图
实体关系(Entity Relationship,E-R)图表明了在组成应用程序的实体之间标识的关系。E-R图对于理解系统的目标至关重要。它们也帮助标识与其他应用程序的接口点,并且确保企业中定义的一致性。
2.物理数据库图
物理数据库图显示了从实体中生成的物理表,以及从逻辑模型中定义的属性所生成的列。即使不是所有数据建模工具都支持逻辑数据库图到物理数据库设计的自动转换,但大多数数据建模工具还是支持这种自动转换的。物理数据库图形表示工具通常能生成创建应用程序对象所需要的DDL。
可使用物理数据库图表来标识在事务中最可能涉及的表,也能标识在数据输入或查询操作期间哪些表经常一起使用。可使用这些信息来有效地计划在可用的物理设备(或ASM磁盘组)中如何分布这些表(及其索引),从而减少遇到的I/O争用数量。
在数据仓库应用程序中,物理数据库图应显示用户查询访问的聚集和物化视图。虽然包含派生的数据,但它们是数据访问路径的关键组成部分,必须进行归档。
3.空间需求
空间需求可交付成果应显示每个数据库表和索引的初始空间需求。5.2.2小节将介绍表、群集和索引的适当大小推荐值。
4.查询和事务处理的调整目标
改变应用程序设计可能对应用程序性能产生严重影响。应用程序的设计也可能直接影响调整应用程序的能力。由于应用程序设计对DBA调整应用程序性能的能力有很大影响,因此DBA必须参与设计过程。
必须在系统投入生产之前标识它的性能目标,而不可过分强调感觉方面的期望值。如果用户期望系统至少与现有系统一样快,那么任何低于这个速度的系统都是不可接受的。必须定义和批准应用程序中使用最多的每个组成部分的估计响应时间。
在这个过程中,重要的是建立两组目标:合理的目标和“伸展”目标。伸展目标表示集中努力的结果,超出限制系统性能的硬件和软件约束。维护两组性能目标可帮助关注针对如下目标的努力:真正关键任务的目标以及超出核心系统可交付成果范围的目标。根据不同的目标,应该建立查询和事务性能的控制边界。如果控制边界交叉,则判定应用程序性能“失控”。
5.安全需求
开发团队必须指定应用程序将使用的账户结构,包括应用程序中所有对象的所有权以及授予权限的方式。必须清楚地定义所有角色和权限。这一部分中的可交付成果将用于生成产品应用程序的账户和权限结构(Oracle安全性功能的完整概述请参见第10章)。
根据不同的应用程序,可能需要指定从联机账户的账户利用率中分离出的批处理账户的账户利用率。例如,批处理账户可能使用数据库的自动登录特性,而联机账户必须手动登录。应用程序的安全计划必须支持这两种用户。
与空间需求可交付成果类似,安全计划是特别需要DBA参与的领域。DBA应能设计满足应用程序需求的实现,同时符合企业数据库安全计划。
6.数据需求
必须清楚地定义数据输入和检索方法。在应用程序处于测试环境中时,必须测试和验证数据输入方法。应用程序任何特殊的数据归档需求也必须文档化,因为它们将是应用程序特有的。
必须描述应用程序的备份和恢复需求。然后将这些需求与企业数据库备份计划(查看第13章了解其指导原则)进行比较。任何超出站点标准的数据库恢复需求都需要修改站点的备份标准,或添加一个模块以适应应用程序的需求。
7.查询执行计划
执行计划是数据库在执行查询时需要完成的步骤。通过EXPLAIN PLAN命令、SET AUTOTRACE命令或SQL监控工具生成执行计划,第8章将描述这一点。记录针对数据库的最重要查询的执行计划,有助于计划索引利用率和应用程序的调整目标。在产品实现之前生成它们将简化调整工作,并在发布应用程序之前标识潜在的性能问题。生成最重要查询的解释计划也有助于执行应用程序代码复查的过程。
如果正在实现第三方的应用程序,则可能无法看到应用程序正在生成的所有SQL命令。第8章将介绍,可使用Oracle的自动调整和监控实用工具来标识两个时间点之间执行的资源最密集的查询。Oracle Database 12c中新增了多个自动调整特性,如提高了适应性SQL计划管理和并行度(Degree Of Parallelism,DOP)自动化精度,从而帮助修复隐藏较深或难以访问的查询问题。
8.验收测试过程
开发人员和用户必须清楚地定义在应用程序可以迁移到生产环境之前应该实现什么样的功能和性能目标。这些目标将组成测试过程的基础,在应用程序处于测试环境中时对其执行这些测试过程。
这些过程也应该描述如何处理未满足要求的目标,而且应清楚地列出在系统继续发展前必须满足的功能目标。此外也应提供非关键功能目标的第二个列表。这种对功能能力的分离将帮助解决调度冲突并结构化适当的测试。
注意:
作为验收测试的一部分,应该测试所有应用程序接口,并验证它们的输入和输出。