dan*_*uss 5 postgresql jdbc jooq
很多时候,我只想N从查询中检索第一行,但我事先不知道N会是什么。例如:
try(var stream = sql.selectFrom(JOB)
.where(JOB.EXECUTE_AFTER.le(clock.instant()))
.orderBy(JOB.PRIORITY.asc())
.forUpdate()
.skipLocked()
.fetchSize(100)
.fetchLazy()) {
// Now run as many jobs as we can in 10s
...
}
Run Code Online (Sandbox Code Playgroud)
现在,在不添加任意 LIMIT 子句的情况下,PG 查询规划器有时会决定对此类查询进行极其缓慢的顺序表扫描,据我所知,因为它认为我将获取结果集中的每一行。任意 LIMIT 类型适用于像这样的简单情况,但我根本不喜欢它,因为:
N行。N足够大的查询而不破坏您的代码可能会很困难。您不想成为下一个必须理解该代码的人。那么,我如何告诉查询规划器我只会获取几行,并且快速获取第一行是这里的优先事项?这可以使用 JDBC API/驱动程序来实现吗?
(注意:我不是在寻找间接影响查询规划器的服务器配置调整,例如修改随机页面成本,也不能接受类似的解决方法set seq_scan=off)
(注2:为了清楚起见,我在示例代码中使用了 jOOQ,但在幕后这只是另一个PreparedStatement使用ResultSet.TYPE_FORWARD_ONLYand ResultSet.CONCUR_READ_ONLY,所以据我所知,我们可以排除错误的语句模式)
(注3:我没有处于自动提交模式)
PostgreSQL 比你想象的更聪明。您需要做的就是使用该方法将 的获取大小设置java.sql.Statement为不同于 0 的值setFetchSize。然后 JDBC 驱动程序将创建一个游标并以块的形式获取结果集。以这种方式计划的任何查询都将针对快速获取前 10% 的数据进行优化(这由 PostgreSQL 参数控制)cursor_tuple_fraction)。即使查询对表执行顺序扫描,也不必读取所有行:一旦不再获取结果行,读取就会停止。
我不知道如何将 JDBC 方法与 ORM 结合使用,但应该有办法。
| 归档时间: |
|
| 查看次数: |
728 次 |
| 最近记录: |