当我们为了完成某个业务逻辑,需要从数据库系统返回记录过多的结果集的时候,往往会引发多方面的问题,这些问题包括:性能优化设计策略、结果集的分页技术等等。对于开发人员来说,都是无法避免的。
先看看数据库查询大结果集可能带来的问题:
(1),内存占有过大。如果我们一次性把成千上万条记录保存在内存的话,内存势必会消耗过大,这使得JVM虚拟机能运用的内存空间减少,数据交换的速度减低,导致服务性能明显降低;而且,很容易引发内存不足不可恢复异常,最后导致整个服务瘫痪。
(2),网络传输阻塞。一般情况下,数据库服务都是独立一台机器,如果我们一次性从数据库返回大量数据的话,很容易瞬间导致网络阻塞,特别是当用户并发访问很大的时时候,情况更加明显。
(3),数据显示问题。如果一次性把成千上万条记录用一个页面或窗口呈献给查询用户,容易造成客户视觉疲劳,所以我们要考虑分页显示。
针对不同的问题,我们解决问题的方法也不尽相同。对待大结果集数据分页的处理上,我们一般的设计策略有以下3种方式:
(一),把结果集所有的数据一次性查询出来,放在应用服务器内存中,然后再分页处理。
这是一种很常见的思路,它的优点是:解藕了ResultSet操作类和数据库查询游标的关系,使得数据库连接得到有效的释放,提高了数据库并发访问的性能。同时,把数据导在本地,处理十分简单。由于数据都在内存中,翻页查询没有必要再从数据库请求数据,直接从内存获取就可以了,因而,响应更快。其缺点有:由于数据缓存在内存中,客户查询有可能看到的是过期数据;如果查询结果集数据量非常大的话,第一次查询遍历结果集会很耗时间,而且缓存这样大的数据也会造成内存消耗过大,使得JVM的效率明显降低。所以,这种方式对于查询结果在1000条以内的“小”结果集,而且数据完整性要求不高的情况下,可以采用,而且也十分简单有效。
(二),对查询结果集进行业务分析,针对查询客户的需要,把客户最为关心的数据首先呈献给客户,对于一些老数据,放入历史库,另外提供一个历史查询模块给客户使用。
这其实是把查询结果集按照客户的需要拆分开,避免了问题的主要矛盾,当然,前提是假设了用户实时关心的数据并不多。例如,对新闻数据查询,客户可能最关心的就是近3天的新闻信息,其它过期新闻可能1个月也不会查询一次。这个方式主要基于业务上设计策略,实现的技术也是甚为灵活。
(三),查询结果集所有的数据仍然留在数据库服务器端。每次翻页,我们都根据页面大小只从数据库服务器里面检索并返回块区数据,直到检索完所有的记录。
由于每次查询的记录数很少,网络传输数据量不大,不会造成阻塞。而且,数据都是由数据库统一提供,不会存在数据过期问题。应该说,这种方式是解决数据分页的理想方式。
实现方式(三)的技术常见有:
■直接使用JDBC底层的ResultSet接口,利用游标来处理。
ResultSet本质是在数据库服务器上建立游标,然后通过行位置定位数据记录。这种方法,当客户第一请求数据时,就执行查询语句,获得ResultSet对象,保存在会话中,以后分页获取数据时都是通过ResultSet对象来定位和获取指定位置的记录。最后,当客户不再进行分页查询的时候,就关闭会话,释放数据库连接和ResultSet等等数据访问资源。
优点:减少sql语句查询的次数,利用标准API实现,便于系统移植。
缺点:每一个用户查询都要占用一个数据库连接和结果集游标。当并发用户量大的时候,会浪费数据库连接资源,使数据库响应变慢,性能降低;另外,从系统设计的角度考虑,开发人员需要操作ResultSet和维护其状态,使得无法从结果集的处理独立出来,对系统框架的抽象设计很是不利;而且,ResultSet在数据定位上的操作也很是笨拙。
所以这方法基本上不值得提倡。
■
利用各种数据库服务器自己提供的对查询结果集的可定位行范围的接口技术来实现。
客户发出请求,数据库就根据查询请求的行范围参数,检索出所需的记录返回给客户端。客户获取记录集后就释放相关的数据访问资源,从而避免了对并发访问的影响。
优点:技术简单,直接利用了数据库产品特性实现,java开发人员无需关心其具体的实现原理;充分利用了数据库的连接资源;系统查询响应速度快;解藕了ResultSet与数据结果集的关系,便于系统框架的抽象设计。
缺点:需要涉及专有的数据库技术,对java开发人员要求高。每翻页一次,就要查询数据库一次;通用性不强,因为每种数据库的行范围定位技术都不一样,需要重新抽象。
虽然对开发人员数据库知识要求高,但这种方法往往是最为有效的解决方法。我们只要根据经验,把各种数据库的行范围技术总结一次,我们就重复利用,数据分页的问题因而也就变得十分简单了。BJAF数据存取框架总结来各个数据库系统分页特有技术,封装成
Pagination
查询分页组件,有效地解决来持久层数据库查询分页编程难题,组件UML结构图如下:
IPagination接口定义了
page(pInfo
:
PageParameter)
:
PageResult
分页方法,PaginationFactory用来解耦客户端与各个实现类之间的调用关系;PageParameter是分页参数对象,负责分页请求参数的构建和组织;PageResult是分页查询结果信息对象;PageHelper是计算分页的助手类。
假设前面查询EMP表薪水>2000的雇员记录数超过3000条,现在采取每页20返回条记录进行分页查询,其实现代码如下:
public static void main_testPagination(String[] args) {
// 建立一个分页参数对象
PageParameter param = new PageParameter();
param.setDataSourceName(Const.dataSourceName); // 设置数据源
param.setUserSql("select empno,ename,job,mgr,hiredate,sal,comm,deptno from emp where sal>=?"); // 查询语句
param.addParameter(new SqlParameter(SqlType.FLOAT, new Float(2000)));// 设置sql参数
param.setPageNumber(1);// 设置查询页号码(现返回第1页数据)
param.setPageSize(20);// 设置每页返回数量大小(条数)
// 利用PaginationFactory获取Oracle分页实现的实例
IPagination pageOpt = PaginationFactory
.getPaginationInstance(PaginationFactory.ORACLE_ID);
// 执行分页查询,并返回查询结果信息对象
PageResult result = pageOpt.page(param);
// 打印此结果信息对象
System.out.println(result.getCurPageNumber());// 当前页号
System.out.println(result.getCurPageSize());// 当前页数量大小
System.out.println(result.getCurPos());// 当前记录集位置
System.out.println(result.getFirstPageNumber());// 首页号码
System.out.println(result.getLastPageNumber());// 最后页号码
System.out.println(result.getNextPageNumber());// 下一页号码
System.out.println(result.getPrePageNumber());// 前一页号码
System.out.println(result.getPageAmount());// 总页数
System.out.println(result.getRecordAmount());// 总记录数
// 利用RsDataSet解析查询记录集
RsDataSet rs = new RsDataSet(result.getSqlResultSet());// 记录数据
for (int i = 0; i < rs.rowCount; i++) {
Emp emp = new Emp();
rs.autoFillRow(emp);
System.out.println(emp.getEmpNo());
System.out.println(emp.getEname());
System.out.println(emp.getHireDate());
System.out.println(emp.getJob());
System.out.println(emp.getMgr());
System.out.println(emp.getSal());
System.out.println(emp.getComm());
System.out.println(emp.getDeptNo());
System.out.println("--");
emp = null;
rs.next();
}
rs.clearAll();
}
注:SqlServerPaginationImp和SybasePaginationImp实现依赖与
Sp_Pagination
数据库存储过程,具体请参考java doc的api文档。
- 大小: 13.3 KB
分享到:
相关推荐
Beetle J2ee Application Framework(BJAF)一个功能强大而简单易用的J2EE应用开发框架。它涵盖了J2EE体系结构的表示层、业务层和持久层,为构建一个可靠、高性能、可扩展、灵活缩放的高质量企业应用系统提供了一套...
【标题】"beetle 开源框架书的源码"涉及的是一个名为"beetle"的开源框架的源代码,这通常意味着该框架可能是用于Java平台,因为J2EE(Java 2 Platform, Enterprise Edition)是Java领域广泛使用的开发企业级应用的...
BJAF(beetle-j2ee-application-framework)甲壳虫J2EE应用开发框架代码&开发指南 甲壳虫,一个功能强大而简单易用的J2EE应用开发框架。它涵盖了J2EE体系结构的表示层、业务层和持久层,为构建一个可靠、高性能、可...
标题中的"Beetle.JT808-master.zip"表明这是一个关于JT808协议的开源项目,由Beetle框架实现,且基于C#编程语言。Beetle是一个通用的通讯框架,而JT808则是一种广泛应用于中国GPS监控系统中的通信协议。这个项目可能...
总的来说,Popular Beetle是一款功能强大且易于使用的数据库管理工具,它的数据库比较和数据整合能力对于软件生命周期管理中的各个阶段都具有重要的价值。通过高效、准确的数据库操作,可以大大提升工作效率,降低因...
已经成功应用于多个高并发量的TCP、UDP框架通信接口,
本用户指南主要介绍了BEETLE_XL_II收款机的操作方法、维护保养以及常见问题解决办法等内容。它适用于所有BEETLE_XL_II系列产品的用户及技术支持人员。 #### 设备护理 - **日常清洁**:使用柔软干净的布料轻轻擦拭...
数据操作的jar包,包括oracle/mssql,通用~
在C#编程中,"Beetle"可能指的是一个自定义的框架或库,用于处理文件传输任务。这个框架可能是为了提高文件传输的效率而设计的。在标题中提到的"beetle类包含其他类",这暗示了Beetle可能是一个封装了多种功能的类库...
甲壳虫 PSX 剧本Beetle PSX 是 Mednafen 的 PSX 模块到 libretro API 的端口/分支。 可以用C++98模式编译,不包括Vulkan渲染器,暂时是用C++11写的。 Beetle PSX 目前在 Linux、OSX 和 Windows 上运行。 这个分叉中...
Beetle.zipscratch2.0 3.0编程项目源文件源码经典游戏案例素材源代码Beetle.zipscratch2.0 3.0编程项目源文件源码经典游戏案例素材源代码Beetle.zipscratch2.0 3.0编程项目源文件源码经典游戏案例素材源代码Beetle....
-dung_beetle.zip" 是一个压缩包,其中包含了一个名为 "dung_beetle-master" 的文件夹,这很可能是项目的源代码目录,通常包括教程的实例、脚本和其他相关资源。让我们逐步了解Python爬虫的基本概念和常用工具。 1....
标题中的“加长版甲壳虫汽车外壳3D图纸”是指使用solidworks2014软件设计的一款经典甲壳虫汽车的加长版车型的三维模型。SolidWorks是一款广泛应用于机械设计领域的三维CAD(计算机辅助设计)软件,以其易用性和强大...
有需要的朋友就下吧
天牛须算法(Beetle Antennae Search Algorithm,简称BAS),是一种新型的智能优化算法,它以长角天牛的搜索行为为灵感而设计。长角天牛因其长长的触须而著名,这些触须常常比它们的身体还要长。BAS算法模拟了这些...
标注类别名称:["Cashew-anthracnose","Cashew-healthy","Cashew-leaf-miner","Cassava-bacterial-blight","Cassava-brown-spot","Cassava-healthy","Maize-healthy","Maize-leaf-beetle","Maize-leaf-blight",...
标题中的“c#_以Beetle为基础SOCKET服客端(WPF)与客户端(winphone\win8 metro)”指的是一个使用C#编程语言构建的网络通信应用,它基于Beetle框架,实现了SOCKET服务器端(WPF)以及Windows Phone和Windows 8 Metro...
至于“keracce-Beetle-9cc3275”,这可能是一个源代码库的特定版本标识,比如Git仓库的一个分支或者标签。这个名称可能指的是Beetle项目的作者或者一个特定的开发迭代。要深入理解这个项目,你需要解压这个压缩包并...
蜣螂优化算法(DBO,Dung Beetle Optimization Algorithm)是一种基于生物行为的新型全局优化算法,灵感来源于蜣螂(也称屎壳郎)在寻找食物过程中所展现出的探索和滚动粪球的行为。2022年底,该算法被首次提出,并...