JDBC性能优化
一、使用PreparedStatement的Batch功能
参见本人一下文章:http://blog.csdn.net/lmb55/article/details/50631062
二、选择合适的光标类型
选择合适的光标类型以最大限度的适用你的应用程序。(以下列出三种光标类型的性能问题)
对于从一个表中顺序读取所有记录的情况来说, Forward-Only型的光标提供了最好的性能。 获取表中的数据时, 没有哪种方法比使用Forward-Only型的光标更快。 但不管怎样, 当程序中必须按无次序的方式处理数据行时, 这种光标就无法使用了。
对于程序中要求与数据库的数据同步以及要能够在结果集中前后移动光标, 使用JDBC的Scroll-Insensitive型光标是较理想的选择。 此类型的光标在第一次请求时就获取了所有的数据(当JDBC驱动采用’lazy’方式获取数据时或许是很多的而不是全部的数据)并且储存在客户端。 因此, 第一次请求会非常慢,特别是请求长数据时会理严重。而接下来的请求并不会造成任何网络往返(当使用’lazy’方法时或许只是有限的网络交通) 并且处理起来很快。因为第一次请求速度很慢,Scroll-Insensitive型光标不应该被使用在单行数据的获取上。 当有要返回长数据时,开发者也应避免使用Scroll-Insensitive型光标, 因为这样可能会造成内存耗尽。 有些Scroll-Insensitive型光标的实现方式是在数据库的临时表中缓存数据来避免性能问题,但多数还是将数据缓存在应用程序中。
Scroll-Sensitive型光标,有时也称为Keyset-Driven光标,使用标识符,像数据库的ROWID之类。当每次在结果集移动光标时, 会重新该标识符的数据。 因为每次请求都会有网络往返, 性能可能会很慢。无论怎样,用无序方式的返回结果行对性能的改善是没有帮助的。
现在来解释一下这个, 来看这种情况。一个程序要正常的返回1000行数据到程序中. 在执行时或者第一行被请求时, JDBC驱动不会执行程序提供的SELECT语句. 相反, 它会用键标识符来替换SELECT查询, 例如, ROWID. 然后修改过的查询都会被驱动程序执行,跟着会从数据库获取所有1000个键值. 每一次对一行结果的请求都会使JDBC驱动直接从本地缓存中找到相应的键值, 然后构造一个包含了’WHERE ROWID=?’子句的最佳化查询, 再接着执行这个修改过的查询, 最后从服务器取得该数据行。
当程序无法像Scroll-Insensitive型光标一样提供足够缓存时, Scroll-Sensitive型光标可以被替代用来作为动态的可滚动的光标。
三、使用有效的getter方法
JDBC提供多种方法从ResultSet中取得数据,像getInt(), getString(), 和getObject()等等。 而getObject()方法是最泛化了的, 提供了最差的性能。 这是因为JDBC驱动必须对要取得的值的类型作额外的处理以映射为特定的对象。 所以就对特定的数据类型使用相应的方法.
要更进一步的改善性能, 应在取得数据时提供字段的索引号, 例如, getString(1), getLong(2), 和getInt(3)等来替代字段名。 如果没有指定字段索引号。网络交通不会受影响。 但会使转换和查找的成本增加。例如,假设你使用getString(“foo”) … JDBC驱动可能会将字段名转为大写(如果需要),并且在到字段名列表中逐个比较来找到”foo”字段。 如果可以,直接使用字段索引,将为你节省大量的处理时间。
例如,假设你有一个100行15列的ResultSet,字段名不包含在其中。你感兴趣的是三个字段 EMPLOYEENAME (字串型), EMPLOYEENUMBER (长整型), 和SALARY (整型)。 如果你指定getString(“EmployeeName”), getLong(“EmployeeNumber”), 和getInt(“Salary”), 查询旱每个字段名必须被转换为metadata中相对应的大小写,然后才进行查找。如果你使用getString(1), getLong(2), 和getInt(15)。 性能就会有显著改善。
四、选择合适的数据类型
接收和发送某些数据可能代价昂贵。当你设计一个schema时, 应选择能被最有效地处理的数据类型。 例如, 整型数就比浮点数或实数处理起来要快一些。浮点数的定义是按照数据库的内部规定的格式,通常是一种压缩格式。 数据必须被解压和转换到另外种格式,这样它才能被数据的协议处理。
五、获取ResultSet
由于数据库系统对可滚动光标的支持有限, 许多JDBC驱动程序并没有实现可滚动光标。除非你确信数据库支持可滚动光标的结果集,否则不要调用rs.last()和rs.getRow()方法去找出数据集的最大行数。因为JDBC驱动程序模拟了可滚动光标, 调用rs.last()导致了驱动程序透过网络移到了数据集的最后一行。取而代之,你可以用ResultSet遍历一次计数或者用SELECT查询的COUNT函数来得到数据行数。
通常情况下,不要写那种依赖于结果集行数的代码, 因为驱动程序必须获取所有的数据集以便知道查询会返回多少行数据,当表中的数据量非常大时,这种做法是非常消耗性能的。
六、获取自动生成的键值
当插入一条记录时,我们很多时候都想马当前插入的主键返回出来.
如果主键是自动生成的(大多数时候是这样),那么取回主键是一种比较困难的事.
可能对于一些特殊的数据库必须把insert into和select max(key)或什么序列当前值作为一个事务的原子来操作,但很多数据库(以及数据库操作环境)并不能为你提供事务并发控制.所以如果多人同时操作,那么select max(key)很可能就不是你刚才insert的那条记录.
在SQL server 很方便,有现程的sql可以用
INSERT INTO tableName (fieldList ...) values (valueList ...) SELECT @@IDENTITY AS aliasName;
- 1
该SQL的示例如下:
--创建表
create table OrgInfo
(
OrgId int identity(1,1) primary key,
OrgName nvarchar(20)
)
--插入测试数据
insert into OrgInfo
select '张三' union select '李四' union select '王五'
select * from OrgInfo
/*
OrgId OrgName
----------- --------------------
1 李四
2 王五
3 张三
*/
--假设此时我们再插入一条,然后得到新插入的id
insert into OrgInfo select '刘六'
--得到新插入的id
select @@identity
/*
4
*/
--得到新插入的数据行
select * from OrgInfo where OrgId=@@identity
/*
OrgId OrgName
----------- --------------------
4 刘六
*/
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
在Oracle中,有两种方案:
1、使用JDBC的getGeneratedKeys()方法,第一次返回oracle的rowid,第二次使用返回的rowid查询该条数据。
String sql = "insert into xx_cust(cust_type,cust_name,login_name)"
+ " values('ipn','aaa','bb')";
//省略创建数据库连接的过程
PreparedStatement stmt = conn.prepareStatement(sql,Statement.RETURN_GENERATED_KEYS);
stmt.execute();
ResultSet rs = stmt.getGeneratedKeys();
rs.next();
String rowid=rs.getString(1);
System.out.println("rowid="+rowid);//返回rowid
PreparedStatement preparedStatement =conn.prepareStatement("select cust_id from xx_cust where rowid=?");
preparedStatement .setString(1, rowid);
ResultSet rs2 = preparedStatement.executeQuery();
rs2.next();
String custId=rs2.getString(1);
System.out.println("custid="+custId);//通过rowid查询插入的数据
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
2、使用oracle的returning语句
String sql = "insert into xx_cust(cust_type,cust_name,login_name)"
+ " values('ipn','aaa','bb') returning cust_id into ?";
OraclePreparedStatement stmt = (OraclePreparedStatement) conn.prepareStatement(sql);
stmt.registerReturnParameter(1, OracleTypes.INTEGER);
int count = stmt.executeUpdate();
if (count > 0) {
ResultSet rs = stmt.getReturnResultSet();
while (rs.next()) {
String name = rs.getString(1);
System.out.println("name=" + name);
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
未完待续。。。
JDBC性能优化的更多相关文章
- JDBC性能优化方案
最近用到了利用JDBC查询Oracle数据库.可是查询效率不尽人意.研究了一下JDBC方面能够优化的地方,在这里跟大家分享一下. 1.设置最优的预取值 defaultRowP ...
- JDBC性能优化篇
系统性能. 少用Metadata方法 与其它的JDBC方法相比, 由ResultSet对象生成的metadata对象的相对来说是很慢的. 应用程序应该缓存从ResultSet返回的metada ...
- mysql jdbc性能优化之mybatis/callablestatement调用存储过程mysql jdbc产生不必要的元数据查询(已解决,cpu负载减少20%)
INFO | jvm 1 | 2016/08/25 15:17:01 | 16-08-25 15:17:01 DEBUG pool-1-thread-371dao.ITaskDao.callProce ...
- JDBC性能优化点
1). 指定数据库连接池中初始化连接数的个数
- JDBC性能分析与优化
JDBC性能分析与优化V1.0http://www.docin.com/p-758600080.html
- 数据库访问性能优化 Oracle
特别说明: 1. 本文只是面对数据库应用开发的程序员,不适合专业DBA,DBA在数据库性能优化方面需要了解更多的知识: 2. 本文许多示例及概念是基于Oracle数据库描述,对于其它关系型数据库也 ...
- SQL性能优化常见措施(Lock wait timeout exceeded)
SQL性能优化常见措施 目 录 1.mysql中explain命令使用 2.mysql中mysqldumpslow的使用 3.mysql中修改my.ini配置文件记录日志 4.mysql中如何加索引 ...
- Hibernate的性能优化问题
本文是根据Hibernate帮助文档,以及一些书籍及项目经验整理而成,只提供要点和思路,具体做法可以留言探讨,或是找一些更详细更有针对性的资料. 初用Hibernate的人也许都遇到过性能问题,实现同 ...
- JVM内存模型和性能优化 转
JVM内存模型和性能优化 JVM内存模型优点 内置基于内存的并发模型: 多线程机制 同步锁Synchronization 大量线程安全型库包支持 基于内存的并发机制,粒度灵活控制,灵活度高于 ...
随机推荐
- ajax 请求 get请求成功,post 404 not found
今天在做express的一个ajax请求的时候发现get请求成功,post 就一直是 404 not found, 研究了半天 才发现是express 的请求方法做了限制,之前一直都是用的 app.g ...
- C语言事实上不简单:数组与指针
之前在写C的时候,没怎么留意数组.就这么定义一个.然后颠来倒去的使用即可了.只是后来碰到了点问题.解决后决定写这么一篇博客,数组离不开指针.索性就放一起好了. 如今我定义了一个数组:int cc[10 ...
- C# MVC 用户登录状态判断 【C#】list 去重(转载) js 日期格式转换(转载) C#日期转换(转载) Nullable<System.DateTime>日期格式转换 (转载) Asp.Net MVC中Action跳转(转载)
C# MVC 用户登录状态判断 来源:https://www.cnblogs.com/cherryzhou/p/4978342.html 在Filters文件夹下添加一个类Authenticati ...
- “取出数据表中第10条到第20条记录”的sql语句+select top 使用方法
1.首先.select top使用方法: 參考问题 select top n * from和select * from的差别 select * from table -- 取全部数据.返回无序集合 ...
- Cholesky分解 平方根法
一种矩阵运算方法,又叫Cholesky分解.所谓平方根法,就是利用对称正定矩阵的三角分解得到的求解对称正定方程组的一种有效方法.它是把一个对称正定的矩阵表示成一个下三角矩阵L和其转置的乘积的分解.它要 ...
- RDA CoreDump 实例
UMF进程的Coredump问题追踪: 通河code开机DUMP问题 现象: 开机Dump,原因:_MAINAPP_SW_Init()调用了Factory_Ver_Debug()内存溢出. 分析流程: ...
- ASP.NET面试点汇总
1.维护数据库的完整性.一致性.你喜欢用触发器还是自写业务逻辑?为什么答:尽可能用约束(包括CHECK.主键.唯一键.外键.非空字段)实现,这种方式的效率最好:其次用触发器,这种方式可以保证无论何种业 ...
- 基于ELK的传感器数据分析练习
目录 Sensor Data Analytics Application 数据构成 数据模型设计 Logstash配置 Kibana可视化 Sensor Data Analytics Applicat ...
- apache相关补充
apache相关补充 sendfile机制 1)不用sendfile的传统网络传输过程: read(file, tmp_buf, len) write(socket, tmp_buf, len) 2) ...
- bzoj 1774: [Usaco2009 Dec]Toll 过路费【排序+Floyd】
非常迷的一道题啊 我觉得挺对的版本只得了30 总之就是Floyd·改,开两个数组,一个是d[i][j]就是普通的只有边权的最短路,a[i][j]是题目要求的那种 具体改的地方是把枚举中转点的地方把中转 ...