[转帖]Oracle JDBC中的语句缓存
在Oracle数据库中,SQL解析有几种:
- 硬解析,过多的硬解析在系统中产生shared pool latch和library cache liatch争用,消耗过多的shared pool,使得系统不具有可伸缩性。
- 软解析,过多的软解析仍然可能会导致系统问题,特别是如果有少量的SQL高并发地进行软解析,会产生library cache latch或者是share方式的mutex争用。
- 软软解析,其实这也也属于软解析,与普通的软解析不同的是,软软解析的SQL会在会话的cached cursor中命中。
- 一次解析,多次执行,这是解析次数最少的方式,也是系统最具有可扩展性的方式。
那么在JAVA开发的应用中,怎么样才能实现上述第4种方式?如果是循环处理某种数据,这个比较容易实现。其实对于不是这种情况,Oracle也提供了很好的方式来实现这一点。下面是一个例子(例子代码文件为TestStmtCache.java)。
import java.sql.*;
import oracle.jdbc.driver.OracleConnection; public class TestStmtCache {
public static Connection getConnection() throws Exception {
String driver = "oracle.jdbc.driver.OracleDriver";
String url = "jdbc:oracle:thin:@localhost:1521:xj11g";
Class.forName(driver);
return DriverManager.getConnection(url, "test", "test");
} public static void main(String args[]) {
Connection conn = null;
try {
conn = getConnection();
conn.setAutoCommit(false);
((OracleConnection)conn).setStatementCacheSize(0);
for (int i=0; i <200; i++) {
testNoCache(conn);
}
((OracleConnection)conn).setStatementCacheSize(20);
((OracleConnection)conn).setImplicitCachingEnabled(true); for (int i=0; i <200; i++) {
testCache(conn);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
public static void testCache(Connection conn) {
PreparedStatement pstmt = null;
try {
pstmt = conn.prepareStatement("select /*cache_test1 */ * from t1 where rownum<=1");
pstmt.execute();
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
pstmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
} public static void testNoCache(Connection conn) {
PreparedStatement pstmt = null;
try {
pstmt = conn.prepareStatement("select /*nocache_test1 */ * from t1 where rownum<=1");
pstmt.execute();
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
pstmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
编译上述代码文件TestStmtCache.java,并运行:
E:\JavaCode>set CLASSPATH=.;ojdbc14.jar E:\JavaCode>d:\works\Java\jdk1.5.0_21\bin\javac TestStmtCache.java E:\JavaCode>d:\works\Java\jdk1.5.0_21\jre\bin\java TestStmtCache
在数据库中进行查询:
SYS@xj11g> select sql_id,parse_calls,executions,sql_text from v$sqlarea where sql_text like '%cache_test%' and sql_text not like '%v$%'; SQL_ID PARSE_CALLS EXECUTIONS SQL_TEXT
------------- ----------- ----------- ------------------------------------------------------------
3nbu9qp40ptjk 200 200 select /*nocache_test1 */ * from t1 where rownum< =1
47hja0fwmmb6c 1 200 select /*cache_test1 */ * from t1 where rownum<=1
可以看到,这两条SQL语句,都执行了200次,但是标记为"nocache_test1"的SQL没有进行语句缓存,其parse calls为200次,即解析了200次,其中一次是硬解析。而标记为"cache_test1"的SQL语句,使用了语句缓存,但是parse calls只有1次,即只有一次硬解析,执行了200次。这里关键的代码在于:
((OracleConnection)conn).setStatementCacheSize(20);
((OracleConnection)conn).setImplicitCachingEnabled(true);
上述第一行代码设置语句缓存大小,当然20比较偏小,对于比较大型的系统来说,设到200-300比较合适,不过这会耗用一定数量的JAVA内存。这个数值表示一个连接能够缓存多少语句。第二行代码是设置隐式打开语句缓存,也即自动会对PreparedStatement的SQL语句进行缓存。
那么,上述的方式无疑是比较简单的,但是这种方式有一个问题就是,缓存的利用效率可能不高,因为JAVA会将不常用的SQL语句也进行了缓存。Oracle的JDBC驱动也提供了一种手工控制的方式:
将测试代码中的第22行替换为:
((OracleConnection)conn).setExplicitCachingEnabled(true);
第40行替换为:
pstmt = ((OracleConnection)conn).getStatementWithKey ("cache_test1");
if (pstmt==null)
第46行替换为:
((OraclePreparedStatement)pstmt).closeWithKey ("cache_test1");
这样通过手工编码的方式控制哪些语句需要缓存,哪些不需要。
关于语句缓存(Statement Caching)可以参考Oracle在线文档:Statement and Result Set Caching
[转帖]Oracle JDBC中的语句缓存的更多相关文章
- oracle过程中动态语句实现
oracle过程中动态语句实现 一般的PL/SQL程序设计中,在DML和事务控制的语句中可以直接使用SQL,但是DDL语句及系统控制语句却不能在PL/SQL中直接使用,要想实现在PL/SQL中使用DD ...
- Oracle ------ SQLDeveloper中SQL语句格式化快捷键
Oracle SQL Developer中SQL语句格式化快捷键: 每次sql复制到SQL Developer面板的时候,格式老不对,而且看起来很不舒服,所有的sql都挤在一行完成. 这时我们可以全选 ...
- [转帖]关于Java中SQL语句的拼接规则
关于Java中SQL语句的拼接规则 自学demo 的时候遇到的问题 结果应该是 '"+e.getName()+"' 注意 一共有三组标点符号 (除去 方法函数后面的括号) 实现目标 ...
- jdbc中SQL语句拼接java变量
例如:String sql = "select * from user where username='" + username + "' and password =' ...
- 请问JDBC中IN语句怎么构建
用PreparedStatement 传多参数时,如果参数个数不确定,还想使用?参数避免sql注入,只有一个办法 根据传递的参数个数,拼接sql语句为 SELECT * FROM TABLE_A WH ...
- JDBC中SQL语句与变量的拼接
变量为 keyWords String sql = "select id from t_user order by id + '"+keyWords+"';";
- Oracle数据库编程:在JDBC中应用Oracle
9.在JDBC中应用Oracle: JDBC访问数据库基本步骤: 1.加载驱动 2.获取链接对象 3.创建SQL语句 4.提交S ...
- oracle 数据库中,应用程序里的连接探測语句的正确使用
oracle 数据库中,应用程序里的连接探測语句的正确使用 本文为原创文章.转载请注明出处:http://blog.csdn.net/msdnchina/article/details/3851376 ...
- 开发PL/SQL子程序和包及使用PL/SQL编写触发器、在JDBC中应用Oracle
1. 子程序的各个部分: 声明部分.可执行部分.异常处理部分(可选) 2.子程序的分类: A. 过程 - 执行某些操作 a. 创建过程的语法: CREATE [OR REPLACE] PROC ...
- 转:Oracle中SQL语句执行过程中
Oracle中SQL语句执行过程中,Oracle内部解析原理如下: 1.当一用户第一次提交一个SQL表达式时,Oracle会将这SQL进行Hard parse,这过程有点像程序编译,检查语法.表名.字 ...
随机推荐
- Dart 3.2 更新盘点
作者 / Kevin Moore 和 Michael Thomsen 我们隆重宣布推出 Dart 3.2,这一版本针对以下方面做出了改进: 新增了一项语言功能,可对私有 final 字段进行非空升级: ...
- Kafka 万字精讲|工作五年这些你都知道吗?
目录 前言 一.Kafka 简介 1.1 事件流平台 1.2 Kafka 主要概念和术语 1.3 Zookeeper 二.Kafka 集群搭建和使用 2.1 使用 Docker Compose 搭建 ...
- Terraform 的开源替代:OpenTofu 宣布 GA!
OpenTofu 社区于1月10日宣布 OpenTofu 项目 GA,这是 OpenTofu 的首个稳定版本(https://github.com/opentofu/opentofu/releases ...
- 斯坦福 UE4 C++ ActionRoguelike游戏实例教程 03.EQS初体验:从智障到智慧
斯坦福课程 UE4 C++ ActionRoguelike游戏实例教程 0.绪论 概述 本文章对应课程第十一章 43节.这篇文章会简单介绍EQS和实际上手使用,为AI添加更丰富的行为逻辑. 目录 初识 ...
- java中获取公网IP
package com.dashan.utils.iputils; import org.apache.commons.lang.StringUtils; import java.io.Buffere ...
- 昇腾携手OpenMMLab,支持海量算法仓库的昇腾AI推理部署
摘要:近日,昇腾AI联合上海人工智能实验室,正式实现OpenMMLab算法仓库在昇腾的异构计算架构CANN上的推理部署,目前相关代码已推入MMDeploy 0.10.0版本,并在GitHub正式发布. ...
- 新能源物流车行业如何服务升级?地上铁联合火山引擎VeDI“破题”
今年以来,克服种种不利因素影响,我国工业经济实现企稳回升,一些行业逆势而上,表现亮眼.尤其是新能源车行业,得益于技术创新与系列重大政策利好推动,在国内和国外市场均实现了快速增长,中国汽车工业协会最新统 ...
- 自然语言处理 Paddle NLP - 机器同传技术及应用-理论
基础 自然语言处理(NLP) 自然语言处理PaddleNLP-词向量应用展示 自然语言处理(NLP)-前预训练时代的自监督学习 自然语言处理PaddleNLP-预训练语言模型及应用 自然语言处理Pad ...
- Unable to find @SpringBootConfiguration, you need to use @ContextConfiguration or @SpringBootTest
test下的包名和java下的包名不一致会产生下面错误 java.lang.IllegalStateException: Unable to find a @SpringBootConfigurati ...
- python 解析字节码的相关方法
python代码被解释器执行时分为两步走: 一.python编译器将代码编译成字节码 二.python虚拟机执行字节码 由于这两步是一起的,所以在python编程中很少能看到字节码.但是想要提高代码效 ...