虎虎漫画小说

繁体版 简体版
虎虎漫画小说 > > SQL语言艺术最新章节 > 第 2 章

第 2 章 免费阅读

用关系数据库管理系统。他擅长SQL系统,以及从组织级到部门级的数据建模。Peter多

次出席英国、欧洲、北美的Oracle数据库大会,在许多数据库专业杂志上发表过文章。他现任

英国Oracle用户组委员会主任,可通过peter.robson@justsql.com联系他。

查询的识别

有经验的朋友都知道,把关键系统从开发环境切换到生产环境是一场战役,一场甚嚣尘上的战

役。通常,在“攻击发起日(D-Day)”的前几周,xìng能测试会显示新系统达不到预期要求。于是,

找专家,调优SQL语句,召集数据库管理员和系统管理员不断开会讨论对策。最后,xìng能总算

与以前的系统大致相当了(尽管新系统用的是价格翻倍的硬件)。

人们常常使用战术,而忽略了战略。战略要求从大局上把握整个架构与设计。和战争一样,战

略的基本原则并不多,且经常被忽视。架构错误的代价非常高,SQL 程序员必须准备充分,明

确目标,了解如何实现目标。在本章中,我们讨论编写高效访问数据库的程序需要实现哪些关

键目标。

查询的识别

Query

Identification

数个世纪以来,将军通过辨别军装颜色和旗帜等来判断各部队的位置,以此检查激战中部队行

进情况。同样,当一些进程消耗了过多的CPU 资源时,通常也可以确定是由哪些正被执行的

SQL 语句造成的。但是,要确定是应用的哪部分提jiāo了这些SQL语句却困难得多,特别是复杂

的大型系统包含动态建立的查询的时候。尽管许多产品提供良好的监控工具,但要确定一小段

SQL语句与整个系统的关系,有时却非常困难。因此,要养成为程序和关键模块加注释的习惯,

在SQL中chā入注释有助于辨别查询在程序中的位置。例如:

/* CUSTOMER REGISTRATION */ select blah ...

这些注释在查错时非常有用。另外,注释也有助于判断单独应用对服务器造成的负载有多大;

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

别有用。

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

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

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

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

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

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

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

保持数据库连接稳定

Stable

Database

Connections

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

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

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

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

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

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

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

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

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

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

统xìng能下降问题。表2-1列出了模拟的结果。

注意

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

术会更快。

表2-1:连接/中断xìng能测试结果

Open the file

Until the end of file is reached

Read a row

Connect to the server specified by the row

Insert the data

Disconnect

Close the file

测试结果

依次对每一行作连接/中断7.4 行/秒

连接一次,所有行逐个chā入1 681 行/秒

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

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

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

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

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

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

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

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

核心间的jiāo互次数,从而使xìng能产生了另一次飞跃。这种每次chā入几行数据的做法,可以使数

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

为何有如此大的xìng能提升?

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

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

客户端与远程服务器的jiān tīng程序(listener program)建立联系;接着,jiān tīng程序要么创建一个

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

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

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

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

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

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

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

xìng能才如此重要。

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

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

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

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

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

『加入书签,方便阅读』