IN列表填充
适用于 ✅ 开源版 ✅ 专业版 ✅ 企业版
具有游标缓存/语句缓存的数据库(例如 Oracle、SQL Server、DB2 等)针对预处理语句的重用进行了高度优化。当客户端向服务器发送预处理语句时,服务器将转到缓存并查找是否已经存在先前计算的语句的执行计划(即 SQL 字符串)。这称为“软解析”(在 Oracle 中)。如果不存在,则即时计算执行计划。这称为“硬解析”(在 Oracle 中)。
在高吞吐量 OLTP 系统中,防止硬解析非常重要,因为在这些系统中,查询通常不是很复杂,但在短时间内会运行数百万次。使用绑定变量,这通常不是问题,但 IN 谓词除外,即使在使用绑定变量时,它也会生成不同的 SQL 字符串
-- All of these are different SQL statements: SELECT * FROM AUTHOR WHERE ID IN (?) SELECT * FROM AUTHOR WHERE ID IN (?, ?) SELECT * FROM AUTHOR WHERE ID IN (?, ?, ?) SELECT * FROM AUTHOR WHERE ID IN (?, ?, ?, ?) SELECT * FROM AUTHOR WHERE ID IN (?, ?, ?, ?, ?)
Java / jOOQ 开发人员可能不清楚这个问题,因为它们总是从同一个 jOOQ 语句生成
// All of these are the same jOOQ statement DSL.using(configuration) .select() .from(AUTHOR) .where(AUTHOR.ID.in(collection)) .fetch();
根据集合的可能大小,可能值得探索使用数组或临时表作为解决方法,或者重用首先生成 ID 集的原始查询(通过半连接)。但有时,这是不可能的。在这种情况下,用户可以选择第三种解决方法:启用 inListPadding
设置。如果启用,jOOQ 会将 IN
列表“填充”到长度为 2 的幂(可以使用 Settings.inListPadBase
配置)。因此,原始查询将如下所示
-- Original SELECT * FROM AUTHOR WHERE ID IN (?) SELECT * FROM AUTHOR WHERE ID IN (?, ?) SELECT * FROM AUTHOR WHERE ID IN (?, ?, ?) SELECT * FROM AUTHOR WHERE ID IN (?, ?, ?, ?) SELECT * FROM AUTHOR WHERE ID IN (?, ?, ?, ?, ?) SELECT * FROM AUTHOR WHERE ID IN (?, ?, ?, ?, ?, ?)
-- Padded SELECT * FROM AUTHOR WHERE ID IN (?) SELECT * FROM AUTHOR WHERE ID IN (?, ?) SELECT * FROM AUTHOR WHERE ID IN (?, ?, ?, ?) SELECT * FROM AUTHOR WHERE ID IN (?, ?, ?, ?) SELECT * FROM AUTHOR WHERE ID IN (?, ?, ?, ?, ?, ?, ?, ?) SELECT * FROM AUTHOR WHERE ID IN (?, ?, ?, ?, ?, ?, ?, ?)
这种技术将大大减少可能的 SQL 字符串的数量,而不会过多地影响 IN
列表较小的情况。在填充时,最后一个绑定变量将被简单地重复多次。
通常,有一种更好的方法 - 将此作为最后的手段!
示例配置
Settings settings = new Settings() .withInListPadding(true) // Default to false .withInListPadBase(4); // Default to 2
反馈
您对此页面有任何反馈吗? 我们很乐意听取您的意见!