【问题标题】:Why slow java app query but fast in PgAdmin?为什么在 PgAdmin 中 Java 应用程序查询速度慢但速度快?
【发布时间】:2021-05-02 14:28:01
【问题描述】:

一个相当复杂的查询的时间安排:

  • 网络应用:12 秒
  • pgAdmin4(5.2 版):700 毫秒(超过 12 倍加速!)

为什么会有这种差异? 查询仅返回 10 行 8 列。

使用 VisualVm 对我的应用进行采样,它表明我的应用在套接字读取中花费了整个查询时间,因此瓶颈必须在 postgres 端。

上下文:

  1. 创建一个临时表temp(一列id integer
  2. 在临时表上创建索引
  3. 在我的复杂选择查询中使用临时表
SELECT DISTINCT min("baseprop"."first"), max("baseprop"."first"), max("baseprop"."second"), "baseprop"."type", "join1name"."lexeme", count(DISTINCT "baseprop"."first"), , (array_agg(DISTINCT "baseprop"."first"))[1:10], "baseprop"."meaning"
FROM "base"
JOIN "temp" ON "temp"."id" = "base"."id"
JOIN "baseprop" ON "baseprop"."base" = "base"."id"
LEFT OUTER JOIN "join1" ON "baseprop"."join1" = "join1"."id"
LEFT OUTER JOIN "join1name" ON "join1name"."owner" = "join1"."id"
LEFT OUTER JOIN "join2" ON "join2"."id" = "join1"."join2"
WHERE (("baseprop"."meaning" = 'm1'
        AND (("join1name"."lexeme" IN ((strip((to_tsvector('en', 'name11')))), (strip((to_tsvector('en', 'name12')))), (strip((to_tsvector('en', 'name13')))))
              AND "join1"."meaning" = 'm1')
             OR ("join1name"."lexeme" IN ((strip((to_tsvector('en', 'name21')))))
                 AND "join1"."meaning" = 'm1')
             OR ("join1name"."lexeme" IN ((strip((to_tsvector('en', 'name22')))))
                 AND "join1"."meaning" = 'm1')
             OR ("join1name"."lexeme" IN ((strip((to_tsvector('en', 'name23')))))
                 AND "join1"."meaning" = 'm1'))
        AND "join2"."country" = 'en'::country)
       OR ("baseprop"."meaning" = 'm2'
           AND (("join1name"."lexeme" IN ((strip((to_tsvector('en', 'name31')))), (strip((to_tsvector('en', 'name32')))), (strip((to_tsvector('en', 'name33')))), (strip((to_tsvector('en', 'name34')))))
                 AND "join1"."meaning" = 'm2')
                OR ("join1name"."lexeme" IN ((strip((to_tsvector('en', 'name41')))))
                    AND "join1"."meaning" = 'm2')
                OR ("join1name"."lexeme" IN ((strip((to_tsvector('en', 'name51')))))
                    AND "join1"."meaning" = 'm2'))
           AND "join2"."country" = 'en'::country)
       OR ("baseprop"."meaning" = 'm3'
           AND "join1name"."lexeme" IN ((strip((to_tsvector('en', 'name61')))))
           AND "join1"."meaning" = 'm3'
           AND "join2"."country" = 'en'::country)
       OR ("baseprop"."meaning" = 'm4'
           AND "join1name"."lexeme" IN ((strip((to_tsvector('en', 'name71')))))
           AND "join1"."meaning" = 'm4'
           AND "join2"."country" = 'en'::country))
GROUP BY "baseprop"."meaning",
         "baseprop"."type",
         "join1name"."lexeme"

即使不使用临时表,我仍然可以得到 7 倍的加速差异。

jdbcdriver 'org.postgresql:postgresql:42.2.20'

Postgres 12

编辑

似乎差异是由于PreparedStatement。使用原始 sql 文本(嵌入式参数)发出查询按预期工作。 相关:PreparedStatement very slow, but manual query quick

【问题讨论】:

    标签: postgresql pgadmin pgadmin-4


    【解决方案1】:

    使用准备好的语句,PostgreSQL 会缓存查询计划,最终可以使用独立于参数值的“通用”计划。

    要强制 PostgreSQL 始终使用自定义计划,请将 plan_cache_mode 设置为 force_custom_plan

    如果您使用临时表,最好在使用它们之前ANALYZE 它们。

    【讨论】:

    • 我认为在postgresql.conf 中设置plan_cache_mode=force_custom_plan 可能会降低其他受益于查询计划缓存的快速查询的性能。
    • 绝对。您只想在需要它的会话/功能/事务中设置它。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-07-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-08-01
    • 1970-01-01
    相关资源
    最近更新 更多