当前位置:网站首页>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.
边栏推荐
- busybox之reboot命令流程分析
- ESP8266-Arduino编程实例-MCP9808数字温度传感器驱动
- 这款悄然崛起的国产API接口管理工具,你一定要晓得
- In Excel using ODBC consumer SAP ABAP CDS view
- 认知—运动康复医疗机器人应用设计
- 学习笔记 Golang 写入文件(io.WriteString、ioutil.WriteFile、file.Write、write.WriteString)
- 快速学完数据库管理
- 立方体IV(暑假每日一题 10)
- Obsidian设置图床
- Life is endless, there are more questions, simple questions to learn knowledge points
猜你喜欢
随机推荐
在 Excel 内使用 ODBC 消费 SAP ABAP CDS view
纷享销客罗旭对话元气森林黄晓枫:零售数字化的终点不是创新,而是数据
建情人节表白网站(超详细过程,包教包会)
apisix-Getting Started
学习笔记 Golang 写入文件(io.WriteString、ioutil.WriteFile、file.Write、write.WriteString)
Structural controllability of switched linear systems with symmetry constraints
Qt鼠标穿透
使用 Excel 读取 SAP ABAP CDS View 通过 ODBC 暴露出来的数据
Getting started with jmeter performance testing steps (performance testing tool jmeter)
St. Regis Takeaway Project: New dishes and dishes paged query
Redis学习笔记-3.慢查询和其他高级数据结构
Life is endless, there are more questions, simple questions to learn knowledge points
kubernetes之服务发现
am335x 看门狗驱动&看门狗应用例程序
SAP Commerce Cloud Product Review 的添加逻辑
最近两个月谷歌 ad 掉的厉害
In Excel using ODBC consumer SAP ABAP CDS view
JVS轻应用的组成与配置
ESP8266-Arduino编程实例-MCP9808数字温度传感器驱动
Obsidian设置图床









