最新文章专题视频专题问答1问答10问答100问答1000问答2000关键字专题1关键字专题50关键字专题500关键字专题1500TAG最新视频文章推荐1 推荐3 推荐5 推荐7 推荐9 推荐11 推荐13 推荐15 推荐17 推荐19 推荐21 推荐23 推荐25 推荐27 推荐29 推荐31 推荐33 推荐35 推荐37视频文章20视频文章30视频文章40视频文章50视频文章60 视频文章70视频文章80视频文章90视频文章100视频文章120视频文章140 视频2关键字专题关键字专题tag2tag3文章专题文章专题2文章索引1文章索引2文章索引3文章索引4文章索引5123456789101112131415文章专题3
当前位置: 首页 - 科技 - 知识百科 - 正文

jdbc测试mysql数据库sql预解析(绑定变量)

来源:动视网 责编:小采 时间:2020-11-09 08:07:23
文档

jdbc测试mysql数据库sql预解析(绑定变量)

jdbc测试mysql数据库sql预解析(绑定变量):jdbc测试mysql数据库sql预解析(绑定变量) 用习惯了oracle,学习mysql,想测试一下mysql绑定变量的效果。以前看网上介绍大部份都说mysql没有sql共享池的概念,所以也不存在sql预解析或绑定变量的说法。 今天测试了一下(通过网络抓包、查看服务器端sql日志
推荐度:
导读jdbc测试mysql数据库sql预解析(绑定变量):jdbc测试mysql数据库sql预解析(绑定变量) 用习惯了oracle,学习mysql,想测试一下mysql绑定变量的效果。以前看网上介绍大部份都说mysql没有sql共享池的概念,所以也不存在sql预解析或绑定变量的说法。 今天测试了一下(通过网络抓包、查看服务器端sql日志


jdbc测试mysql数据库sql预解析(绑定变量) 用习惯了oracle,学习mysql,想测试一下mysql绑定变量的效果。以前看网上介绍大部份都说mysql没有sql共享池的概念,所以也不存在sql预解析或绑定变量的说法。 今天测试了一下(通过网络抓包、查看服务器端sql日志及

jdbc测试mysql数据库sql预解析(绑定变量)

用习惯了oracle,学习mysql,想测试一下mysql绑定变量的效果。以前看网上介绍大部份都说mysql没有sql共享池的概念,所以也不存在sql预解析或绑定变量的说法。
今天测试了一下(通过网络抓包、查看服务器端sql日志及分析源码等方法),发现mysql还是有sql预解析的实现。
服务器端是mysql 5.1.58(win32),用jdbc(5.1.18)做客户端,默认的连接方式是不会有sql预解析效果,即使我们用PreparedStatement对象也差不多,它只是把SQL和变量拼接成一个完整的SQL发送给服务器,如下代码:

PreparedStatement pstmt = conn.prepareStatement("select * from t1 where c1=?");
pstmt.setString(1, "abc");
pstmt.execute();

实际上不会有预解析的过程,而是经过简单的拼接,把如下SQL发送给服务器

select * from t1 where c1='abc'
要实现预解析的效果,我们必须设置jdbc Connection的参数useServerPrepStmts=true,再使用PreparedStatement后就OK了,创建PreparedStatement时客户端先把"select * from t1 where c1=?"发送到服务器端预解析,execute时只是把变量传送到服务器执行。

mysql服务器的sql语句缓存可以通过状态变量Prepared_stmt_count查看

mysql> show status like 'Prepared_stmt_count';
+---------------------+-------+
| Variable_name | Value |
+---------------------+-------+
| Prepared_stmt_count | 1 |
+---------------------+-------+
1 row in set

不过mysql的sql语句缓存与oracle有很大不同,它是会话语句级的,不是全局共享,当会话断开或PreparedStatement.close后这个缓存就没有了。我们需要设置Connection的参数cachePrepStmts=true把PreparedStatement缓存起来,prepStmtCacheSize=xxx来设置每个会话缓存语句的最大数量(很多连接池也有类似的功能)。

OK,已经知道如何启用预解析了,想看看启用与不启用预解析性能有多少差别,会不会也像oracle那么明显呢?经过简单的测试,发现当没有PreparedStatement缓存(cachePrepStmts=false)时,打开预解析性能下降很多, 当有PreparedStatement缓存(cachePrepStmts=true)时,两者性能基本一样。这个结果让人很失望,个人分析有几个原因:
启用预解析但没有PreparedStatement缓存时,每次创建PreparedStatement都需要解析一次,execute时又需要交互一次,而预解析的SQL在PreparedStatement.close又不能重用,所以性能反而更差。

当有PreparedStatement缓存时,预解析的SQL文本缓存在服务器端,但是并不会像oracle一样缓存执行计划,所以每次execute时都需要解析SQL和生成执行计划,因此只是减少了每次execute传输SQL的文本大小,性能差别不大。

注:如果SQL语法错误,那么服务器端预解析会出错,但jdbc收到预解析出错的信息后并不提示出错,而是将取消本条语句预解析的状态,execute时直接把SQL接装发送给服务器,mysql jdbc在PreparedStatement构造函数中代码如下,其中返回ServerPreparedStatement类表示使用了绑定变量,返回PreparedStatement表示未使用绑定变量:

try {
	pStmt = ServerPreparedStatement.getInstance(getLoadBalanceSafeProxy(), nativeSql,
	this.database, resultSetType, resultSetConcurrency);
	
	pStmt.setResultSetType(resultSetType);
	pStmt.setResultSetConcurrency(resultSetConcurrency);
} catch (SQLException sqlEx) {
	// Punt, if necessary
	if (getEmulateUnsupportedPstmts()) {
	pStmt = (PreparedStatement) clientPrepareStatement(nativeSql, resultSetType, resultSetConcurrency, false);
	} else {
	throw sqlEx;
	}
}
经过上面分析,个人认为不需要打开SQL预解析的效果,PreparedStatement对象还是尽量使用,因为虽然不能提升性能,但可以避免SQL注入安全问题 。
2012-02-17

文档

jdbc测试mysql数据库sql预解析(绑定变量)

jdbc测试mysql数据库sql预解析(绑定变量):jdbc测试mysql数据库sql预解析(绑定变量) 用习惯了oracle,学习mysql,想测试一下mysql绑定变量的效果。以前看网上介绍大部份都说mysql没有sql共享池的概念,所以也不存在sql预解析或绑定变量的说法。 今天测试了一下(通过网络抓包、查看服务器端sql日志
推荐度:
标签: 绑定 测试 数据库
  • 热门焦点

最新推荐

猜你喜欢

热门推荐

专题
Top