微调数据库访问会使应用程序和数据库保持协调一致。
如果您在开发 Web 应用程序,那么您很可能熟悉基于Java连接到数据库的方法:JDBC 和 SQLJ。但是您知道如何能让使用这些方法的应用程序获得最佳性能吗?
如果您认为性能不是开发人员所关心的问题,那么请您再想想,有的系统执行效率一般,有的系统执行效率很棒,造成这一区别的原因是什么呢?我认为这主要在于数据库架构设计师、数据库管理员和应用程序开发人员的技能和经验。
尽管数据库优化应该从最初的设计阶段开始,但是也可以在生产环境中对早已建立的数据库和相关的应用程序进行微调。提高性能并不仅仅包括在数据库中创建索引和规范化,虽然这些也是必须要做的工作,但是仅有此还不够。访问数据库的应用程序设计(及其访问数据库的方式)对获得最佳性能也是至关重要的。
为帮助您提高应用程序性能,针对通过 JDBC(或使用 JDBC 的 IBM WebSphere Application Server)和 SQLJ 来进行数据库存取的应用程序,这里提供了一些优化方面的技巧。
优化 JDBC
几乎所有的企业级 Web 应用程序中都使用三层设计:表示层、应用层和数据层,在这种模型中,基于 Java 的应用程序连接到数据库所采用的标准之一就是 JDBC。
要优化使用 JDBC 接口的数据库访问,请遵循这些准则:
尽量避免使用元数据方法。虽然不能完全避免使用元数据(描述其他数据和引用的数据)方法,但是请尽可能少使用它们。由于它们是添加的抽象层,因而访问它们相对较慢。
避免使用 GETCOLUMNS
。不要使用 GETCOLUMNS
命令查找表的详细信息,请尝试用 GETMETADATA
命令进行“哑”查询。
避免使用地毯式搜索。在 JDBC 查询中使用数据库命令 LIKE
和 AS
会降低性能,查询大型表时尤其如此。查询中使用空的自变量也会降低性能。请尽可能地消除这些语句。
减少要检索的数据量。仅查询您需要的数据,不要超出此范围。除非绝对必需,否则不要检索很长的数据列表。最好设计一个终端程序,可以一次发送几组数据,就像 Yahoo! 和 Google 这样高度优化的搜索引擎一样。除非使用 SELECT * FROM <TABLE NAME>
是必需的,否则请不要使用此方式。
减少要返回的数据量。通过 SETMAXROWS
和 SETMAXFIELDSIZE
设置查询的界限,将界限与所需的最大数据相匹配,这样会有助于提高性能。例如,搜索引擎不需要返回一次查询中所有 600,000 个匹配。相反,它可以设置合理的界限,使之能满足 99% 的用户,而对于剩下的 1% 的用户,则需要再做一次额外的调用。这种方法要花费更多的时间去构建,并且要很好地了解用户的需求和行为。但是,在非常敏感的企业数据库系统中,像这样做来提高性能是很值得的。
选择合适的数据类型。如果数据库设计经常更改,这种方法可能会引起太多开销。但通常情况下,在建表时选择保存数据所需的最小存储长度的数据类型是一个非常好的方法。例如,当需要整数时,使用整数类型而不是实数或浮点数(后两者需要花费更多的时间来处理)。
使用参数来调用自变量。这一规则在任何应用程序中都是最佳编码方式。固化自变量不灵活,经常导致以后的维护问题。同时,因为在调用存储过程时所有的参数都会作为字符串送往数据库,使用固定值的参数还会降低数据库性能。在远程过程调用(RPC)过程中使用变参效果会更好。
为作业选择正确的游标。弄清楚表所需的游标类型,使用其中能提供最高性能的游标。对于只需顺序读的情况,应选择正向游标。对于需要查询的数据量比较小的应用程序,最好使用Insensitive 游标,该游标会创建数据集的临时拷贝,然后可以在该数据拷贝中遍历,这种游标在 Web 应用程序中尤其常见。Sensitive 游标只用于大的数据集和动态的数据检索,因为它们通常是性能中开销最大的。
管理连接。虽然像 WebSphere 这样的应用服务器能处理大量的会话管理,但还是应该注意一些优化技巧。例如,一次只连接到一个数据源。避免执行 SQL 调用时需要对数据库进行连接和断开连接所带来的高开销。并且尽量共用连接以获得更佳的性能。DB2 通用数据库(UDB)V8.1 还提供了新的连接的集中和简化机制,通过有效自动地管理数据库连接来提高应用程序的性能。
关闭 AUTOCOMMIT
。这是优化数据库中最重要的规则。您甚至不必去考虑它,只需设置 WSCONNECTION.SETAUTOCOMMIT(FALSE)
即可。
尽可能地使用本地事务。分布式事务会比较慢。
使用 UPDATEXXX 命令取代一般的 update 命令。这个方法对于常要更改数据库设计的系统来说是不适用的。但在设计相对静态的系统中,UPDATEXXX
命令会提高性能,因为具有针对性的命令总是比通用的命令快。
即使对于最复杂的、使用 JDBC 的 Web 应用程序,以上建议仍能使之获得很好的性能。
优化 WebSphere
因为 WebSphere 符合J2EE规范,它的许多连接使用了 JDBC,所以用于 JDBC 的这些优化建议同样适用于它。但是,使用 WebSphere 时,还需知道两个重要的优化技巧:
- 使用
GETBESTROWIDENTIFIER()
。使用这个命令来获取最优的列集合,它将减少处理时间。使用GETPRIMARYKEYS()
和GETINDEXINFO()
来用格式化WHERE
子句,这将有助于使开销降到最少。 - 使用 Statement 对象。在对数据库只执行一次性存取的时侯,用 Statement 对象进行处理。PreparedStatement 对象的开销比Statement大,对于一次性操作并不会带来额外的好处。
优化 SQLJ
SQLJ 可以替代 JDBC,它有特定的优势。同样达到最优的性能时,SQLJ 的效率比 JDBC要高好。但是,SQLJ 的灵活性不及 JDBC,因为它使用了更多固定的静态值,而没有提供变量的替换方法。这两个数据库访问方法之间的区别,类似于使用编译型程序(SQLJ)和使用解释型程序(JDBC)之间的区别(前者在运行时之前就执行了一些处理,后者在运行时编译并执行)。
SQLJ 是一种高级语言,它涵盖了 JDBC 的功能,但是它需要非常严格的、特定的函数以确保达到最高性能。和 JDBC 一样,SQLJ 是 Java 程序的标准之一,它保持了 Java 的平台独立性。但是,SQLJ 不符合 J2EE,因此,在所有应用程序服务器中都不支持它。
在许多方法中,需要最高性能的企业级 Web 应用程序要高效地与 DB2 相连,SQLJ 就是关键因素之一。其它数据库在这一级别不支持 SQLJ,因此它通常使 DB2 的工作性能比其竞争对手要好。支持 Web 的 DB2 要想避免性能损失可能很困难,对于事务处理系统来说尤其如此。但是,在真正的静态实现中,SQLJ 和 DB2 具有的性能优势超过其它数据库。
以下准则将有助您利用这个前沿技术:
显式地关闭和释放资源。如果连接到数据库的应用程序需要长期运行,最重要的规则之一是在正确的时机清除活动会话。切记,任何人都不期望经常重新引导系统。
完成后关闭结果集。通常会遗漏这个步骤,但是如果您没有执行这一步骤,则 Java 虚拟机(JVM)垃圾收集机制就不能回收对象。最后应用程序可能耗尽 JDBC 资源,甚至可能耗尽内存。
只更新和访问需要的字段。再一次重申,应该只访问需要的数据,不要超出此范围。
定制 SQLJ profiler和请求联机检查。该步骤防止 SQLJ 动态地访问数据,从而降低性能。这条规则将确保 SQLJ 静态地运行。
调优 JVM 堆的大小。1MB 的缺省堆往往不够大,会影响性能。增大堆的大小以满足应用程序的需要。但是要注意:将堆的大小设置成最大会降低垃圾收集的频率,其结果反而会影响性能。
使版本保持最新。尽量使用新的版本。虽然移植要花费一些精力,但通常值得我们这样做。SQLJ 和 JDBC 都是比较新的标准,每个新的版本都会有比较显著的性能提高。
打开高速缓存。该规则帮助您避免准备动态 SQL 所要的开销。设置 CACHEDYN=YES
将有助于提高 SQLJ 代码的性能。
通过微调 SQLJ,使 Web 应用程序访问数据库的性能能够赶上甚至超越使用 JDBC 时的性能。
选择自己的途径
优化数据库有许多可能的途径。不要期望一次就应用所有的方法。如果您一次只从一个途径着手,就应该可以得到性能的提高。通过准备工作和适当的计划,即使是最复杂的数据库应用也能达到最优的性能。别忘了,千里之行始于足下。