[转帖]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,这过程有点像程序编译,检查语法.表名.字 ...
随机推荐
- P3537 [POI2012]SZA-Cloakroom 题解
题目大意 有 \(n\) 件物品,每件物品有三个属性 \(a_i, b_i, c_i (a_i < b_i)\). 再给出 \(q\) 个询问,每个询问由非负整数 \(m, k, s\)组成,问 ...
- 通用 Mapper 的批量插入实现
具体的 SQL 模板实现如下所示: import org.apache.ibatis.mapping.MappedStatement; import tk.mybatis.mapper.MapperE ...
- 全网最全的华为ensp数通设备命令全集
[命令] display history-command [视图]所有视图 [参数]无 [描述] display history-command 命令用来显示当 前用户曾键入的最后 10 条命令.用户 ...
- Spring系列:基于注解的方式构建IOC
目录 一.搭建子模块spring6-ioc-annotation 二.添加配置类 三.使用注解定义 Bean 四.@Autowired注入 五.@Resource注入 六.全部代码 从 Java 5 ...
- Microsoft Docs & Learn Champion 冠军赛
2021年个人作为微软MVP,参与了Microsoft Docs & Learn Champion 冠军赛,经过一年的努力,全面宣传了微软的技术. 以下是Microsoft Docs & ...
- 数据库开发实战教程:使用Python连接Kerberos的Presto
[摘要]本文将为大家带来Python连接presto开源的两个实践案例. Python连接presto开源提供了以下两个库可以使用 presto-python-client:https://githu ...
- 华为云HBase冷热分离最佳实践
本文分享自华为云社区<华为云HBase 冷热分离最佳实践>,作者:pippo. HBase介绍 HBase是Hadoop Database的简称,是建立在Hadoop文件系统之上的分布式面 ...
- CANN 6.0来了,硬核技术抢先看
摘要:在华为全联接大会2022期间,华为正式官宣昇腾AI异构计算架构CANN 6.0版本将在年底正式发布. 本文分享自华为云社区<昇腾AI异构计算架构CANN 6.0全新开放升级,全面释放AI生 ...
- VEGA:诺亚AutoML高性能开源算法集简介
摘要:VEGA是华为诺亚方舟实验室自研的全流程AutoML算法集合,提供架构搜索.超参优化.数据增强.模型压缩等全流程机器学习自动化基础能力. 本文分享自华为云社区<VEGA:诺亚AutoML高 ...
- 抓包工具 Fiddler 抓取 exe 包
浏览器访问网页,可以使用 Fiddler 直接抓去,如果是 exe的客户端,可以借助 Proxifier 工具 设置完成后,添加代理规则,排除fiddler,也就是让fiddler进行网络直连.不然f ...