首页 新闻 论坛 群组 Blog 文档 下载 读书 Tag 网摘 搜索 开源 FAQ 第二书店 博文视点 程序员
频道: 研发 数据库 中间件 信息化 视频 .NET Java 游戏 移动 服务: 人才 外包 培训
    图书品种:235680
       
热门搜索: ASP.NET Ajax Spring Hibernate Java

保持数据库连接稳定

Stable Database Connections

建立一个新的数据库连接,既快又方便,但这其中往往掩藏着重复建立数据库连接带来的巨大开销。所以,管理数据库连接必须非常小心。允许多重连接——可能就藏在你的应用中——的后果可能很严重,下面即是一例。

不久前,我遇到一个应用,要处理很多小的文本文件。这些文本文件最大的也不超过一百行,每一行包含要加载的数据及数据库等信息。此例中固然只有一个数据库实例,但即使有上百个,这里所说明的原理也是适用的。

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

    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

上述处理工作令人满意,但当大量小文件都在极短的时间内到达时,可能应用程序来不及处理,于是积压大量待处理文件,花费时间相当可观。

我用 C 语言编了个简单的程序来模拟上述情况,以说明频繁的数据库连接和中断所造成的系统性能下降问题。表 2-1列出了模拟的结果。

注意

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

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

测  试

结  果

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

7.4 行/秒

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

1 681 行/秒

连接一次,以 10 行为一数组插入

5 914 行/秒

连接一次,以 100 行为一数组插入

9 190 行/秒

此例说明了尽量减少分别连接数据库次数的重要性。对比表中前后两次针对相同数据库的插入操作,明显发现性能有显著提升。其实还可以做进一步的优化。因为数据库实例的数量势必有限,所以可以建立一组处理程序(handler)分别负责一个数据库连接,每个数据库只连接一次,使性能进一步提高。正如表 2-1 所示,仅连接数据库一次(或很少次)的简单技巧,再加上一点额外工作,就能让效率提升200倍以上。

当然,在上述改进的基础上,再将欲更新的数据填入数组,这样就尽可能减少了程序和数据库核心间的交互次数,从而使性能产生了另一次飞跃。这种每次插入几行数据的做法,可以使数据的总处理能力又增加了5倍。表 2-1 中的结果显示改进后的性能几乎是最初的 1 200 倍。

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

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

在常见的客户/服务器模式中(现在仍广为使用),简单的连接操作背后潜藏着如下事实:首先,客户端与远程服务器的监听程序(listener program)建立联系;接着,监听程序要么创建一个进程或线程来执行数据库核心程序,要么直接或间接地把客户请求传递给已存在的服务器进程,这取决于此服务器是否为共享服务器。

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

次session建立新环境,以跟踪它的行为。建立新session前,DBMS还要检查密码是否与保存的加密的账户密码相符。或许,DBMS还要执行登录触发器(logon trigger),还要初始化存储过程和程序包(如果它们是第一次被调用)。上面这些还不包括客户端进程和服务器进程之间要完成的握手协议。正因为如此,连接池(connection pooling)等保持永久数据库连接的技术对性能才如此重要。

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

即使数据库连结已经建立且仍未中断,程序和 DBMS 核心之间的上下文切换(context switch)也有代价。因此,如果 DBMS 支持数据通过数组传递,应毫不犹豫地使用它。如果该数组接口是隐式的(API内部使用,但你不能使用),那么明智的做法是检查它的默认大小并根据具体需要修改它。当然,任何逐行处理的方式都面临上下文切换的问题,并对性能产生严重影响——本章后面还会多次涉及此问题。

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

查看所有评论(0)条】

最近评论



正在载入评论列表...
热点评论