[转帖]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,这过程有点像程序编译,检查语法.表名.字 ...
随机推荐
- shiro基于角色URL进行鉴权
前言 shiro基于URL进行鉴权,网上有很多,但是多数都是copy不排版,眼睛都看花了,还不如自己看看源码. 2021年1月14日21:23:49最新的shiro是1.7,使用时发现了首次访问的一个 ...
- Spring Batch 的基本使用
简介 A lightweight, comprehensive batch framework designed to enable the development of robust batch a ...
- PowerDotNet平台化软件架构设计与实现系列(17):PCRM个人用户管理平台
个人用户管理是业务系统中非常基础且重要的一个公共服务系统,我们写的绝大多数应用都和个人用户或会员有关,用户(会员)数据安全无小事,必须有一个完备的用户管理平台系统. 因为不同公司的主业务不同,个人用户 ...
- mac 编译php 7.2+扩展编译 的坑史(不是swoole的坑),php的一个坑,这个坑还没填满,问题根源还没有找到 !
目前网上找到的文章全是php 7.1,但是brew己经没有7.1了,最新是7.2,这让我怀疑是不是我的版本问题,导致swoole编译时总是编译不过去.后来发现任何扩展都编不过去,提示: Configu ...
- 列举GaussDB(DWS)常见的查询时索引失效场景
摘要:使用GaussDB(DWS)时,有时为了加快查询速度,需要对表建立索引.有时我们会遇到明明建立了索引,查询计划中却发现索引没有被使用的情况.本文将列举几种常见的场景和优化方法. 本文分享自华为云 ...
- Vue 应用程序性能优化:代码压缩、加密和混淆配置详解
简介在 Vue 应用程序的开发中,代码压缩.加密和混淆是优化应用程序性能和提高安全性的重要步骤. Vue CLI 是一个功能强大的开发工具,它提供了方便的配置选项来实现这些功能.本文将介绍如何使用 ...
- 火山引擎AB测试:企业产品优化主题分享在北京举办
更多技术交流.求职机会,欢迎关注字节跳动数据平台微信公众号,回复[1]进入官方交流群 近日,火山引擎数智平台在北京举办了"超话数据:企业产品优化分享"的活动.该活动邀请了火山引擎的 ...
- MongoDB 读写分离——MongoDB 安装
下载安装包:https://www.mongodb.com/try/download/community 同一台电脑装了两服务,所以下载zip包,单机服务 mis 安装方便些 解压并重命名. 4.2 ...
- TypeError: this.libOptions.parse is not a function
安装完node.js运行项目后,报错: TypeError: this.libOptions.parse is not a function at ESLint8Plugin.<anonymou ...
- Go--下载安装
下载包地址:https://go.dev/dl/ linux: 下载后上传实例解压 tar -xvf go1.19.8.linux-amd64.tar.gz -C /usr/local/ 创建工作目录 ...