友情提示:如果本网页打开太慢或显示不完整,请尝试鼠标右键“刷新”本网页!阅读过程发现任何错误请告诉我们,谢谢!! 报告错误
狗狗书籍 返回本书目录 我的书架 我的书签 TXT全本下载 进入书吧 加入书签

SQL语言艺术(PDF格式)-第3章

按键盘上方向键 ← 或 → 可快速上下翻页,按键盘上的 Enter 键可回到本书目录页,按键盘上方向键 ↑ 可回到本页顶部!
————未阅读完?加入书签已便下次继续阅读!




例如我们希望本地应用承担更多工作,需要判断当前硬件是否能承受突发高负载,这时注释特 

别有用。 



有些产品还提供了专门的记录功能(registration facilities),将你从“为每个语句加注释”的乏味 

工作中解放出来。例如Oracle 的dbms_application_info包,它支持48个字 



符的模块名称(module name)、32 个字符的动作名称(action name)和64个 字符的客户信 

息,这些字段的内容可由我们定制。在 Oracle 环境下,你可以利用这个程序包记录哪个应用 

正在执行,以及它在何时正在做什么。因为应用是通过“Oracle V 动态视图”(能显示目前内存 

中发生的情况)向程序包传递信息的,于是我们可以轻易地掌握这些信息。 



总结:易识别的语句有助于定位性能问题。 



保持数据库连接稳定 



Stable Database Connections 

SSttaabbllee DDaattaabbaassee CCoonnnneeccttiioonnss 



建立一个新的数据库连接,既快又方便,但这其中往往掩藏着重复建立数据库连接带来的巨大 

开销。所以,管理数据库连接必须非常小心。允许多重连接——可能就藏在你的应用中——的 

后果可能很严重,下面即是一例。 


…………………………………………………………Page 7……………………………………………………………

不久前,我遇到一个应用,要处理很多小的文本文件。这些文本文件最大的也不超过一百行, 

每一行包含要加载的数据及数据库等信息。此例中固然只有一个数据库实例,但即使有上百个, 

这里所说明的原理也是适用的。 

处理每个文件的代码如下: 

      Open the file 

     Until the end of fileisreached 

     Readarow 

     Connect tothe server specified bythe row 

     Insert the data 

     Disconnect 

     Close the file 



上述处理工作令人满意,但当大量小文件都在极短的时间内到达时,可能应用程序来不及处理, 

于是积压大量待处理文件,花费时间相当可观。 



我用 C 语言编了个简单的程序来模拟上述情况,以说明频繁的数据库连接和中断所造成的系 

统性能下降问题。表 2…1列出了模拟的结果。 



注意 

产生表 2…1结果的程序使用了常规的insert语句。顺便提一下,直接加载(direct…loading)的技 

术会更快。 



表2…1:连接/中断性能测试结果 



 测 试                                       结 果 



 依次对每一行作连接/中断                              7。4 行/秒 



 连接一次,所有行逐个插入 

                                           1 681 行/秒 



 连接一次,以 10 行为一数组插入                         5 914 行/秒 



 连接一次,以 100 行为一数组插入                        9 190 行/秒 


…………………………………………………………Page 8……………………………………………………………

此例说明了尽量减少分别连接数据库次数的重要性。对比表中前后两次针对相同数据库的插入 

操作,明显发现性能有显著提升。其实还可以做进一步的优化。因为数据库实例的数量势必有 

限,所以可以建立一组处理程序(handler)分别负责一个数据库连接,每个数据库只连接一次, 

使性能进一步提高。正如表 2…1 所示,仅连接数据库一次(或很少次)的简单技巧,再加上一 

点额外工作,就能让效率提升200倍以上。 



当然,在上述改进的基础上,再将欲更新的数据填入数组,这样就尽可能减少了程序和数据库 

核心间的交互次数,从而使性能产生了另一次飞跃。这种每次插入几行数据的做法,可以使数 

据的总处理能力又增加了5倍。表 2…1 中的结果显示改进后的性能几乎是最初的 1 200 倍。 



为何有如此大的性能提升? 



第一个原因,也是最大的原因,在于数据库连接是很“重”的操作,消耗资源很多。 



在常见的客户/服务器模式中(现在仍广为使用),简单的连接操作背后潜藏着如下事实:首先, 

客户端与远程服务器的监听程序(listener program)建立联系;接着,监听程序要么创建一个 

进程或线程来执行数据库核心程序,要么直接或间接地把客户请求传递给已存在的服务器进程, 

这取决于此服务器是否为共享服务器。 



除了这些系统操作(创建进程或线程并开始执行)之外,数据库系统还必须为每 



次session建立新环境,以跟踪它的行为。建立新session前,DBMS还要检查密码是否与保存 

的加密的账户密码相符。或许,DBMS还要执行登录触发器(logon trigger),还要初始化存储 

过程和程序包(如果它们是第一次被调用)。上面这些还不包括客户端进程和服务器进程之间要 

完成的握手协议。正因为如此,连接池(connection pooling)等保持永久数据库连接的技术对 

性能才如此重要。 



第二个原因,你的程序(甚至包括存储过程)和数据库之间的交互也有开销。 



即使数据库连结已经建立且仍未中断,程序和 DBMS 核心之间的上下文切换(context switch) 

也有代价。因此,如果 DBMS 支持数据通过数组传递,应毫不犹豫地使用它。如果该数组接 

口是隐式的(API内部使用,但你不能使用),那么明智的做法是检查它的默认大小并根据具体 

需要修改它。当然,任何逐行处理的方式都面临上下文切换的问题,并对性能产生严重影响— 

—本章后面还会多次涉及此问题。 



总结:数据库连接和交互好似万里长城——长度越长,传递消息越耗时。 



战略优先于战术 



Strategy Before Tactics 

SSttrraatteeggyy BBeeffoorree TTaaccttiiccss 



战略决定战术,反之则谬也。思考如何处理数据时,有经验的开发者不会着眼于细微步骤,而 

是着眼于最终结果。要获得想要的结果,最显而易见的方法是按照业务规则规定的顺序按部就 

班地处理,但这不是最有效的方法——接下来的例子将显示,刻意关注业务处理流程可能会使 


…………………………………………………………Page 9……………………………………………………………

我们错失最有效的解决方案。 



几年前,有人给了我一个存储过程,让我“尝试”着进行一下优化。为什么说是“尝试”呢?因为 

该存储过程已经被优化两次了,一次是由原开发者,另一次是由一个自称Oracle 专家的人。但 

尽管如此,这个存储过程的执行仍会花上20分钟,使用者无法接受。 



此存储过程的目的,是根据现有库存和各地订单,计算出总厂需要订购的原料数量。大体上, 

它就是把不同数据源的几个相同的表聚合(aggregate)到一个主表(master table)中。首先, 

将每个数据源的数据插入主表;接着,对主表中的各项数据进行合计并更新;最后,将与合计 

结果无关的数据从表中删除。针对每个数据源,重复执行上述步骤。所有 SQL 语句都不是特 

别复杂,也没有哪个单独的SQL语句特别低效。 



为了理解这个存储过程,我花了大半天时间,终于发现了问题:为什么该过程要用这么多步骤 

呢?在from子句中加上包含 union 的子查询,就能得到所有数据源的聚合(aggregation)。一条 

select 语句,只需一步就得到了结果集,而之前要通过插入目标表(target table)得到结果集。 

优化后,性能的提升非常惊人——从 20 分钟减至 20 秒;当然,之后我花了一些时间验证了 

结果集,与未优化前完全相同。 



想要获得上述的大幅提高性能,无需特别技能,仅要求站在局外思考(think outside thebox)的 

能力。之前两次优化因“太关注问题本身”而收到了干扰。我们需要大胆的思维,站得远一些, 

试着从大局的角度看待问题。要问自己一些关键的问题:写存储过程之前,我们已有哪些数据? 

我们希望存储过程返回什么结果?再辅以大�
返回目录 上一页 下一页 回到顶部 赞(1) 踩(1)
未阅读完?加入书签已便下次继续阅读!
温馨提示: 温看小说的同时发表评论,说出自己的看法和其它小伙伴们分享也不错哦!发表书评还可以获得积分和经验奖励,认真写原创书评 被采纳为精评可以获得大量金币、积分和经验奖励哦!