`

JDBC PreparedStatement的Performance问题,setString 和 varchar/nvarchar的关系

阅读更多

近期为了解决一些security的问题,把DAO层JDBC的Statement全部替换为PreparedStatement,然后遇到一个非常奇怪的问题是,一个简单的SQL, 比如

SELECT * FROM MDC_DATA_TYPE WHERE name = 'A' AND number = 1;

改成使用SELECT * FROM MDC_DATA_TYPE WHERE name = ? AND number = ?之后,执行时间几乎慢了100倍,这几乎与业界推荐使用PreparedStatement的事实背道而驰。于是花了很多时间来找原因。

 

后来找了曾在微软做SQL Server TCS的同事帮忙看,果然是高手,查看了执行计划 (Execution Plan),这里我留一些备忘:

select spid,status,hostname,program_name,text from sys.sysprocesses p
cross apply sys.dm_exec_sql_text(p.sql_handle) t
where spid>50 and program_name like 'JSQL%'
and program_name like 'JSQL%'
order by spid


select * from sys.dm_exec_requests r
cross apply sys.dm_exec_sql_text(r.sql_handle)
where session_id>50



dbcc freeproccache
dbcc freesystemcache('All')
dbcc dropcleanbuffers
dbcc freeproccache

kill 102

select * from sys.dm_exec_quests

 

// 下面这个是找到找到问题的SQL
select * from sys.dm_exec_cached_plans p
cross apply sys.dm_exec_sql_text(p.plan_handle)
cross apply sys.dm_exec_query_plan(p.plan_handle)

 

可以看到SQLServer缓存的sql:
(@P0 nvarchar(4000),@P1 int,@P2 nvarchar(4000))SELECT * FROM MDC_DATA_TYPE WHERE rmname = @P0 AND numPeriods = @P1 AND periodUnit = @P2 

 

根本原因:

http://www.newatlanta.com/c/support/servletexec/self_help/faq/detail?faqId=183

PreparedStatement.setString() performs more slowly than PreparedStatement.setBytes(). Why?

 

  This can occur when the SQL Server data type of your table's column is different than the type being used in your query.

For example, say you have a table in your SQL Server database with a column of type char or varchar, and the query in your Java code looks like this:
"SELECT * from mytable where mytext = ?"
If you use pstmt.setString(1, "99"); in your Java code, then JTurbo inserts the parameter and builds the query using 'N' like this:
... where mytext = N'99'
This forces SQL Server to do a conversion from nvarchar to the type of your table's column (char or varchar).
A conversion like this is expensive.
If you use pstmt.setBytes(1, "99".getBytes("8859_1")); in your Java code, then JTurbo inserts the parameter and builds the query like this:
... where mytext = 0x3939
which does not require a type conversion within SQL Server.
The only way that JTurbo's PreparedStatement could avoid prepending the 'N' would be if it were to first ask SQL Server whether or not the column type was nchar, nvarchar, or ntext. Asking this for every sql query it builds could be very expensive.

Our recommendation is that you change your database column type to be one of the 'n' types:
  • nchar
  • nvarchar
  • ntext
  • 大小: 71.9 KB
分享到:
评论

相关推荐

    使用PreparedStatement的setString方法会自动在varchar后面补空格

    此实例意在解决预处理命令PreparedStatement的setString()方法,在sql2008数据库中写入数据时,会自动补足空格的问题, 同时此实例也解决了当存在自动补足空格的问题时,使用nvarchar可以使查找出来的数据与原输入...

    JDBC中PreparedStatement接口提供的execute、executeQuery和executeUpdate之间的区别及用法

    JDBC 中 PreparedStatement 接口提供的 execute、executeQuery 和 executeUpdate 之间的区别及用法 JDBC 中的 PreparedStatement 接口提供了三种执行 SQL 语句的方法:executeQuery、executeUpdate 和 execute。...

    【性能】JDBC PreparedStatement和连接池PreparedStatement Cache学习记录

    在Java的数据库编程中,`JDBC PreparedStatement`和连接池中的`PreparedStatement Cache`是两个非常重要的概念,它们对于提升应用程序的性能和效率有着显著的作用。本文将深入探讨这两个主题,并结合Oracle数据库的...

    jdbc连接实例(sqlserver 2000/2005、 oracle 10g)

    本教程将详细介绍如何使用JDBC连接SQL Server 2000/2005和Oracle 10g数据库。 首先,让我们了解JDBC连接的基本步骤: 1. **加载驱动**:在Java程序中,我们需要加载对应的数据库驱动。例如,对于SQL Server,我们...

    JDBC基础教程之PreparedStatement.doc

    `PreparedStatement`是Java数据库连接(JDBC)API中的一种重要接口,它继承自`Statement`接口,并在其基础上进行了扩展和优化。`PreparedStatement`的主要特点在于它可以预先编译SQL语句,并允许用户在执行前动态地...

    达梦8数据库驱动-jdbc

    在Java应用程序中,我们通常会使用Java Database Connectivity (JDBC) API来连接和操作数据库,而`DmJdbcDriver18.jar`就是达梦8数据库的JDBC驱动包,用于Java程序与达梦数据库之间的通信。 **JDBC简介** JDBC是...

    JDBC.pdf

    为了提高SQL语句的执行效率和安全性,JDBC提供了`PreparedStatement`和`CallableStatement`两种特殊的`Statement`子类。`PreparedStatement`可以预编译SQL语句,减少解析时间,并防止SQL注入攻击;`...

    JDBC+JSP实例

    此外,JDBC还提供了Statement和PreparedStatement两种方式执行SQL。PreparedStatement可以防止SQL注入攻击,并且可以提高性能,因为它可以被预编译。 在展示查询结果时,可以使用JSP的迭代标签`<c:forEach>`配合...

    2014_05_12 javabean类型的辅助类存储传输接收数据.

    java.sql.PreparedStatement psta=null; //连接jdbc驱动,获取连接对象(connection) try { //先写好sql语句 String sqlstr="delete from test_user where username=?"; //生成statement...

    connection 和 preparedstatement 的关闭问题

    ### Connection 和 PreparedStatement 的关闭问题 在Java编程语言中,处理数据库连接及执行SQL语句时,合理地管理和释放资源是非常重要的。本文将详细介绍`Connection`和`PreparedStatement`的使用时机与关闭策略,...

    超市收银系统(java+jdbc)

    conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/jdbc?useSSL=false&serverTimezone=UTC", "root", "yw20010522"); // 准备 SQL 语句 String sql = "SELECT * FROM tl_user WHERE nuName=? AND ...

    人大金仓kingbase 驱动jdbc

    人大金仓Kingbase是一款源自中国人民大学的国产关系型数据库管理系统,以其高效稳定、安全可靠的特点在业界享有较高声誉。在Java编程中,JDBC(Java Database Connectivity)是连接数据库的标准接口,它允许Java应用...

    Sybase数据库JDBC驱动(包括2版和3版)

    Sybase ASE(Adaptive Server Enterprise)是一款高性能的关系型数据库管理系统,广泛应用于企业级的数据存储和管理。在Java应用程序中,为了与Sybase ASE数据库进行交互,开发者通常会使用JDBC(Java Database ...

    JDBC连接MySQL

    它提供了一种标准化的方式来访问关系型数据库,使得开发人员无需关心具体的数据库实现细节,就能完成数据的增删查改操作。在本场景中,我们讨论的是如何使用JDBC连接MySQL数据库。 首先,为了使用JDBC连接MySQL,...

    sqljdbc和sqljdbc4 sqlserver最新驱动

    SQLJDBC和SQLJDBC4是Microsoft为Java应用程序提供的用于连接SQL Server数据库的驱动程序。这两个版本都是JDBC(Java Database Connectivity)驱动,允许Java开发者在应用程序中与SQL Server进行交互。下面将详细介绍...

    jdbc教程_jdbc教程

    JDBC(Java Database Connectivity)是Java平台中的一个标准API,用于在Java应用程序和各种类型的数据库之间建立连接。它允许开发者执行SQL语句,处理结果集,以及进行事务管理。JDBC是Java SE的一部分,也是Java EE...

    各种数据库的jdbc(mysql,orcal ,derby,hive,postgresql,monetdb-jdbc)

    MySQL JDBC支持事务处理、预编译的SQL语句(PreparedStatement)以及结果集的滚动和分页。 2. **Oracle JDBC**: Oracle数据库是企业级的数据库系统,提供了强大的功能和高度的可扩展性。Oracle JDBC驱动分为 Thin...

    JDBC连接数据库驱动集合及JDBC语句(MSSQL,ORACLE,MYSQL)

    在IT领域,Java Database Connectivity(JDBC)是Java平台中用于与关系数据库进行交互的一组标准API。JDBC提供了一种标准的接口,使得Java程序员能够以统一的方式处理不同的数据库系统,包括MSSQL(Microsoft SQL ...

    34.jdbc中preparedStatement比Statement的好处.avi

    jdbc中preparedStatement比Statement的好处

    JDBC数据库连接测试

    - **CallableStatement**:用于调用数据库存储过程,其方法命名与PreparedStatement类似,但多了`registerOutParameter()`和`getXXX()`方法用于处理存储过程的输出参数。 ### 5. 数据库连接池 在实际开发中,为...

Global site tag (gtag.js) - Google Analytics