简单查询真的很慢
Simple query is really slow
我有这个查询需要 36 秒才能执行,但我不明白为什么或如何改进它。有帮助吗?
SELECT p.* FROM products p INNER JOIN product_store ps ON p.id = ps.product_id
INNER JOIN stores s ON s.id = ps.store_id WHERE s.city = 'Berlin' GROUP BY p.id LIMIT 16 OFFSET 0;
这些是以下数字:
SELECT count(*) FROM products;
43309
SELECT count(*) FROM product_store;
1456445
SELECT count(*) FROM stores;
155
我想这可能是为了关系 table 但 36 秒对于 16 行来说太多了。
知道如何改进这个查询吗?
编辑:
无论出于何种原因,问题都不是由 Postgres 引起的,而是由 Hibernate 引起的。查询在 pgAdmin 4 中非常快,但在 Hibernate 中非常慢。
谢谢大家!
编辑 2:
分析
编辑 3:
抱歉,这是我添加"DISTINCT"
时的真正问题
SELECT DISTINCT p.* FROM products p INNER JOIN product_store ps ON p.id = ps.product_id
INNER JOIN stores s ON s.id = ps.store_id WHERE s.city = 'Berlin' GROUP BY p.id LIMIT 16 OFFSET 0;
生产
本地
聚合是个大问题。我建议改用 EXISTS
:
SELECT p.*
FROM products p
WHERE EXISTS (SELECT 1
FROM product_store ps INNER JOIN
stores s
ON s.id = ps.store_id
WHERE p.id = ps.product_id AND s.city = 'Berlin'
)
LIMIT 16 OFFSET 0;
然后确保您在 product_store(product_id, store_id)
上有索引。我假设您已经在 stores(id)
上建立了索引——因为那应该是主键。
我建议改用 IN
,因为选择性谓词在子查询中。如果选择性谓词在父查询中,最好使用 EXISTS
。当您使用 IN
时,优化器将子查询写入视图,然后通过唯一索引连接到 products
table。请检查同时使用 EXISTS
和 IN
的执行计划以查看差异。
SELECT p.*
FROM products p
WHERE p.id IN (SELECT ps.product_id
FROM product_store ps
JOIN stores s ON s.id = ps.store_id
WHERE p.id = ps.product_id AND s.city = 'Berlin'
)
LIMIT 16 OFFSET 0;
我有这个查询需要 36 秒才能执行,但我不明白为什么或如何改进它。有帮助吗?
SELECT p.* FROM products p INNER JOIN product_store ps ON p.id = ps.product_id
INNER JOIN stores s ON s.id = ps.store_id WHERE s.city = 'Berlin' GROUP BY p.id LIMIT 16 OFFSET 0;
这些是以下数字:
SELECT count(*) FROM products;
43309
SELECT count(*) FROM product_store;
1456445
SELECT count(*) FROM stores;
155
我想这可能是为了关系 table 但 36 秒对于 16 行来说太多了。
知道如何改进这个查询吗?
编辑:
无论出于何种原因,问题都不是由 Postgres 引起的,而是由 Hibernate 引起的。查询在 pgAdmin 4 中非常快,但在 Hibernate 中非常慢。
谢谢大家!
编辑 2:
分析
编辑 3:
抱歉,这是我添加"DISTINCT"
时的真正问题SELECT DISTINCT p.* FROM products p INNER JOIN product_store ps ON p.id = ps.product_id
INNER JOIN stores s ON s.id = ps.store_id WHERE s.city = 'Berlin' GROUP BY p.id LIMIT 16 OFFSET 0;
生产
本地
聚合是个大问题。我建议改用 EXISTS
:
SELECT p.*
FROM products p
WHERE EXISTS (SELECT 1
FROM product_store ps INNER JOIN
stores s
ON s.id = ps.store_id
WHERE p.id = ps.product_id AND s.city = 'Berlin'
)
LIMIT 16 OFFSET 0;
然后确保您在 product_store(product_id, store_id)
上有索引。我假设您已经在 stores(id)
上建立了索引——因为那应该是主键。
我建议改用 IN
,因为选择性谓词在子查询中。如果选择性谓词在父查询中,最好使用 EXISTS
。当您使用 IN
时,优化器将子查询写入视图,然后通过唯一索引连接到 products
table。请检查同时使用 EXISTS
和 IN
的执行计划以查看差异。
SELECT p.*
FROM products p
WHERE p.id IN (SELECT ps.product_id
FROM product_store ps
JOIN stores s ON s.id = ps.store_id
WHERE p.id = ps.product_id AND s.city = 'Berlin'
)
LIMIT 16 OFFSET 0;