【问题标题】:Indexes to support OR condition over a JOIN在 JOIN 上支持 OR 条件的索引
【发布时间】:2021-11-18 21:50:27
【问题描述】:

我想知道 Postgres 是否支持针对以下基本问题进行优化。

我想在通过外键连接的不同表上搜索两列。我为每一列创建了一个索引。如果我进行联接查询并且对其中一列或另一列有 where 条件,则使用相应的索引来过滤结果,并且查询性能很好。如果对每个表的一个字段使用两个由 OR 组合的 where 子句,则查询会变得非常慢并且不使用索引。这大概是因为优化器认为除了执行全表连接和扫描来解决之外别无他法。查询看起来像这样:

select table1.id
from table1
left join table2 on table1.fk = table2.id
where table1.haystack ilike '%needle%' or table2.haystack ilike '%needle%'

操作 (ilike) 不是问题并且可以互换,我有一个有效的 Trigram 索引设置。我只是想知道除了将所有搜索字段非规范化到一个表中之外,是否还有其他方法可以使这种类型的查询高效。

如果有任何想法,我都会非常感激。

【问题讨论】:

  • 不相关,但是:您的 WHERE 子句有效地将外部联接转换回内部联接
  • 一个基本的解决方案是在两个查询之间做一个UNION ALL,每个查询只在一列上有一个where条件
  • @a_horse_with_no_name :你能解释一下为什么 where 子句将外连接变成内连接吗?谢谢。

标签: postgresql


【解决方案1】:

不,数据库中没有对此进行优化的特殊支持。自己动手:

SELECT table1.id
FROM table1
   JOIN table2 ON table1.fk = table2.id
WHERE table1.haystack ILIKE '%needle%'
UNION
SELECT table1.id
FROM table1
   JOIN table2 ON table1.fk = table2.id
WHERE table2.haystack ILIKE '%needle%'

如果这两个条件都是选择性的并使用三元组索引进行索引,并且您在连接条件上有索引,那么速度会更快。

【讨论】:

  • 嗨 Laurenz,感谢您的回答。我们也在考虑使用 UNION。在实践中,我们正在讨论的查询实际上非常复杂且处理量很大,有很多连接、横向连接、繁重的子选择等。我们不仅仅是在谈论要搜索的两个连接表,实际上是 4 个。但即使如果我们不想进行非规范化或实际的搜索引擎,鉴于所有这些 UNIONS 可能是要走的路。我只是想知道是否有另一种方法。
  • 非规范化是一种方法 - 本质上,您需要一个物化视图来处理复杂的查询,这会带来一系列问题。
  • 我还没有考虑过在那种情况下的物化视图。虽然由于各种原因具体化完整查询是不切实际的,但我可以创建仅包含可搜索列的具体化视图,然后通过主主键将其连接起来。自从我上次使用物化视图以来已经有十多年了。 “刷新时阻塞”问题解决了吗?否则,我猜可以使用基于视图和时间的交替访问和刷新的两个实例。
  • 您现在可以REFRESH MATERIALIZED VIEW CONCURRENTLY。但是您仍然必须忍受陈旧的数据。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-03-15
  • 2016-12-20
  • 1970-01-01
  • 1970-01-01
  • 2021-09-20
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多