Postgres 选择查询在使用 JDBC 时运行缓慢,但在从同一服务器在 PSQL 中运行时快速
Posted
技术标签:
【中文标题】Postgres 选择查询在使用 JDBC 时运行缓慢,但在从同一服务器在 PSQL 中运行时快速【英文标题】:Postgres select query runs slow when using JDBC but quick when running it in PSQL from the same server 【发布时间】:2020-08-09 17:43:04 【问题描述】:我有以下非常简单的查询,我使用 JDBC 运行该查询需要花费过多的时间。该数据库是 AWS RDS 服务器。 rt2 表有大约 600K 条目,CM2 表大约有 300K。查询返回 11230 行。
SELECT cm2.target
from sysmgmt.sys_root rt2
join cmgmt.member cm2 on cm2.cmid = rt2.cmid and cm2.version=rt2.work_version_id
where rt2.tid=1001
and rt2.proj='d791194b-f2b7-42a7-aba7-f879e052e59d'::uuid
and rt2.deleted = false
and cm2.tid=1001 and cm2.proj = 'd791194b-f2b7-42a7-aba7-f879e052e59d'::uuid;
当我使用 JDBC 调用运行此查询时,需要 40 秒!但是,如果我在同一台机器上的 PSQL 命令行中运行这个完全相同的查询,它几乎是瞬间完成的。
运行 EXPLAIN ANALYZE 显示以下计划。
Nested Loop (cost=0.85..7.77 rows=1 width=176) (actual time=0.030..36.067 rows=11230 loops=1)
-> Index Scan using m_cell_tid_proj_version_idx on member cm2 (cost=0.42..3.32 rows=1 width=197) (actual time=0.020..2.988 rows=11230 loops=1)
Index Cond: ((tid = '1001'::numeric) AND (proj = 'ed1a7c79-a3a1-4d8e-815b-0fbbcbd7bf4b'::uuid))
-> Index Scan using sys_root_cmid_workversion_idx on sys_root rt2 (cost=0.42..4.45 rows=1 width=21) (actual time=0.002..0.002 rows=1 loops=11230)
Index Cond: ((cmid = cm2.cmid) AND (work_version_id = cm2.version))
Filter: ((NOT deleted) AND (tid = '1001'::numeric) AND (proj = 'ed1a7c79-a3a1-4d8e-815b-0fbbcbd7bf4b'::uuid))
Planning Time: 0.374 ms
Execution Time: 36.499 ms
我试图加快速度。
重新排列查询 添加匹配更好的索引 更改填充因子(似乎没有任何效果) 真空这些似乎都没有任何效果。 Java 代码非常简单,运行查询然后迭代结果。计时是在 executeQuery 之前和之后进行的。
Took :[40644.067138] Comment:found 11230 SQL Query:[SELECT cm2.target from sysmgmt.sys_root rt2 join mgmt.member cm2 on cm2.cmid = rt2.cmid and cm2.version=rt2.work_version_id where rt2.tid=1001 and rt2.proj='ed1a7c79-a3a1-4d8e-815b-0fbbcbd7bf4b'::uuid and cm2.tid=1001 and cm2.proj = 'ed1a7c79-a3a1-4d8e-815b-0fbbcbd7bf4b'::uuid and rt2.deleted = false]
大约有 5 到 10 个其他查询在同一事务中运行,其他查询是否有可能在下游到达该查询时导致问题?
如果有人对可能出现的问题有任何想法,我将不胜感激。
【问题讨论】:
需要下载多少数据?假设它是一个text
列,你可以在psql 中select sum(length(cm2.target))
。
您在 Java 代码中究竟是如何传递参数的?
查询有几个“?”参数并使用以下命令进行设置。 selectLockItems.setLong(i++, tId); selectLockItems.setObject(i++, projId); //rt2 selectLockItems.setLong(i++, tId); //cm2
使用 sum(length(cm2.target)) 返回 1931560
@a_horse_with_no_name 我错过了在我的评论中标记你。感谢您清理计划格式
【参考方案1】:
事实证明,解释分析计划在活动上下文中运行时有所不同。打开 auto_explain 参数并将其记录到 postgres 日志文件表明该计划与我将其作为独立请求运行时不同。然后问题变成了“如何让它做正确的事情?”。答案是将 default_statistics_target 从 100 提高到 200 并在数据库上运行 ANALYZE。我还重新排列了连接表的顺序。在做这两个方面,问题已经消失了(希望是好的)。这个 wiki https://wiki.postgresql.org/wiki/Performance_Optimization 也被证明是一个很好的资源。
【讨论】:
“我还重新排列了连接表的顺序。”我怀疑这会改变什么以上是关于Postgres 选择查询在使用 JDBC 时运行缓慢,但在从同一服务器在 PSQL 中运行时快速的主要内容,如果未能解决你的问题,请参考以下文章
在 Postgres (Redshift) 中使用两个选择列运行 MAX 聚合查询时出现问题
clojure/java.jdbc 和 postgres:Prepared statments 比字符串连接查询慢 100 倍?
Postgres使用JDBC Kafka Connect进行流式传输
Spring Boot jdbc模板在自定义模式下的postgres中找不到表
获取 PSQLException:错误:在带有 Postgres 的 spark jdbc 中使用查询而不是表名时在“SELECT”处或附近出现语法错误