使用 OR 语句时 Postgres SQL 很慢
Posted
技术标签:
【中文标题】使用 OR 语句时 Postgres SQL 很慢【英文标题】:Postgres SQL slow when using OR statement 【发布时间】:2019-05-10 01:32:10 【问题描述】:我有一个需要 12 秒的查询(日志表 1.2m 行),根本原因如下
select 1
from
myTable myTable
join myJournal Journal on (Journal.status=0 and myTable.id = Journal.myTableId)
join arrival Arrival on (myTable.id = Arrival.myTableId)
join calc Calc on (myTable.id = Calculated.myTableId)
join ms ms on (Parent.id = ms.myTableId)
join perf Perf on (myTable.id = Perf.myTableId)
join ref Ref on (myTable.id = Ref.myTableId)
where
((myTable.name like 'cheese%' or
Journal.algorithm like 'cheese%' or --if this is removed, its fine <1sec
myTable.client like 'cheese%' or
myTable.something like 'cheese%'))
但是日志表执行正常。在做
select * from myJournal where algorithm like 'cheese%' --takes < 1 sec.
如果我删除了四个连接(未在 where 子句中使用),查询也可以正常执行。
当我加入超过 3 个表时,性能会急剧/成倍下降。
【问题讨论】:
也许您可能需要在Journal(myTableId,status)
上建立一个复合索引。
据我所知,表达式ilike '%cheese%'
不能使用索引。如果您有这种需求,请考虑使用全文搜索。否则,如果要使用索引,请确保使用整个列或仅使用前缀,而不是后缀。
@TimBiegeleisen 好的,谢谢,但这并不能完全解释缓慢吗?因为该查询本身很快
嗯,您正在添加更多限制,这意味着需要更长的时间。在这里要清楚,您的“OK”查询可能没有使用索引。
@TimBiegeleisen 是的,我明白这一点。我已经编辑了我的问题,问题仍然存在
【参考方案1】:
我将首先将查询编写为:
select 1
from myTable t join
myJournal j
on t.id = j.myTableId
where j.status = 0 and
(t.name like 'cheese%' or
j.algorithm like 'cheese%' or
t.client like 'cheese%' or
t.something like 'cheese%'
)
那么最佳索引可能是myJournal(status, myTableId, algorithm)
和myTable(id, name, client, something)
。
这些索引主要用于join
和第一个过滤条件。它们对字符串比较没有多大帮助。但是,由于or
条件,这些很难优化。
【讨论】:
所以我认为我的问题是所有相关信息,但还有其他未在 where 中使用的连接。当我删除其他连接,但保留慢位 int 问题时,性能显着提高,与删除那个或语句一样多。我是否达到了加入的一些 postgres 门槛? 大声笑,我没有投反对票。事实证明,如果我加入超过 3 个表,性能会急剧下降。也许我正在达到一些 postgres 内部限制/阈值 @NimChimpsky 。 . .首先,您不能真正优化字符串上的OR
比较; OR
和字符串都会阻碍这一点(除非 Postgres 对此有奇特的机制)。其次,您可以优化JOIN
s。第三,在查看结果以衡量持续时间时,您必须小心。这可能与返回第一个结果的速度有关,而不是与所有结果有关。
仅供参考 SET LOCAL enable_nestloop = off;解决问题
@NimChimpsky 。 . .有趣的。复杂的where
子句导致 Postgres 切换到嵌套循环连接。对我来说,这听起来像是优化器中的一个错误。以上是关于使用 OR 语句时 Postgres SQL 很慢的主要内容,如果未能解决你的问题,请参考以下文章
使用触发器将 postgres SQL 插入语句拆分为 2 个表