"A OR exists(B)"查询中的 Postgres 优化



我在Postgres优化中的特定情况下遇到了很多麻烦。

基本上,我有三个表,它们将简化为:

  • Place:id,名称(字符串(,选择(布尔值(
  • Bookmark:id、用户(整数(、地点(整数(
  • User: id, name (字符串(

Place表有几百万行(并且还在增长(,但其中相对较少的行select为真。

我在这些表上有几个索引,显然在所有id上,加上一个关于place where "select"=true的部分索引,以及一个关于bookmark(用户、地点(组合的唯一索引。还有更多,但我认为它们在这里无关紧要。

当我执行以下类型的查询时:

SELECT * 
FROM place 
WHERE "select" 
LIMIT 10;

需要 3 毫秒。

当我执行以下类型的查询时:

SELECT * 
FROM place 
WHERE exists (SELECT id 
FROM bookmark 
WHERE user IN (1,2,3,4) 
AND bookmark.place = place.id) 
LIMIT 10;

它的速度也非常快。

但是,如果我在这两种情况下都做OR,如下所示:

SELECT * 
FROM place 
WHERE "select" 
OR exists (SELECT id 
FROM bookmark 
WHERE user IN (1,2,3,4) 
AND bookmark.place = place.id) 
LIMIT 10;

它减慢到1秒以上。

除了在我的代码中执行两个查询并组合结果之外,还有什么方法可以优化它吗?

老问题,OR是一个性能杀手。

使用UNION

(SELECT * FROM place
WHERE select
LIMIT 10)
UNION
(SELECT * FROM place
WHERE exists (SELECT 1 FROM bookmark
WHERE user IN (1,2,3,4)
AND bookmark.place = place.id)
LIMIT 10)
LIMIT 10;

最新更新