按键盘上方向键 ← 或 → 可快速上下翻页,按键盘上的 Enter 键可回到本书目录页,按键盘上方向键 ↑ 可回到本页顶部!
————未阅读完?加入书签已便下次继续阅读!
据库设计方面的知识,也贡献了持续的热情来修改我冗长的句子、调整副词位置、斟酌替换词
汇。Peter Robson和我在好几个大会上都碰过面,我们都是演讲者。
Jonathan Gennick担任本书编辑,这有点让人受宠若惊,Jonathan Gennick是O'Reilly出版的
SQL Pocket Guide等畅销名著的作者。Jonathan是个非常尊重作者的编辑。由于他的专业、他
对细节的关注、他的犀利视角,使本书的质量大大提升。同时,Jonathan也使本书的语言更具“中
大西洋”风味(Peter和我发现,虽然我们保证按美国英语拼写,但还远远不够)。
…………………………………………………………Page 5……………………………………………………………
我还要感谢很多人,他们来自三个不同的大陆,阅读了本书全部或部分草稿并坦诚地提出意见。
他们是:Philippe Bertolino、Rachel Carmichael、Sunil CS、LarryElkins、Tim Gorman、Jean
Paul Martin、Sanjay Mishra、Anthony Molinaro、Tiong Soo Hua。我特别感激Larry,因为本
书的思想最初来自于我们的E…mail讨论。
我也要感谢O'Reilly的许多人,他们使本书得以出版。他们是:Marcia Friedman、Rob Romano、
Jamie Peppard、Mike Kohnke、Ron Bilodeau、Jessamyn Read、Andrew Savikas。感谢Nancy
Reinhardt卓越的手稿编辑工作。
特别感谢Yann…Arzel Durelle…Marc慷慨提供第12章用到的图片。感谢Paul McWhorter授权我们
将他的战争图用于第6章。
最后,感谢Roger Manser和Steel Business Briefing的职员,他们为Peter和我提供了位于伦敦
的办公室(还有大量咖啡)。感谢Qian Lena (Ashley)提供了本书开始引用的《孙子兵法》的中
文原文。
作者介绍
Stéphane Faroult从1983年开始接触关系数据库。Oracle法国成立早期他即加入(此前是短暂的
IBM经历和渥太华大学任教生涯),并在不久之后对性能和调优产生了兴趣。1988年他离开了
Oracle,此后一年间,他进行调整,并研究过运筹学。之后,他重操旧业,一直从事数据库咨
询工作,并于1998年创办了RoughSea公司(http:// roughsea。)。
Stéphane Faroult出版了FortranStructuréet Méthodes Numériques一书(法语,Dunod出版社,1986;
与Didier Simon合作),并在Oracle Scene和Select(分别为英国和北美Oracle用户组杂志)以及
Oracle杂志在线版上发表了许多文章。他还是美国、英国、挪威等众多用户组大会的演讲者。
PeterRobson毕业于达拉谟大学地质专业(1968年),然后在爱丁堡大学任教,并于1975年获得
地质学研究型硕士学位。在希腊度过了一段地质学家生涯之后,他开始在纽卡斯尔大学专攻地
质和医学数据库。
他使用数据库始于1977年,1981年开始使用关系数据库,1985年开始使用Oracle,这期间担任
过开发工程师、数据架构师、数据库管理员等角色。1980年,Peter参加了英国地质普查,负责
指导使用关系数据库管理系统。他擅长SQL系统,以及从组织级到部门级的数据建模。Peter多
次出席英国、欧洲、北美的Oracle数据库大会,在许多数据库专业杂志上发表过文章。他现任
英国Oracle用户组委员会主任,可通过peter。robson@justsql。联系他。
查询的识别
…………………………………………………………Page 6……………………………………………………………
有经验的朋友都知道,把关键系统从开发环境切换到生产环境是一场战役,一场甚嚣尘上的战
役。通常,在“攻击发起日(D…Day)”的前几周,性能测试会显示新系统达不到预期要求。于是,
找专家,调优SQL语句,召集数据库管理员和系统管理员不断开会讨论对策。最后,性能总算
与以前的系统大致相当了(尽管新系统用的是价格翻倍的硬件)。
人们常常使用战术,而忽略了战略。战略要求从大局上把握整个架构与设计。和战争一样,战
略的基本原则并不多,且经常被忽视。架构错误的代价非常高,SQL 程序员必须准备充分,明
确目标,了解如何实现目标。在本章中,我们讨论编写高效访问数据库的程序需要实现哪些关
键目标。
查询的识别
Query Identification
QQuueerryy IIddeennttiiffiiccaattiioonn
数个世纪以来,将军通过辨别军装颜色和旗帜等来判断各部队的位置,以此检查激战中部队行
进情况。同样,当一些进程消耗了过多的 CPU 资源时,通常也可以确定是由哪些正被执行的
SQL 语句造成的。但是,要确定是应用的哪部分提交了这些SQL语句却困难得多,特别是复杂
的大型系统包含动态建立的查询的时候。尽管许多产品提供良好的监控工具,但要确定一小段
SQL语句与整个系统的关系,有时却非常困难。因此,要养成为程序和关键模块加注释的习惯,
在SQL中插入注释有助于辨别查询在程序中的位置。例如:
/* CUSTOMER REGISTRATION */ select blah 。。。
这些注释在查错时非常有用。另外,注释也有助于判断单独应用对服务器造成的负载有多大;
例如我们希望本地应用承担更多工作,需要判断当前硬件是否能承受突发高负载,这时注释特
别有用。
有些产品还提供了专门的记录功能(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内部使用,但你不能使用),那么明智的做法是检查它的默认大小并根据具体