Java 访问数据库的速度瓶颈问题的分析及解决(1)

发表于:2007-07-14来源:作者:点击数: 标签:
Java 访问 数据库 的速度瓶颈问题的分析及解决(1) · 速度瓶颈问题的提出 在企业级的Java应用中,访问数据库是一个必备的环节。数据库作为数据资源的集散地,往往位于企业级软件体系的后方,供前方的应用程序访问。在Java技术的体系中,应用程序是通过JDBC
Java 访问数据库的速度瓶颈问题的分析及解决(1)

· 速度瓶颈问题的提出

  在企业级的Java应用中,访问数据库是一个必备的环节。数据库作为数据资源的集散地,往往位于企业级软件体系的后方,供前方的应用程序访问。在Java技术的体系中,应用程序是通过JDBC(Java Database Connectivity)接口来访问数据库的,JDBC支持"建立连接、SQL语句查询、处理结果"等基本功能。在应用JDBC接口访问数据库的过程中,只要根据规范来操作,这些功能的实现不会出差错。但是,有些时候进行数据查询的效率着实让开发人员懊恼不已,明明根据规范编写的程序,却得不到预期的运行效果,造成了整个软件的执行效率不高。

  起初,我们把问题归结于Java字节码加载和执行速度的缓慢,紧接着硬件的功能普遍得到了增强,证明这样的想法些许是错误的,还没有抓到真正的根本原因。本文将逐步解剖JDBC访问数据库的机制,深层分析造成这种速度瓶颈问题的原因,并提出在现有的Java技术框架下解决这个速度瓶颈问题的思路和方法。

· JDBC访问数据库的机制


图1


图2

  图1和图2描述了Java应用程序通过JDBC接口访问数据库的4种驱动模式,也就是底层实现JDBC接口的模式。对于这些模式,我们逐一介绍:

  模式4:图1左边的分支称为模式4,它一般是数据库厂商才能实现的纯Java的基于本地协议的驱动,直接调用DBMS(数据库管理系统)使用的网络协议,对于企业内部互联网来说,是一个实用的解决方案

  模式3:图1右边的分支称为模式3,它同样是一个纯Java驱动,不同于模式4的是基于网络协议。它的机制是将JDBC调用转换为中间网络协议,然后转换为DBMS协议。中间网络协议层起到一个读取数据库的中间件的作用,能够连接许多类型的数据库,因而是最灵活的JDBC模式。这种模式的产品比较适用于企业内部互联网,如若支持国际互联网,还需添加对安全、穿过防火墙访问等的支持。

  模式1:图2左边的分支称为模式1,即通常由Sun公司提供的JDBC-ODBC桥接器。它提供了经由一种或多种ODBC驱动进行访问的JDBC接口,而ODBC驱动,在很多情况下也即数据库的客户端,必须加载到客户机。因而,它适用于下载和自动安装Java程序不重要、实验用途或者没有其它JDBC驱动可用的情况下。

  模式2:图2右边的分支成为模式2,类似于JDBC-ODBC桥接器,需要加载到客户机,却是一个部分用Java实现的驱动接口。它将JDBC调用转换为对数据库(Oracle、Sybase、Informix、DB2等)客户端接口的调用。

不同模式的JDBC接口的选择

  以上阐述的JDBC接口的模式不同,让我们可以把JDBC接口按照实现的模式分为四类。有些同仁可能有这样的体会,选择不同的JDBC接口会有不同的访问速度,为何会出现这样的情况?这个问题的答案是,不同的应用需要不同模式的JDBC接口,因而我们在面对一个应用时,要慎重选择JDBC接口。

  通常的DBMS都支持微软提出的ODBC规范,因而模式1可当作您在设计和实现软件时的选择,它易于配置的特性能够让你把选择JDBC等烦恼的问题暂且抛在一边,让自己的Java程序能够及早地正常工作起来。

  一般说来,商业DBMS的提供者往往会为自己的数据库提供一个JDBC接口,应用的是模式4。这种模式的优势在于和数据库本身结合比较紧密,而且是纯Java的实现,在企业级的软件应用中,应该是首选。例如,对于Oracle数据库来说,有Oracle、SilverStream、DataDirect等公司提供这种类型的驱动,其性能往往被评价为最高效的、最可靠的驱动程序。但偶尔也有比较麻烦的情况,例如微软就不会提供MS SQL的JDBC接口,这时就需要到Sun的网站( http://industry.java.sun.com/products/jdbc/drivers )查找相关的模式4驱动,上面提到的DataDirect公司( http://www.datadirect-technologies.com/jdbc/jdbc.asp )就提供了支持MS SQL的模式4驱动,只是你需要支付750$购买这个JDBC驱动。

  同样是纯Java实现的模式3,与模式4相比,优势在于对多种数据库的支持,体现了其灵活性。在大型的企业级的软件应用中,后台数据库往往不是一个,而且是由不同的厂商支持的。不过,模式3的JDBC驱动往往提供许多企业级的特征,例如SSL安全、支持分布式事务处理和集中管理等,因而会对你特殊的用途有很大的帮助。是否选用,还在于你对扩展应用是否有需求以及对多DBMS的支持。

  谈到这儿,我对模式3和模式4作一个总结:两者都是纯Java实现的驱动,因而不需要数据库厂商提供附加的软件,就可以运行在任何标准的Java平台,性能上比较高效、可靠。

  了解上述3种JDBC的实现模式之后,模式2就更容易阐释了,你可以理解它为前三者利弊平衡的妥协产物:

  1. 借鉴模式1利用客户机本地代码库,加速数据访问的执行,但却摒除ODBC标准,而是支持厂商自己指定的性能扩展
   2. 借鉴模式3利用多层结构,上层用Java实现,利于跨平台应用和支持多数据库,但下层却改为本地代码,加速执行速度
   3. 借鉴模式4和数据库结合紧密的优点,部分用Java实现,更是对数据库性能有很大的扩展

  这种开放和高性能的特征得到了业界的肯定,因而被主要的数据库厂商强烈推荐。尽管它需要你下载本地代码库到客户机,但相对于你访问数据库速度的提高,这些应该只是举手之劳了。下面对4种实现JDBC的模式选择,归纳一下选择的顺序(当然是指你有选择余地的时候,不存在的话向后推延):

编号 选择过程分析 选择顺序
1 实验性环境下,尽可能选择易于配置的驱动,利于Java程序的开发,后期可在对应用环境进行判断后,再对JDBC模式进行选择 1>2>3>4
2 小型企业级环境下,不需要对多数据库的支持,因而模式2和3的有些优点并不能体现出来,强烈推荐你选择模式4的JDBC驱动 4>2=3>1
3 大型企业级环境下,需要对多数据库的支持,模式2和3各有千秋,但是更多情况下是你会选择速度较快的模式2 2>3>4>1

  对于不同厂商提供的但应用相同模式的JDBC接口,理论上比较不出效率的高低,你只有通过一定的工具,例如Benchmark等,对它们进行比较才能更有利于你的选择。因为暂时不存在第三方提供的数据比较结果,所以这些问题需要你对上述内容有了透彻理解之后自行解决。

· Java程序中SQL语句格式的优化

  这个时候,你也许还在为找不到合适的JDBC驱动而一筹莫展,也许为自己在凌晨3点下载的JDBC驱动通过了测试而欣喜若狂,但是并不说明你对程序的优化工作已经无关紧要了。切记,对整个软件系统的优化,包括每个环节的优化,要不有可能你会前功尽弃。我在这儿不和大家讨论Java程序的算法,而是简单阐述一下选择SQL语句格式的必要和如何选择对自己有利的SQL语句格式。看下面两段程序片断:

  Code Fragment 1:

  String updateString = "UPDATE COFFEES SET SALES = 75 " + "WHERE COF_NAME LIKE 'Colombian'";
   stmt.executeUpdate(updateString);

  Code Fragment 2:

  PreparedStatement updateSales = con.prepareStatement("UPDATE COFFEES SET SALES = ? WHERE COF_NAME LIKE ? ");
   updateSales.setInt(1, 75);
   updateSales.setString(2, "Colombian");
   updateSales.executeUpdate();

  片断2和片断1的区别在于,后者使用了PreparedStatement对象,而前者是普通的Statement对象。PreparedStatement对象不仅包含了SQL语句,而且大多数情况下这个语句已经被预编译过,因而当其执行时,只需DBMS运行SQL语句,而不必先编译。当你需要执行Statement对象多次的时候,用PreparedStatement对象将会大大降低运行时间,当然也加快了访问数据库的速度。

  这种转换也给你带来很大的便利,不必重复SQL语句的句法,而只需更改其中变量的值,便可重新执行SQL语句。选择PreparedStatement对象与否,在于相同句法的SQL语句是否执行了多次,而且两次之间的差别仅仅是变量的不同。如果仅仅执行了一次的话,它应该和普通的Statement对象毫无差异,体现不出它预编译的优越性。

软件模型中对数据库访问的设计模式的优化

  在我阅读J2EE蓝图和JDO草案的过程中,我发现了访问模式对数据库访问的影响,因而想在本文中阐述如何针对自己的软件需求选择合适的软件模式。

  J2EE蓝图的设计者在Java Pet Store示例应用中使用了MVC(Model-View-Controller)体系,给许多J2EE设计模式提供了背景。我要谈及的三种设计模式是:Data Aclearcase/" target="_blank" >ccess Object、Fast Lane Reader、Page-by-Page Iterator,它们为加快数据存取速度提供了一些可以在系统设计阶段值得我们借鉴的想法。

  Data Access Object

  将商业逻辑从数据存取逻辑中分离出来,把存取的资源改编,从而使资源可以容易和独立地转变。

  依赖于底层数据资源的特殊要素(例如数据库的供应商)的商业组件,常将商业逻辑和数据存取逻辑配合起来,只能使用特殊类型的资源,而使用不同类型的资源时,复用将会非常困难,因此,只能服务于有限的市场领域。DAO(Data Access Object)即是将数据存取逻辑从EJB中抽去出来抽象为一个独立的接口,EJB根据接口的操作执行商业逻辑,而接口针对使用的数据资源实现为DAO对象。

  在Java Pet Shop这个例子中,OrderEJB组件通过关联的OrderDAO类访问数据库,自身则关注于商业逻辑的实现。在调度阶段,将配置某一类(OrderDAOCS、OrderDAOOracle或OrderDAOSybase)为OrderDAO的实现,而OrderEJB无须任何更改。图3更能帮助你明白其中的道理:


图3 Data Access Object的设计模式

  此举增加了数据存取的弹性、资源的独立性和扩展性,但复杂度有相应的提高,其它附带的问题我们不在这儿讨论。

(未完,待续)

原文转自:http://www.ltesting.net