近期为了解决一些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:
|
相关推荐
此实例意在解决预处理命令PreparedStatement的setString()方法,在sql2008数据库中写入数据时,会自动补足空格的问题, 同时此实例也解决了当存在自动补足空格的问题时,使用nvarchar可以使查找出来的数据与原输入...
JDBC 中 PreparedStatement 接口提供的 execute、executeQuery 和 executeUpdate 之间的区别及用法 JDBC 中的 PreparedStatement 接口提供了三种执行 SQL 语句的方法:executeQuery、executeUpdate 和 execute。...
在Java的数据库编程中,`JDBC PreparedStatement`和连接池中的`PreparedStatement Cache`是两个非常重要的概念,它们对于提升应用程序的性能和效率有着显著的作用。本文将深入探讨这两个主题,并结合Oracle数据库的...
本教程将详细介绍如何使用JDBC连接SQL Server 2000/2005和Oracle 10g数据库。 首先,让我们了解JDBC连接的基本步骤: 1. **加载驱动**:在Java程序中,我们需要加载对应的数据库驱动。例如,对于SQL Server,我们...
`PreparedStatement`是Java数据库连接(JDBC)API中的一种重要接口,它继承自`Statement`接口,并在其基础上进行了扩展和优化。`PreparedStatement`的主要特点在于它可以预先编译SQL语句,并允许用户在执行前动态地...
在Java的JDBC编程中,`PreparedStatement`是一个非常重要的接口,它用于预编译SQL语句,提高了数据库操作的效率和安全性。当我们处理大量重复的SQL操作时,使用`PreparedStatement`可以避免SQL注入等问题,同时提升...
在Java应用程序中,我们通常会使用Java Database Connectivity (JDBC) API来连接和操作数据库,而`DmJdbcDriver18.jar`就是达梦8数据库的JDBC驱动包,用于Java程序与达梦数据库之间的通信。 **JDBC简介** JDBC是...
为了提高SQL语句的执行效率和安全性,JDBC提供了`PreparedStatement`和`CallableStatement`两种特殊的`Statement`子类。`PreparedStatement`可以预编译SQL语句,减少解析时间,并防止SQL注入攻击;`...
此外,JDBC还提供了Statement和PreparedStatement两种方式执行SQL。PreparedStatement可以防止SQL注入攻击,并且可以提高性能,因为它可以被预编译。 在展示查询结果时,可以使用JSP的迭代标签`<c:forEach>`配合...
java.sql.PreparedStatement psta=null; //连接jdbc驱动,获取连接对象(connection) try { //先写好sql语句 String sqlstr="delete from test_user where username=?"; //生成statement...
### Connection 和 PreparedStatement 的关闭问题 在Java编程语言中,处理数据库连接及执行SQL语句时,合理地管理和释放资源是非常重要的。本文将详细介绍`Connection`和`PreparedStatement`的使用时机与关闭策略,...
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是一款源自中国人民大学的国产关系型数据库管理系统,以其高效稳定、安全可靠的特点在业界享有较高声誉。在Java编程中,JDBC(Java Database Connectivity)是连接数据库的标准接口,它允许Java应用...
Sybase ASE(Adaptive Server Enterprise)是一款高性能的关系型数据库管理系统,广泛应用于企业级的数据存储和管理。在Java应用程序中,为了与Sybase ASE数据库进行交互,开发者通常会使用JDBC(Java Database ...
它提供了一种标准化的方式来访问关系型数据库,使得开发人员无需关心具体的数据库实现细节,就能完成数据的增删查改操作。在本场景中,我们讨论的是如何使用JDBC连接MySQL数据库。 首先,为了使用JDBC连接MySQL,...
SQLJDBC和SQLJDBC4是Microsoft为Java应用程序提供的用于连接SQL Server数据库的驱动程序。这两个版本都是JDBC(Java Database Connectivity)驱动,允许Java开发者在应用程序中与SQL Server进行交互。下面将详细介绍...
JDBC(Java Database Connectivity)是Java平台中的一个标准API,用于在Java应用程序和各种类型的数据库之间建立连接。它允许开发者执行SQL语句,处理结果集,以及进行事务管理。JDBC是Java SE的一部分,也是Java EE...
MySQL JDBC支持事务处理、预编译的SQL语句(PreparedStatement)以及结果集的滚动和分页。 2. **Oracle JDBC**: Oracle数据库是企业级的数据库系统,提供了强大的功能和高度的可扩展性。Oracle JDBC驱动分为 Thin...
在IT领域,Java Database Connectivity(JDBC)是Java平台中用于与关系数据库进行交互的一组标准API。JDBC提供了一种标准的接口,使得Java程序员能够以统一的方式处理不同的数据库系统,包括MSSQL(Microsoft SQL ...
jdbc中preparedStatement比Statement的好处