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 中运行时快速的主要内容,如果未能解决你的问题,请参考以下文章

JDBC 将我的 postgres 查询中的表大写

在 Postgres (Redshift) 中使用两个选择列运行 MAX 聚合查询时出现问题

clojure/java.jdbc 和 postgres:Prepared statments 比字符串连接查询慢 100 倍?

Postgres使用JDBC Kafka Connect进行流式传输

Spring Boot jdbc模板在自定义模式下的postgres中找不到表

获取 PSQLException:错误:在带有 Postgres 的 spark jdbc 中使用查询而不是表名时在“SELECT”处或附近出现语法错误