当前位置:网站首页>Use IN List Population in Your JDBC Application to Avoid Cursor Cache Contention Issues
Use IN List Population in Your JDBC Application to Avoid Cursor Cache Contention Issues
2022-07-31 12:09:00 【DebugUsery】
Few developers are aware of a problem,那就是在SQL中使用INmay be encountered when listing "cursor cache contention "或 "Execution plan cache contention "的问题.This problem is described in detail in a previous article,It can be summed up like this.
All of these are differentSQL查询,Need to have a strong plan cacheRDBMS(例如Db2、Oracle、SQL Server)中被解析/计划/Cached execution plans that may differ:
SELECT * FROM t WHERE id IN (?);
SELECT * FROM t WHERE id IN (?, ?);
SELECT * FROM t WHERE id IN (?, ?, ?);
SELECT * FROM t WHERE id IN (?, ?, ?, ?);
SELECT * FROM t WHERE id IN (?, ?, ?, ?, ?);
复制代码
Although this is on the developer machine不是 问题,But it will be generated in production重大 问题.我见过这种情况,during peak loads,整个OracleInstances are paralyzed.虽然RDBMSSuppliers should strive to avoid serious problems that could result from this,But you can use us injOOQInvented a trick to fix it(Hibernate现在也有).
IN 列表填充
这个技巧非常简单.只要将你的IN
列表 "填充 "到最接近的2
的幂数,Then repeat the last value,直到结束:
SELECT * FROM t WHERE id IN (?); -- Left as it is
SELECT * FROM t WHERE id IN (?, ?); -- Left as it is
SELECT * FROM t WHERE id IN (?, ?, ?, ?); -- Padded 3 to 4
SELECT * FROM t WHERE id IN (?, ?, ?, ?); -- Left as it is
SELECT * FROM t WHERE id IN (?, ?, ?, ?, ?, ?, ?, ?); -- Padded 5 to 8
复制代码
This is really a hack,There are better solutions to avoid this problem,包括使用数组或临时表,But your production system may be down,You need a quick fix.
从jOOQ 3.9(2016年底)开始,jOOQ已经支持IN
The list fills for years,But with relatively new parsers and ParsingConnection
,You can now also in your nonjOOQsystem to any arbitrarySQLQueries apply this technique.这里有一个简单的例子:
// Any arbitrary JDBC Connection is wrapped by jOOQ here and replaced
// by a "ParsingConnection", which is also a JDBC Connection
DSLContext ctx = DSL.using(connection);
ctx.settings().setInListPadding(true);
Connection c = ctx.parsingConnection();
// Your remaining code is left untouched. It is unaware of jOOQ
for (int i = 0; i < 10; i++) {
try (PreparedStatement s = c.prepareStatement(
// This alone is reason enough to use jOOQ instead,
// but one step at a time :)
"select 1 from dual where 1 in (" +
IntStream.rangeClosed(0, i)
.mapToObj(x -> "?")
.collect(Collectors.joining(", ")) +
")")
) {
for (int j = 0; j <= i; j++)
s.setInt(j + 1, j + 1);
try (ResultSet rs = s.executeQuery()) {
while (rs.next())
System.out.println(rs.getInt(1));
}
}
}
复制代码
The above example just builds and runs10a query of this form:
select 1 from dual where 1 in (?)
select 1 from dual where 1 in (?, ?)
select 1 from dual where 1 in (?, ?, ?)
select 1 from dual where 1 in (?, ?, ?, ?)
select 1 from dual where 1 in (?, ?, ?, ?, ?)
select 1 from dual where 1 in (?, ?, ?, ?, ?, ?)
select 1 from dual where 1 in (?, ?, ?, ?, ?, ?, ?)
select 1 from dual where 1 in (?, ?, ?, ?, ?, ?, ?, ?)
select 1 from dual where 1 in (?, ?, ?, ?, ?, ?, ?, ?, ?)
select 1 from dual where 1 in (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
复制代码
But that's not what is being executed.在DEBUG日志中,我们可以看到以下内容:
Translating from : select 1 from dual where 1 in (?)
Translating to : select 1 from dual where 1 in (?)
Translating from : select 1 from dual where 1 in (?, ?)
Translating to : select 1 from dual where 1 in (?, ?)
Translating from : select 1 from dual where 1 in (?, ?, ?)
Translating to : select 1 from dual where 1 in (?, ?, ?, ?)
Translating from : select 1 from dual where 1 in (?, ?, ?, ?)
Translating to : select 1 from dual where 1 in (?, ?, ?, ?)
Translating from : select 1 from dual where 1 in (?, ?, ?, ?, ?)
Translating to : select 1 from dual where 1 in (?, ?, ?, ?, ?, ?, ?, ?)
Translating from : select 1 from dual where 1 in (?, ?, ?, ?, ?, ?)
Translating to : select 1 from dual where 1 in (?, ?, ?, ?, ?, ?, ?, ?)
Translating from : select 1 from dual where 1 in (?, ?, ?, ?, ?, ?, ?)
Translating to : select 1 from dual where 1 in (?, ?, ?, ?, ?, ?, ?, ?)
Translating from : select 1 from dual where 1 in (?, ?, ?, ?, ?, ?, ?, ?)
Translating to : select 1 from dual where 1 in (?, ?, ?, ?, ?, ?, ?, ?)
Translating from : select 1 from dual where 1 in (?, ?, ?, ?, ?, ?, ?, ?, ?)
Translating to : select 1 from dual where 1 in (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
Translating from : select 1 from dual where 1 in (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
Translating to : select 1 from dual where 1 in (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
复制代码
就这样,Our legacy application is ready to run in production again,You will have time to address this more thoroughly.
结论
虽然jOOQMainly an interiorDSL,用于在JavaWrite type-safe embedded in SQL,But you can also base on anyJDBCuse it in many other applications.上面的例子是使用ParsingConnection
,It can parse all yoursSQL语句,and translate them/Convert to anything else,Including other dialects.
边栏推荐
猜你喜欢
MySQL面试八股文(2022最新整理)
荣耀手机参数写错,客服认为没错
Selenium自动化测试之Selenium IDE
IDEA configure method annotation automatic parameters
使用docker搭建mysql主从
学习爬虫之Scrapy框架学习(1)---Scrapy框架初学习及豆瓣top250电影信息获取的实战!
Full GC (Ergonomics)排查分析
DCM 中间件家族迎来新成员
Data Persistence Technology - MP
The item 'node.exe' was not recognized as the name of a cmdlet, function, script file, or runnable program.
随机推荐
数据持久化技术——MP
快速学完数据库管理
If the value of the enum map does not exist, deserialization is not performed
A40i/T3 uboot启动时对PMU部分初始化
JVS函数公式使用场景介绍
Experience innovation and iteration through the development of lucky draw mini-programs
Getting started with jmeter performance testing steps (performance testing tool jmeter)
数据湖(十九):SQL API 读取Kafka数据实时写入Iceberg表
带有对称约束切换线性系统的结构可控性
Chrome开发自定义右键菜单实现快速跳转到指定页面
关于==和equals的区别和联系,面试这么回答就可以
SAP Commerce Cloud Product Review 的添加逻辑
vb.net 画曲线
Comparison of ipv4 and ipv6 (IPV4)
SAP ABAP OData 服务如何支持 $filter (过滤)操作试读版
Exploring Plain Vision Transformer Backbones for Object Detection 论文阅读笔记
科学论文和学术论文写作
Json和对象之间转换的封装(Gson)
认知—运动康复医疗机器人应用设计
MySql模糊查询大全