为什么在 PgAdmin 中速度慢 java 应用查询但速度快?
Why slow java app query but fast in PgAdmin?
相当复杂的查询时间:
- 网络应用程序:12 秒
- pgAdmin4(5.2 版):700 毫秒(加速超过 12 倍!)
为什么会有这种差异?
查询仅返回 10 行 8 列。
使用 VisualVm 对我的应用程序进行采样表明我的应用程序将整个查询时间都花在套接字读取上,因此瓶颈一定在 postgres 端。
上下文:
- 创建临时 table
temp
(一列 id integer
)
- 在临时文件上创建索引 table
- 在我的复杂 select 查询中使用临时 table
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"
即使不使用临时 table,我仍然可以获得 7 倍的加速差异。
jdbcdriver 'org.postgresql:postgresql:42.2.20'
Postgres 12
编辑
差异似乎是由于 PreparedStatement
。使用原始 sql 文本(嵌入参数)发出查询按预期工作。
相关:PreparedStatement very slow, but manual query quick
使用准备好的语句,PostgreSQL 缓存查询计划并最终可以使用独立于参数值的“通用”计划。
要强制 PostgreSQL 始终使用自定义计划,请将 plan_cache_mode
设置为 force_custom_plan
。
如果您正在使用临时表,最好在使用前 ANALYZE
它们。
相当复杂的查询时间:
- 网络应用程序:12 秒
- pgAdmin4(5.2 版):700 毫秒(加速超过 12 倍!)
为什么会有这种差异? 查询仅返回 10 行 8 列。
使用 VisualVm 对我的应用程序进行采样表明我的应用程序将整个查询时间都花在套接字读取上,因此瓶颈一定在 postgres 端。
上下文:
- 创建临时 table
temp
(一列id integer
) - 在临时文件上创建索引 table
- 在我的复杂 select 查询中使用临时 table
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"
即使不使用临时 table,我仍然可以获得 7 倍的加速差异。
jdbcdriver 'org.postgresql:postgresql:42.2.20'
Postgres 12
编辑
差异似乎是由于 PreparedStatement
。使用原始 sql 文本(嵌入参数)发出查询按预期工作。
相关:PreparedStatement very slow, but manual query quick
使用准备好的语句,PostgreSQL 缓存查询计划并最终可以使用独立于参数值的“通用”计划。
要强制 PostgreSQL 始终使用自定义计划,请将 plan_cache_mode
设置为 force_custom_plan
。
如果您正在使用临时表,最好在使用前 ANALYZE
它们。