提升数据访问层的性能(一)

原创 2004年08月29日 21:40:00
在J2EE应用中,我们经常通过JDBC访问企业资源。但JDBC用的不好,将会影响系统的性能。本文参照John Goodson的《Performance Tips for the Data Tier(JDBC)》一文,写成此文,希望对我们的开发有所帮助。
本文从以下四个部分加以说明:
l    适当地使用数据库的元数据方法
l    检索需要的数据
l    选择优化性能的功能
l    管理连接和数据更新
1.    适当地使用数据库的元数据方法
1.1.    尽量少用元数据方法
由于元数据方法执行速度比较慢,故要尽量少用元数据方法。由于调用元数据方法产生结果集需要大量的开销,由元数据方法产生的结果集应该缓存起来,而不是多次执行查询,这样可以提供JDBC的性能。例如在应用中你调用了getTypeInfo一次,你就应该将结果集缓存起来,共应用再次使用。
1.2.    避免查询模式
给元数据提供null参数或查询模式将会产生耗时的查询。同时,由于一些不需要的数据通过网络传递,导致网络流量的增大,降低整个系统的性能。由于元数据方法执行比较慢,所以尽可能地给它提供非null参数和高效地调用它。而我们的应用常出现这样的现象:
ResultSet WSrs = WSc.getTables (null, null, "WSTable", null);
应该改成:
ResultSet WSrs = WSc.getTables ("cat1", "johng", "WSTable",  "TABLE");
显然,在第一个getTables()调用中,应用可能需要知道WSTable表是否存在。当然, JDBC驱动按字面上的调用与解析请求不同。JDBC是这样解析请求的:返回所有的名称叫“WSTable”的表,视图,系统表,同义词,零时表,或在任何数据库目录中数据库的模式存在的别名。
第二个getTables()的调用更准确地反映了应用需要知道什么。JDBC这样解析这个请求:返回所有名叫“WSTable”存在与当前目录中模式为“johng’的所有表。显然,JDBC驱动处理第二个请求要比处理第一个请求来得更有效。
给元数据方法提供的信息越多,你得到的信息的准确性和性能也越高。
1.3.    使用哑元查询来确定表的特征
避免使用getColumns()确定一个表的特征。用getMedata()哑元查询替换之。考虑一个容许用户选择列的应用。应用应该用getColumns()返回用户列的信息还是准备一个哑元查询并调用getMetadata()呢?
情形1:getColumns方法
ResultSet WSrc = WSc.getColumns (... "UnknownTable" ...);// This call to getColumns() will generate a query to// the system catalogs... possibly a join// which must be prepared, executed, and produce// a result set. . .WSrc.next();string Cname = getString(4);. . .// user must retrieve N rows from the server// N = # result columns of UnknownTable// result column information has now been obtained
情形2:getMetadata方法
// prepare dummy queryPreparedStatement WSps = WSc.prepareStatement  ("SELECT * from UnknownTable WHERE 1 = 0");// query is never executed on the server - only preparedResultSetMetaData WSsmd=WSps.getMetaData();int numcols = WSrsmd.getColumnCount();...int ctype = WSrsmd.getColumnType(n)...// result column information has now been obtained
在两个情形中,查询被送到服务器上。但在情形1中,查询必须被准备和执行,结果描述信息必须被简洁地表达,并且结果集必须送到客户端。在情形2中,一个简单的查询必须准备并且仅有结果描述信息被简洁地描述。显然,情形2是更好的性能模式。
这多少有些把这个讨论复杂化了,让我们考虑一个不支持本地准备SQL语句的数据库。情形1的性能没有变,但由于哑元查询必须被求值而不是仅仅准备,因此情形2的性能稍微有些增加。因为查询语句的Where子句计算结果总是FALSE,因此查询没有产出结果行和不存取表数据的执行。在这个情形下,方法2仍然要比方法1做的好。
总之,总是使用结果集元数据检索表列信息,如列名,列数据类型和列精度和数值范围。当被请求的信息不能从结果记录集(例如,表列默认值)获取的时候,仅仅使用getColumns()方法。
2.    检索需要的数据
2.1.    检索长数据
除非必要,由于检索长数据会造成网络资源紧张而降低性能。通常大多数用户不需要看到长数据,如果用户需要看这些数据,应用再去检索。
我们的代码中长出现这样的代码:select * from <table name> …如果选择的表中有长数据列,那这个查询的性能将会非常糟糕。再说,表中的所有数据项你都需要吗?如果不需要,为什么要让它们在网络上传递,浪费网络资源?
例如,看看下边的JDBC代码:
ResultSet rs = stmt.executeQuery (   "select * from Employees where SSID = '999-99-2222'");rs.next();string name = rs.getString (4);
JDBC不是智能的。当你这样写代码的时候,它根本就不知道你真正需要那些列,它把所有的都返回当然是情理之中的事情了,所以开发的时候就劳烦把需要的列在Select语句中指明。如果Employees表中有照片之类的长数据字段,系统的性能之低就可想而知了。
尽管有方法getClob()和getBlod()支持这种长数据字段的检索,但并不是每个数据库都支持它。所以记住:需要长数据的时候再去读它。
2.2.    减少检索到的数据的大小
有时候,长数据必须被检索。在这种情况下,大多数用户可能不需要在屏幕看到100k(或更多)的正文。 为了减少网络流量和提高性能,你可以通过调用setMaxRows(),setMaxFieldSize(),以及与驱动相关的setFetchSize()方法把检索到的数据大小减少到可管理的范围之内。另一个减少检索到的数据大小的方法是减少列的数量。如果驱动允许你定义包尺寸,使用最小的包尺寸将会满足你的需要。
记住:注意只返回你需要的行和列。如果你返回了五列而你只需要两列,性能就降低了??特别是不需要的结果中包含了长数据。
2.3.    选择正确的数据类型
检索和送出某种数据的类型的开销是很昂贵的。当设计数据库模式时,选择能最有效处理的数据类型。例如,整型要比浮点数和小数数据要快。浮点数根据数据库特殊的格式定义,通常是压缩格式。为了能被数据库通讯协议处理,这些数据必须被解压后再转换成不同的格式。
2.4.    检索记录集
由于数据库系统对滚动游标的有限支持,大多数JDBC驱动不能实现滚动游标。除非你确定数据库支持滚动记录集(例如,rs),否则不要调用rs.last()和rs.getRow()去得到记录集有多少行。对模仿滚动游标的JDBC驱动而言,调用rs.last()会导致驱动为了到最后一行而通过网络检索所有的数据。可以替代的方法是你可以通过记录集枚举记录行数,或者通过提交在SELECT语句中一个带有COUNT列的查询得到行数。
一般情况下,不要写依赖于记录集行数的代码,因为为了取得行数,驱动必须读取记录集中的所有的行。

如何提高数据库访问性能

特别说明: 1、  本文只是面对数据库应用开发的程序员,不适合专业DBA,DBA在数据库性能优化方面需要了解更多的知识; 2、  本文许多示例及概念是基于Oracle数据库描述,对于其它关...
  • u010327174
  • u010327174
  • 2014年10月16日 16:35
  • 1757

数据访问层的设计(一)——功能与接口定义

数据访问层的设计我研究了很长时间,关于接口的定义,好几次都推翻重来。 园子看到过很多easyui+MVC+EF的文章,在早期,我的设计也类似。 但是后来为了增强它,想加点功能通用的功能进去,就耗费...
  • dyllove98
  • dyllove98
  • 2013年07月19日 19:19
  • 7938

实验楼sql进阶之简化数据操作提升性能(window)

背景成绩管理系统中,当有同学的分数被修改时,需要通过触发器将成绩表中的这条更新记录存到新的表 modifymark 中。同时需要创建一个存储过程用来显示数学课的全部学生的成绩,并按分数降序排列。另外,...
  • u013716535
  • u013716535
  • 2017年11月07日 21:05
  • 104

数据访问层的设计和实现(分布式系统七)

(1)如何对外提供数据访问层的功能 数据访问层就是方便应用进行数据读写访问的抽象层,在该层上解决各个应用通用的访问数据库的问题。 上图显示了三种方式,第一种是为用户提供专有API,不过不推...
  • u011393781
  • u011393781
  • 2016年10月08日 17:41
  • 1478

数据访问层的性能优化

本文只是自己项目的经验总结。 目前自己独立做的一些项目都是采用传统的MVC模式,采用Spring MVC+Hibernate+Mysql 开发,Request的调用层次是Controller 调用S...
  • nokiaisacat
  • nokiaisacat
  • 2016年07月22日 15:23
  • 213

三层架构:表示层-业务逻辑层-数据访问层

三层架构和MVC是两个东西。 非要相关的话: 三层架构中"表现层"的aspx页面对应MVC中的View(继承的类不一样) 三层架构中"表现层"的aspx.cs页面(类)对应MVC中的Co...
  • ruiguang21
  • ruiguang21
  • 2016年12月25日 11:29
  • 2072

.net中的数据访问层的封装

当年.net项目中自己封装的数据访问层,个人感觉使用非常方便
  • kevin_xf
  • kevin_xf
  • 2016年12月05日 15:53
  • 764

分布式数据访问层(DAL)

概述分布式(Distributed)数据访问层(Data Access Layer),简称DAL,是利用MySQL Proxy、Memcached、集群等技术优点而构建的一个架构系统。主要目的是为了解...
  • xcbeyond
  • xcbeyond
  • 2017年02月11日 00:46
  • 1339

数据访问层MyBatis解析

一、背景         最近在研究Java的框架,刚刚接触到java对于数据访问层封装的框架之一,MyBatis,不得不说使用起来很是方便,跟写sql语句的感觉一样一样的;顺便读了少部分官方文档,...
  • u012704843
  • u012704843
  • 2017年04月06日 17:46
  • 864

php大型网站如何提高性能和并发访问

 一、大型网站性能提高策略:     大型网站,比如门户网站,在面对大量用户访问、高并发请求方面,基本的解决方案集中在这样几个环节:使用高性能的服务器、高性能的数据库、高效率的编程语言、还...
  • u011690564
  • u011690564
  • 2017年02月06日 10:36
  • 564
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:提升数据访问层的性能(一)
举报原因:
原因补充:

(最多只允许输入30个字)