我有一个查询,它需要36s来执行,但我不明白为什么或如何改进它。有帮助吗?
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
我想可能是关系表,但对于16行来说36s太多了。
您知道如何改善此查询吗?
编辑:
由于任何原因,问题不是由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;
答案 0 :(得分:3)
聚合是一个大问题。我建议改用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)
上建立了索引-因为那应该是主键。
答案 1 :(得分:1)
我建议改用IN
,因为选择谓词在子查询中。如果选择谓词位于父查询中,则最好使用EXISTS
。使用IN
时,优化器将子查询写入视图,然后通过唯一索引联接到products
表。请检查同时使用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;