今天的笔记要从2.5 Application Design Principles开始
2.5 应用设计原则
--朴素简单的应用设计
--数据模型
--表和索引的设计
--使用视图
--sql执行效率
--实施应用
--应用发展趋势
2.5.1 应用设计的简洁性
应用和其它工业产品的设计是一样的。会依靠好的设计结构,机器以及工具,容易使用和维护,并且在概念上特别简单。一般条件下,如果设计看起来时正确的,那工具就对了,在建立引用的过程中,我们要坚持这个原则。
考虑以下设计问题
--如果表的设计复杂到没人能完全理解,那么这个表就是坏的设计。
--如果sql描述是太长,没有办法被优化器有效的进行实时优化,那就是一句坏的sql,基础的事务,或者表的设计。
--如果索引中的列和表中的列一样,那也是坏的索引设计。
--如果对于在线用户提交的问题没有快速响应的限制,那么就可能是坏的用户接口和事务设计。
--如果数据库的被软件的多个应用逻辑调用,那就是一个坏的软件开发方法。
2.5.2 数据模型
数据模型偶那个对于成功的相关应用设计是很重要的。这必须以快速展现交易实际的方式实现。冒险的是,关于正确数据模型会有激烈的争论。最重要的是应用巨大的模型效果去影响最频繁的商业交易。在模型的语法,有很大的诱惑是会花费太多的时间到非核心的数据元素上,这导致增加了开发引导次数。使用模型工具能快速生成模式定义并且当需要一个快速出行的时候也是有用的。
2.5.3 数据模型
表的设计在很大程度上会比较核心事务的灵活性和性能,为了保证数据库的灵活性和容纳不可预见的负载,表的设计应该和数据模型的设计类似,它应该至少经过三次正常化的设计。但是 ,用户需要一定量的核心事务由于性能的目的选择性的非正常化。
oracle提供了很多选项供存储综合和预先链接的数据,比如集群表和物化视图,这些特性允许使用更简单的表设计去适应初始化。
焦点和资源应该花费在业务关键表上,所以优化性能能被实现,对于非关键表,为了达到更加快速的应用开发,设计中的快捷键会被适应。但是,如果一个非核心表的雏形和设计会成为一个性能问题。那么就要应用补救的设计。
基于应用设计者生成的sql,
索引的设计也是需要不断重复的过程。但是,可能要通过强制主键约束去在已知的访问样式上建立索引,例如人的名字。通过在现实的数据量上对应用进行测试,某些问题需要通过建立更好的索引来改善。以下是当建立新的索引的时候需要考虑的设计思路:
添加列到索引上 或者建立索引组织表
使用不同的索引类型
找到索引的花费值
级联索引
在索引中对列排序
2.5.3.1 附加列到索引上 或者建立索引组织表
降低逻辑io的最容易的一个解决办法是从执行计划中消除表的访问。可以追加需求中涉及到的列到索引中。这些列可以是列表中的列,需要链接的列,或者排序的列。这个技术在加速在线应用的响应时间特别有用,因为消费IO被减少了。这是当应用在第一次获取一定数据的最实用的方法。
这个技术最极端是建立一个索引组织表。但是必须注意增加的叶子节点的数量会破坏减少的io。
2.5.3.2 使用不同的索引类型
2.5.3.2.1 b 树索引
这是标准的索引类型,主键和高选择的索引是非常优秀的。用b树索引能够用来提取被索引列排序的数据。
2.5.3.2.2 位图索引
这个索引适合集合基数低的表。通过压缩基数,能够用最少的io生成大量的rowid。在非选择性的列上联合位图索引允许在有and和or选项的时候可以以最小的io获得最大的rowid。位图索引在需要使用count函数的时候特别有效,因为可以通过索引满足问题。
2.5.3.2.3 基于函数的索引 这些索引允许访问来自基本数据的函数值。基于函数的索引在使用null值的时候会有局限性,并要求使优化器可用。
2.5.3.2.4 分区索引
全局索引分区后,允许分区的裁剪去代替对全索引的访问,并且减少了io,通过定义分区列表的范围,对于正确分区索引的快速索引扫描可以获得最快的反应时间
2.5.3.2.5 反向索引
这些索引用来消除热键插入。这些索引在插入的时候性能是非常优秀的。但是他们不能用来做索引范围扫描。
2.3.3.3 找到索引的消耗
建立和维护索引结构是很昂贵的,它消耗像磁盘空间,cpu io能力等资源。设计者必须确保索引带来的好处能超过索引维护带来的负面影响。
使用简单的估计方法来获得索引维护的消耗:每个索引通过insert delete或者update操作维护,在实际的dml语句中需要三倍于同样的资源。就意味着,当你插入一行数据到有三个索引的表中,会将近比插入数据到没有索引的表中慢10倍。对于dml,尤其是insert比例较大的应用,索引的设计应该被认真的进行检阅,可能需要对需求和插入的性能做一个比较。
2.5.3.4 序列化索引
序列,时间戳的使用,生成了可以指向热点问题的关键字,能够影响反应时间和吞吐量。这常常由于单调增长的键导致了右边增长的索引,为了避免这个问题,尽量使生成插入到整个索引范围中。这个结果在平衡的索引中更加有扩展性和对空间的有效性。可以通过反向索引或者用一个循环的序列去解决序列值的问题。
2.5.3.5 调整索引中的列
设计者必须灵活的设计关于索引的规则。依赖于实际情况,使用如下两种方法去对索引中的关键字排序:
--选择性最高的列优先,这种方法最经常用,因为它提供了以最小的io进行最快的访问去得到实际需要的列。这个技术主要用于高选择性的范围扫描的主键。
--调整通过集群或者排序数据降低id的列,选择数据最少的列可以减少io,或者按照数据应该被提取的顺序对数据进行排序。
2.5.4 使用视图
视图能够加速和简化应用的设计。一个简单的视图定义能够封装数据模型的复杂性,通过这个视图的程序我们可以提取,显示,收集和存储数据。
但是,由于视图提供了清楚的程序接口,会导致不理想的资源密集问题。最坏的视图类型是当视图涉及到其它的视图,并且产生了视图的链接。在一些类中,开发者能够直接通过表而不是视图来解决这个问题。经常由于他们内在的特点,视图使优化器很难生成最优的执行计划。
2.5.5 sql执行效率
在任系统的结构设计中,必须小心确保应用的开发者理解sql的执行效率。为了这个目的,开发环境必须支持以下特点:
--好的数据库连接管理
链接数据库是昂贵的,因为它是高度不可扩展的操作。因此,数据库的在线链接数量应该尽量最小化。一个简单的系统,在单一用户链接应用的初始状态是完美的。但是在一个基于web或者多应用的系统中,应用服务器对于用户的链接是多元的,这就比较困难了。根据这种类型的应用,设计效果应该确保数据库的连接是合并的并且不会因为每个用户请求被重建。
--好的游标使用和管理
维护用户的链接和最小化系统的解析是同等重要的。解析是解释执行sql语句和创建执行计划的过程,这个过程有很多解析,包括语法检查,安全检查,执行计划生成和从shared pool中申请共享存储。有两种类型的解析操作。
----硬解析
sql语句第一次提交,在sharedpool中没能匹配,硬解析最小号资源并且不可扩展,因为他们执行解析中的每个步骤。
----软解析
第一次提交的时候,在shared pool里面找到与之匹配的执行计划。也可以匹配别的用户之前的执行计划,sql语句实现了共享,这可以提高性能。但是,软解析并不理想,因为仍然需要语法和安全检查,这也会消耗系统资源。
因为解析应该尽可能的最小化,应用开发者应该设计应用的时候使sql语句一旦解析就执行很多次。这是通过游标实现的。有经验的sql程序员应该熟悉打开和再次执行游标的概念。
应用开发者一定要确保sql语句在shared pool里面是共享的,绑定变量可以代表需求的部分在每次执行的时候有所不同。如果没有这么做,sql就会被解析一次并且再也不会被其它用户使用。为了保证sql共享,使用绑定变量不是用sql的字面值,例如
使用字面值:
SELECT * FROM employees
WHERE last_name LIKE 'KING';
使用绑定变量
SELECT * FROM employees
WHERE last_name LIKE :1;
下例显示了再一个简单的oltp系统上的测试结果:
Test #Users Supported
No Parsing all statements 270
Soft Parsing all statements 150
Hard Parsing all statements 60
Re-Connecting for each Transaction 30
这个测试是在一个4个cpu的机器上执行的。差异随着系统上cpu的个数不断增加。
2.5.6 执行应用
开发环境和编程语言的选择增大了技巧在开发团队和结构决策的可用性。一些简单的性能管理规则可以引导可扩展,高性能的应用。
1 选择适合于软件组建的开发环境,不要使它限制你的系能巨额东的设计,如果限制了,那就说明你选错了语言和开发环境。
--用户接口
程序模型在HTML生成器和直接调用窗口系统是不一样的。开发方法应该集中于用户接口代码的响应时间。如果HTML活着java在网络上被传输,那么尽量减小网络容量和交互。
--业务逻辑
解释性语言,例如java或者plsql,对于业务逻辑是理想的代码。他们很轻便,使得更新相关逻辑变得很简单。两种语言的语法都很丰富,代码的易读性和解释性也很好。如果业务逻辑需要复杂的数学方程,那么就会需要收集二进制语言。业务逻辑代码可以在客户机器上,应用服务器上,以及数据库服务器上。但是应用服务器是业务逻辑最普遍的地方。
--用户需求和资源分配
这个部分不会被程序怨言所影响,但是工具和第四代语言封装了数据库连接和游标管理,可能会使用无效率的机制。当衡量这些工具和环境的时候,检查他们的数据库连接模型和他们使用的游标和绑定变量
--数据管理和事务
大部分是不受程序语言的影响的。
2 当实施一个软件组件,实施它的功能和与其他组件的非功能性联系。在不理想的设计和实施中执行另外一个组件的功能性结果。应用是对于所有的组件的。
3 不要在功能或者软件组建的研究,设计,实施,测试中留下缺陷。大多数情况下,直到应用被展开或者是在真实环境下测试才会发现缺陷。这是体系结构失败的一个信号。数据的存档、清除模型在初始化系统设计,创建和实施中总是被频繁忽略。
4 当实施程序逻辑,实施程序语言,比如c,java或者plsql,当实施数据访问或者数据改变的时候,使用sql。这个规则对于业务逻辑模型的代码是显而易见的,程序代码或混淆数据访问代码。将程序逻辑放在sql中式极大的诱惑。这导致了坏的sql资源密集。使用decode 的sql语句总是被优化的对象,就像有很多or程序的或者集合处理的,例如union或者minus。
5 缓存频繁访问,很少改变的数据在提取上是很昂贵的,但是缓存的机制很方便的使用和保证它确实比在原始方法中访问数据要容易。把数据在本地缓存起来,这对于所有的模型是相当合适的,我们不需要重复的从远程数据存储提取数据。
本地缓存包括以下的例子:
--缓存今天的日期占数据库负载的60%以上
--当前用户名
--重复应用的变量和常量 比如税率 折扣率 或者本地信息
--局部缓存数据能够更延伸到创建一个本地数据缓存到中间件。帮助降低重心数据库的负载。然而,必须注意构造局部缓存后,他们的复杂性,抵消掉了性能上的收益。
--局部序列
这个设计暗含应该考虑的缓存。例如,如果用户链接到中间件上并且日期被缓存,那么用户的日期值就无意义了。
6 优化组建之间的几口,确保所有的组件使用最有扩展性的配置。这个规则需要最小的解释和应用到所有的模型和接口上。
7 在应用上使用外键约束,强制相关完整性是昂贵的。你可以通过选择该列确保它是存在的。外键约束的实施被oracle提供。但是并没有使用sql,所以是快速的很容易声明并且不产生网络通信。
8 考虑在应用中使用端对端的应用追踪设置行动和模型名字。这允许在追踪网络负载问题的时候有的灵活性。
2.5.7 应用开发的趋势
在今天的应用开发中有两个大的挑战。使用java渐渐取代了c和c++,并且使用了面向对象的技术,影响了模式的设计。
java提供了更轻便的代码和程序的可用性。但是有很多的性能潜在问题伴随着java。因为java是解释性语言。在执行和编译小的逻辑的时候比c慢。结果,客户端使用的资源增加了。这需要更多的cpu去应用客户端和中间件机器和更多的程序员精力去产生有效的代码。
因为java是一个面向对象的语言,它鼓励数据的访问在类中解决而不是业务逻辑。结果程序员可能调用已经使用过没有性能的数据访问方法。这导致了数据库访问的结果很少的情况下使用了最迟钝的接口。
根据软件设计的类型,需求并不总是包括where来使预言变得更有效。行的过滤在java程序中被处理。这是很没有效率的。总的说,对于DML操作,尤其是insert 单挑的insert操作,使得数据接口不可能被使用。另外一些情况,这使得程序的调用更加无效。将数据从数据库移动花费的资源比实际的数据库调用的资源更多。
总的来说,最好将数据访问调用放在业务逻辑下面去获得最好的总体事务设计。
在程序层面的面向对象的接受导致了面向对象的数据库在数据库服务器内部的产生。已经在很多方面得到了证实,存储对象结构包括BLOB 并且仅仅拥有数据库有效性作为一个索引卡片文件去使用数据库对象的相关特征。
如果你适应了面向对象的方法去做模式设计,那么要确保你没有失去相关存储模型的灵活性,在一些案例中,对于模式设计的面向对象的方法止于一个很重的非正常的数据结构。一些设计经常展现了从后台到网络的分等级的数据库,这些设计已经被相关的存储方法取代。
总的来说如果你正在存储你的数据到数据库中,那么从长期的和期望一定程度的临时应用在同样的模式上,你会找到性能最好最灵活的存储方法。
来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/24799772/viewspace-677712/,如需转载,请注明出处,否则将追究法律责任。
转载于:http://blog.itpub.net/24799772/viewspace-677712/