PreparedStatementCache的意义
Oracle支持游标,一个PreparedStatement对应服务器一个游标,如果PreparedStatement被缓存起来重复执
行,PreparedStatement没有被关闭,服务器端的游标就不会被关闭,性能提高非常显著。在类似SELECT * FROM T WHERE
ID = ?这样的场景,性能可能是一个数量级的提升。
由于PreparedStatementCache性能提升明显,DruidDataSource、DBCP、JBossDataSource、WeblogicDataSource都实现了PreparedStatementCache。
PreparedStatementCache带来的问题
阿里巴巴在使用jboss连接池做PreparedStatementCache时,遇到了full gc频繁的问题。通过mat来分析jmap
dump的结果,发现T4CPreparedStatement占内存很多,出问题的几个项目,有的300M,有的500M,最夸张的900M。这些应用
都是用jboss连接池访问Oracle数据库,T4CPreparedStatement是Oracle JDBC
Driver的PreparedStatement一种实现。
oracle driver不是开源,通过逆向工程以及mat分析,发现其中占内存的是字段char[] defineChars,defineChars大小的计算公式是这样的:
defineChars大小 = rowSize * rowPrefetchCount
|
rowPrefetchCount在Oracle中,缺省值为10。
其中rowSize是执行查询设计的每一列的大小的和。计算公式是:
rowSize = col_1_size + col_2_size + ... + col_n_size
|
很悲剧,有些列数据类型是varchar2(4000),于是rowSize巨大,很多个表关联的SQL,rowSize可能高达数十K,再乘以
rowPrefetchCount,defineChars大小接近1M。可以想想,maxPoolSize设置为
30,PreparedStatementCacheSize设置为50的场景下,是可能导致PreparedStatementCache占据上G的内
存。
实际测试得到的结果如下:
varchar2(4000) |
col_size 4000 chars |
clob -> col_size |
col_size 4000 bytes |
实际占据内存的公式:
占据内存大小峰值 = defineChars大小 * PreparedStatementCacheSize * MaxPoolSize
|
我们实际分析,一个应用运行的SQL大约数百条,PreparedStatementCacheSize为
50,PreparedStatementCache的算法为LRU,很多的SQL执行之后,在Cache中HitCount为0就被淘汰了,淘汰的过
程,其位置从第1移到第50,这个漫长的过程导致了defineChars不能够被young gc回收。
Druid的解决方案
命中率低的SQL,不持有defineChars缓存。
OracleStatement提供了clearDefines方法,用于清理defineChars。DruidDataSource在
PreparedStatement加入Cache时,如果发现hitCount <
1,就调用clearDefines方法。通过这种方式,避免了命中率为0的PreparedStatement占用内存。测试表明,200个
SQL,PreparedStatementCacheSize为50的场景,能够减少一半的young gc。(生产环境还没做测试)
根据PreparedStatement执行的结果,计算RowPrefetch大小
添加PreparedStatementCache计数器
包括:
- PreparedStatementCacheCurrentSize
- PreparedStatementCacheDeleteCount 缓存删除次数
- PreparedStatementCacheHitCount 缓存命中次数
- PreparedStatementCacheMissCount 缓存不命中次数
- PreparedStatementCacheAccessCount 缓存访问次数
通过这五个计数器,我们清晰了解PreparedStatementCache的工作情况,然后根据实际情况调整。
分享到:
相关推荐
oracle数据库归档日志满问题解决方案.docx
Oracle 数据库多语言入库问题的解决方案 本文通过研究Oracle 数据库如何成功实现多语言入库,给出了一种实现多国语言信 息存储的基本方法,该方法解决了非中文语言入库时出现的乱码问题。随着企业在发展过程 中业务...
Oracle数据库操作常见错误及解决方案[借鉴].pdf
oracle数据库归档日志满问题解决方案[归类].pdf
Oracle数据库服务器IO高的分析方案.docx
oracle数据库中文乱码问题解决方案.docx
Oracle数据库课程设计医院系统数据库源代码。包含Java代码和SQL语句。源码中默认使用的数据库为运行的Oracle数据库 如需修改,在java源码/database.propertie中修改即可!Oracle数据库课程设计医院系统数据库源代码...
《Oracle 12c数据库基础教程》教学课件—03Oracle数据库管理工具.pdf《Oracle 12c数据库基础教程》教学课件—03Oracle数据库管理工具.pdf《Oracle 12c数据库基础教程》教学课件—03Oracle数据库管理工具.pdf《Oracle...
ORACLE数据库ORACLE数据库ORACLE数据库ORACLE数据库ORACLE数据库ORACLE数据库ORACLE数据库ORACLE数据库
Oracle数据库操作常见错误及解决方案.doc
Oracle数据库应用管理解决方案.rar
Oracle数据库多语言文字存储解决方案
很多常见错误以及详细的解决方案,非常适合刚接触Oracle的童鞋使用
Oracle数据库日常运维及应急故障处理手册 适合学习数据库的同学
ORACLE数据库迁移方案,单机迁移到rac
第二讲:Oracle实例中内存结构 第三讲:Oracle实例中后台进程管理 第四讲:Oracle数据数据文件管理 第五讲:Oracle数据库在线日志文件管理 第六讲:Oracle数据库归档日志文件管理 第七讲:Oracle数据库控制文件管理...
Oracle数据库字符集问题解决方案大全.doc,搜罗的一些关于Oracle数据库的汉字无法正常显示的解决方案。希望对于需要的朋友有用。
向Oracle数据库插入Clob大段文本解决方法
医院信息系统ORACLE数据库升级解决方案.pdf
本文档主要是解决Oracle数据库使用过程中,经常出现的SID无法识别问题的一个解决方案。