`

Java_JDBC优化策略

    博客分类:
  • Java
 
阅读更多

via: http://lavasoft.blog.51cto.com/62575/225828/

相比Hibernate、iBatis、DBUtils等,理论上JDBC的性能都超过它们。JDBC提供更底层更精细的数据访问策略,这是Hibernate等框架所不具备的。

 

在一些高性能的数据操作中,越高级的框架越不适合使用。这里是我在开发中对JDBC使用过程中一些优化经验总结。

 

1、选择纯Java的JDBC驱动。

 

2、使用连接池--使用一个“池”来管理JDBC连接,并精心调试池配置的参数,目前可用的数据库连接池很多很多。

如何配置合适的参数呢,需要的是测试,而不是感觉。

 

3、重用Connection--最大限度使用每个数据库连接,得到了就不要轻易“丢弃”。

有时候在一个过程中,会多次操作数据库,而仅仅需要一个连接就够了,没必用一次就获取一个连接,用完后关闭或者入池。这样会增加“池”管理的成本,千万别以为你用了“池”就可以随便申请和归还连接,都是有代价的。如果是一个庞大循环块中操作数据库,更应该注意此问题!

除此之外,还应该对连接进行密集使用,尽可能晚的打开,并可能早的关闭。比如,你一个业务中有N多的操作,数据库操作穿插在其中,而其他的业务处理操作时间很长,那么使用一个连接处理这些操作是有问题的。这会导致长期占用连接,给数据库带来压力。

 

4、重用Statement/PreparedStatement--对于一些预定义SQL,设置为静态常量,并尽可能重用预定义SQL产生的PreparedStatement对象。对于多次使用一种模式的SQL,使用预定义SQL可以获取更好的性能。对于Statement对象,可以反复的重用,每次都可以接收不同的SQL语句,而对于PreparedStatement则不可以,因为预定义SQL在定义PreparedStatement对象时候已经确定了,但是如果sql语句不变,则可以调用clearParameters()来达到从用目的,如果sql语句发生变化,也可以从用变量名。

 

5、使用批处理SQL。

 

6、优化结果集ResultSet--查询时候,返回的结果集有不同的类型,优先选择只读结果集、不可滚动的属性。

这里是很容易出现问题的地方:

java.sql.ResultSet 

 

static int CLOSE_CURSORS_AT_COMMIT    该常量指示调用 Connection.commit 方法时应该关闭 ResultSet 对象。    

static int CONCUR_READ_ONLY    该常量指示不可以更新的 ResultSet 对象的并发模式。    

static int CONCUR_UPDATABLE    该常量指示可以更新的 ResultSet 对象的并发模式。    

static int FETCH_FORWARD    该常量指示将按正向(即从第一个到最后一个)处理结果集中的行。    

static int FETCH_REVERSE    该常量指示将按反向(即从最后一个到第一个)处理结果集中的行处理。    

static int FETCH_UNKNOWN    该常量指示结果集中的行的处理顺序未知。    

static int HOLD_CURSORS_OVER_COMMIT    该常量指示调用 Connection.commit 方法时不应关闭 ResultSet 对象。    

static int TYPE_FORWARD_ONLY    该常量指示指针只能向前移动的 ResultSet 对象的类型。    

static int TYPE_SCROLL_INSENSITIVE    该常量指示可滚动但通常不受其他的更改影响的 ResultSet 对象的类型。    

static int TYPE_SCROLL_SENSITIVE    该常量指示可滚动并且通常受其他的更改影响的 ResultSet 对象的类型。

 

说明下:

结果集分两种类型:只读和可更改,只读的话,更省内存,查询的结果集不能更改。如果结果集在查询后,更改了值又要保存,则使用可更改结果集。

结果集的游标也有两种类型:如果没必要让游标自由滚动,则选择单方向移动的游标类型。

对于是否并发操作:如果不需要考虑线程安全,则选择忽略并发的结果集类型,否则选择并发安全的类型。

另外,还要控制结果的大小,几乎所有的数据库都有查询记录条数控制的策略,可以海量数据进行分批处理,一次一批,这样不至于把系统搞死。

 

7、事物优化--如果数据库不支持事物,就不要写回滚代码,如果不考虑事物,就不要做事务的控制。

 

8、安全优化--管理好你的Connection对象,在异常时候能“入池”或者关闭。因此应该将Connection释放的代码写在异常处理的finally块中。

 

9、异常处理优化--不要轻易吞噬SQLException,对于DAO、Service层次的数据访问,一般在DAO中跑出异常,在Service中处理异常。但DAO中也可以处理异常,并做转义抛出,不要随便抛出RuntimeExeption,因为这是JVM抛出的,不需要你可以去抛出,因为RuntimeException往往会导致系统挂起。

 

10、代码高层优化--在以上的基础上,优化封装你的数据访问方式,尽可能让代码简洁好维护,如果你还觉得性能不行,那就该从整个系统角度考虑优化了,比如加上缓存服务器,集群、负载均衡、优化数据库服务器等等,以获取更好的系能。

 

 

via: http://java.chinaitlab.com/JDBCJDO/18044.html

 

如果可能,避免访问数据库

  ·  为应用选择最好最快的 JDBC 驱动 ,参考本站文章 。 JDBC3.0提供了新的特性来提高性能,诸如连接池, statemente池的改进  

  · 对数据库使用连接池并且重用连接,而不要重复打开和关闭连接。最佳的连接池大小是当连接池大到足够使服务请求不等待 

  ·  尽量使用支持 JDBC3.0 的驱动,因为 JDBC3.0 支持包括 DataSource 对象,连接池,分布式事务支持, RowSets 和 prepared statement 池等性能增强特性

  ·  Prepared statement 池(自从 JDBC3.0 开始有)高速缓存已经预先优化并运行了的 SQL 查询,这样,他们被再次请求的时候,不必经历再次的优化预处理(避免最优化步骤,诸如检查语法,验证地址,优化访问路径和执行计划)。 Statement 池是一个很好的,重要的性能优化方法

  ·  JDBC3.0 中的 Statement 池和连接池能合作共享 statement 池,这样,能使用一个已高速缓存的 statement (该 statement 来自另外一个连接)的连接,在由任一连接执行的 一些SQL 首次被执行时,产生的 statement 准备开销仅一次

  ·  RowSet对象与 ResultSet 对象相似,但是能提供当断开连接的时候对数据库数据的访问。这允许数据以它最简单的形式被高效的高速缓存

  ·  用同一个连接执行多个 statements

  ·  关闭 autocommit ,但不要让事务打开太久

  ·  避免将事务分布开(事务跨越多个连接)

  ·  最小化数据库的行和列数据获取。使用 setMaxRows, setMaxFieldSize,和 SetFetchSize

  ·  使用最高效的数据类型:字符串比整数型快,整数型比浮点类型和时间戳类型都要高效(是否不太理解^&^,这是针对DB2数据库处理来说的,处理character类型最快,而处理integer类型通常需要一些转换或者字节排序)

  ·  使用 updateXXX()方法更新: updateXXX() 在可更新的结果集上调用。结果集已经定位到了一行 , 因此当使用一个 UPDATE statement 时,可以消除通常的查找要更新的数据行的开销

  ·  Cache任何请求的元数据( metadata )并尽可能少的使用元数据 方法,其慢的程度一用便知

  ·  避免在元数据 查询中使用 null 参数

  ·  使用虚拟查询获得一行的元数据,不要使用getcolumns()(假如应用允许用户使用列数据,应用是使用getColumns来返回列的信息给用户还是准备一个虚拟查询而后调用getMetadata呢?

  ·  使用存储过程,避免多余的网络传输

  ·  在存储过程中使用参量,不要将数据挨个地放在statement中,最小化解析开销。此条针对DB2来说,其它数据库未必适用。SQL总是以字符串形式发送给DB2数据库,例如:

  CallableStatement cstmt = conn.prepareCall ("call getCustName (12345)");

  ResultSet rs = cstmt.executeQuery ();

  DB2服务器必须解析该SQL,验证参量类型,并将参量转化为正确的数据类型。

  ·  对需要重复执行的statement使用预处理statement(PreparedStatement)

  ·  选择使用最佳游标:对连续读取使用游标;对双向滚动使用游标。对仅返回一行的查询避免使用游标。

  ·  在JVM中Cache频繁请求的数据,避免不必要的数据库请求

  ·  采用预读取机制, 批量取行,而不要一次一行 。调整批大小和预取行的数量。避免使用预取 BLOB 数据。

  ·  除非绝对需要,否则避免移动数据

  ·  在数据穿过网络之前要使流化数据( Streamline data )

  ·  避免每次处理一行,尽可能一起处理多行。

  ·  在表中统计个数(例如:使用 select count(*) from myTable,yourTable where …)属于资源密集型的。试试首先选入临时表,仅返回该计数(count),然后发送精确的二次查询获得临时表中的行的子集。

  ·  恰当的使用 SQL 能减少资源请求。使用返回所需数据的最小值的查询:避免 select * 查询。一个返回小的数据子集的复杂查询,比一个简单的,返回超过所需的大量数据的简单查询更高效。

  ·  使你的查询尽可能精巧,例如:尽可能精确地最小化要传输的数据,使其是所需的子集

  ·  努力批量更新:将 statement 收集到一起,然后在一个事务里面一起执行。如果可能,使用有条件的逻辑和临时变量来达到 statement 批处理

  ·  永远不要让 DBMS 事务跨越用户输入

  ·  考虑使用乐观锁。乐观锁使用时间戳验证数据是否还没有被其他用户改变,否则事务失败

  ·  使用 恰当的更新,例如:更新行/表中已经存在的数据,而不要添加或者删除行/表。在适当的位置更新数据要比移动数据快得多,如果更新需要的空间比表设计能提供的更多,这可能是需要的。如果你设计的行需要空间初始化,更新将会更快。交易是你的表可能需要更多的磁盘空间,但可能速度更快。由于磁盘空间是便宜的,使用一点点能提高性能,这应该说是非常有价值的投资

  ·  分开存储正在操作的数据和历史数据(更一般的情况是将频繁使用的数据和不常使用的数据分开存储)

  ·  尽可能小的保留你的操作数据集,避免必须读那些不相关的数据

  ·  DBMS可以很好的并行运转,尽量将应用设计成当和 DBMS交互时应用能做其他事情。

  ·  使用流水线操作和并行操作。 将应用设计成支持大量并行进程, 使应用运行更快。如果要处理多步,努力设计好应用,以使后来的步骤能够在任何优先的进程已经完成的数据部分上开始工作,而不是必须等到优先进程完成

  · 事物的保护级别越高,性能损失就越大。事物级别按增长的顺序为: TRANSACTION_NONE, TRANSACTION_READ_UNCOMMITTED, TRANSACTION_READ_COMMITTED, TRANSACTION_REPEATABLE_READ, TRANSACTION_SERIALIZABLE。使用Connection.setTransactionIsolation() 设置你想要的事物级别

  · 默认的自动提交模式由于使每一个数据库命令都成为一个单独的事务,这会严重影响性能,关闭自动提交(Connection.setAutoCommit(false) ),明确声明事务

  ·  通过整合多个事务为一个的批量操作,并在一个statement中使用Statement.addBatch() 和Statement.executeBatch()

  · Savepoints (from JDBC3.0)需要昂贵的资源。一旦不再需要,就立刻使用Connection.releaseSavepoint()释放掉Savepoints

  ·  ConnectionPoolDataSource (from JDBC3.0)和PooledConnection接口为连接池提供了built-in支持

  · 使用setLogWriter() (from Driver, DataSource, or ConnectionPooledDataSource; from JDBC3.0) 帮助跟踪JDBC流

  · 使用Connection.setReadOnly(true)优化只读数据库(操作)交互

  · 使用Connection.nativeSQL()察看SQL查询如何在数据库种执行,帮助确保SQL已被优化

  ·切记:一旦可能,立刻关闭Statement和ResultSet

  ·使用DatabaseMetaData获得数据库功能性信息

  ·一直捕捉和处理数据库警告和异常

  ·使用最恰当的数据类型明确数据的类型,例如:以date类型存储日期,儿不要用varchar

  ·使用可滚动ResultSet (JDBC 2.0)

分享到:
评论
发表评论

文章已被作者锁定,不允许评论。

相关推荐

    Access_JDBC30.jar

    Microsoft Access作为一个广泛使用的数据库管理系统,其JDBC驱动程序为Java开发者提供了与Access数据库交互的桥梁。然而,原始的JDBC驱动可能会遇到一些限制和问题,比如查询次数和返回行数的约束,以及执行方法可能...

    (java)JDBC_example.rar_JDBC例子_jdbc_jdbc Java

    - JDBC操作数据库的性能相对较低,对于大量数据操作,应考虑优化策略。 总的来说,这个压缩包提供了一个学习和实践JDBC的起点,通过阅读和运行这些示例代码,可以更好地理解JDBC的工作原理和使用方式。对于Java...

    java_database_programming_with_jdbc.rar_java programming

    通过阅读"java_database_programming_with_jdbc.pdf"这份资料,你将能够学习到如何配置JDBC驱动、创建数据库连接、编写SQL语句、处理结果集、管理事务以及优化JDBC代码。同时,这份文档也可能涵盖了高级话题,如JDBC...

    JAVA_JDBC面向对象分页(初步设计二之oracle)

    在Java编程中,JDBC(Java Database Connectivity)是用于与数据库交互的标准API,它使得Java开发者能够连接到各种类型的数据库并执行SQL语句。在处理大量数据时,分页查询是一种有效的策略,可以提高应用程序的性能...

    Java_JDBC由浅入深

    14.2 数据库连接池优化 77 14.2.1 对线程池加锁 77 14.2.2 连接不够用时抛出异常 77 14.3 数据库连接池之代理模式 78 14.3.1 静态代理 78 14.3.2 动态代理 84 14.4 DBCP数据库连接池的使用 87 第十五节 jdbc轻量级...

    Access_jdbc30.jar

    标题中的"Access_jdbc30.jar"是一个专用于Java应用程序通过JDBC(Java Database Connectivity)接口连接Microsoft Access数据库的驱动程序。这个特定的版本(jdbc30)表明它遵循JDBC 3.0规范,该规范是Java 2平台...

    java基于jdbc界面.zip_jdbc_sitbu3

    综上所述,"java基于jdbc界面.zip_jdbc_sitbu3"这个项目是一个通过图形用户界面(GUI)利用JDBC与数据库交互的应用,涵盖了数据库连接、SQL执行、结果处理、事务控制、异常处理以及可能的性能优化策略。对于学习和...

    Java_JDBC学习教程 由浅入深.doc

    ### Java JDBC 学习教程知识点总结 #### 一、JDBC 概念及与应用程序的关系 **2.1 JDBC 概念** - JDBC (Java Database Connectivity) 是 Java 平台上的标准数据库访问接口,用于执行 SQL 语句并处理结果。 - 它提供...

    000_动力节点_JDBC_源码.rar_java_jpg_noonnk4_roomqyf_动力节点源码

    - 数据库连接池的配置和管理,理解其工作原理和优化策略。 通过深入研究这些源码,你可以更好地掌握JDBC的实战应用,并提升数据库操作的技能。此外,动力节点的课程通常会涵盖这些内容,通过视频教程结合源码,...

    impala_jdbc.zip

    而Impala JDBC(Java Database Connectivity)驱动则是连接Impala与各种编程语言的桥梁,使得开发者可以利用Java或支持JDBC的任何其他语言与Impala交互。 Impala JDBC驱动是基于Java API设计的,允许Java应用程序...

    jsp_servlet_jdbc登陆实例

    在IT行业中,`jsp_servlet_jdbc` 是Java Web开发中的核心技术栈,它们共同构建了动态网站应用程序。本文将深入探讨这些技术以及如何利用它们实现一个Oracle数据库的登陆实例。 首先,`JSP(JavaServer Pages)`是...

    spring_mysql_jdbc

    这涉及到数据库连接池的配置、事务管理策略、SQL查询优化以及错误处理等方面的知识。 综上所述,"spring_mysql_jdbc"主题涵盖了Spring框架的JDBC支持,MySQL的JDBC驱动程序,以及它们如何协同工作以实现高效、可靠...

    2-JSP_JDBC_真分页

    综上所述,“2-JSP_JDBC_真分页”这个资源可能包含以下内容:JSP页面设计、JDBC连接MySQL数据库的代码示例、使用LIMIT和OFFSET实现分页的SQL查询、前端分页UI的实现、以及可能的性能优化策略。通过学习和实践这些...

    JDBC笔记_JDBC学习笔记_

    四、JDBC优化 1. 使用PreparedStatement代替Statement,减少解析时间,提高效率。 2. 使用连接池:例如C3P0、DBCP、HikariCP等,避免频繁创建和销毁数据库连接。 3. 批量处理:尽量将多条SQL语句一起执行,减少...

    MySQL_JDBC.zip

    此外,还可能涉及优化JDBC性能的策略,如批处理和连接池的使用。 学习这部分内容对于Java开发者来说至关重要,因为数据库操作是大多数Web应用程序的核心部分。理解并熟练掌握JDBC和MySQL的结合使用,能够帮助你构建...

    JDBC.rar_java jdbc mysql

    通过以上知识点,我们掌握了如何使用Java JDBC与MySQL数据库进行交互的基本步骤和技巧,包括连接数据库、执行SQL、处理结果、事务控制、批处理以及性能优化等。这为开发基于Java的数据驱动应用程序奠定了坚实的基础...

    java_database.rar_JAVA数据库_database java_数据库

    通过使用PreparedStatement、预编译SQL、合理的索引策略、批量操作和连接池,可以显著提升Java数据库应用的性能。 以上就是“java_database.rar”资料包中涉及的主要Java数据库相关知识点。学习和掌握这些内容,将...

    Java_C3P0_ConnectionPool.rar_C3P0_c3p0 ja_connection pool jdbc_j

    6. **性能优化**:C3P0提供了一些性能优化选项,比如预热连接,即在启动时就尝试创建一部分连接,避免首次使用时的延迟。 7. **异常处理**:C3P0具有良好的异常处理机制,可以捕获并处理各种数据库连接问题,如连接...

    SQL.rar_java sql_java sql查询_query optimization_sql_sql优化

    以下是一些常见的SQL优化策略: 1. **查询语句优化**:避免使用全表扫描,尽可能利用索引。这通常意味着在WHERE子句中使用索引字段,而不是在SELECT或ORDER BY子句中。此外,减少JOIN操作的数量和复杂性也能提升...

    java_art_for_web.rar_java web_java英文_web java

    6. **JDBC与数据库交互**:介绍如何使用Java进行数据库连接,执行SQL语句,以及事务管理。 7. **Web服务**:讲解如何用Java创建RESTful API,以及使用JSON或XML进行数据交换。 8. **安全实践**:讨论Web应用的安全...

Global site tag (gtag.js) - Google Analytics