我面临数据库中
select
的问题。我在循环中调用相同的查询并仅更改offset
。前 9 个查询非常快(大约 300 毫秒),但第 10 个及后续查询大约需要 40 秒。
我将尽可能多的日志打印到我的 postgresql 日志中,我看到了两件事:
在此日志之后:
2024-03-20 21:20:00 2024-03-20 20:20:00.105 UTC [34] LOG: disconnection: session time: 0:15:37.444 user=admin database=registry host=172.20.0.1 port=46436`
数据库再次正常工作,快速调用 9 个查询,然后再次变慢 - 直到再次断开连接。在代码中设置断点并重新启动数据库也有帮助,但这不是解决方案。另外,当我停留在断点上时调用类似的东西时:
SELECT pg_terminate_backend(pid)
FROM pg_stat_activity
WHERE datname = 'your_database_name';
有助于无延迟地通过接下来的 9 个查询,但像以前一样 - 这不是一个解决方案。
当查询速度变慢时,我看到的执行计划与查询速度快时不同。这些是我看到的差异:
这里是差异链接:https://www.diffchecker.com/vYu3Ejrp/
我也尝试过:
当我使用复杂性较低的查询时(例如:我删除一个
where
或 join
子句),它工作得很好,我可以在循环中调用任意数量的查询。另外,当我添加一些索引时,问题就消失了。但对我来说这太奇怪了。我想如果是效率问题那么数据库应该总是缓慢地回答,而不是在几次查询之后。我说得对吗?
为了总结这一点,我可以补充一点
entityManager.createNativeQuery()
而不是 entityManager.createQuery()
并使用标准生成器进行制作时,一切正常。但是从日志中我看到问题是数据库执行查询的时间太长了。
我想如果是效率问题那么DB应该总是缓慢地回答,而不是在几次查询之后
PREPARE
声明的文档说:
准备好的语句可以使用通用计划或自定义计划来执行。 ...当前的规则是前五次执行是通过自定义计划完成的,并计算这些计划的平均估计成本。然后创建通用计划,并将其估计成本与平均定制计划成本进行比较。如果通用计划的成本没有比平均自定义计划成本高出太多,那么后续执行将使用通用计划,从而使重复的重新计划看起来更可取。
这解释了为什么你的执行计划在 some 执行后发生变化(不知道你是如何达到 nine 执行的)以及为什么如果你强制
plan_cache_mode
它是稳定的。
根本原因是通用计划(即使用变量代替文字的计划)的成本错误(太低),因此切换后性能会下降。