优化 Postgres 以搜索未知长度的子字符串

问题描述 投票:0回答:1

我在表

character varying
中有一个名为
message
messages
列,用于存储来自 IRC 频道的用户消息。通过聊天机器人,我允许用户搜索某个术语已被输入的次数。该术语可以是任何内容:一个字符、一个单词或多个单词。该表有大约 1500 万行,查询时间可能相当长。

我使用以下查询来查找所有匹配

term
的子字符串(不区分大小写):

select sum(array_length(string_to_array(LOWER(message), LOWER('term')), 1) -1) from messages;

查询采用顺序扫描。当我

set enable_seqscan = off;
时,它使用我在桌子上也有的
btree
索引。该表还有一个三元组索引,但它从未被使用过。

您会从什么角度来提高查询性能?

我使用 Postgres 14.9

sql postgresql performance query-optimization
1个回答
0
投票

您可以为此应用程序使用 postgreSQL 优化吗?是的,但不是你组织的方式。

首先计算

messages
行,其中
message
列包含任意用户提供的搜索词。您可以通过此查询来执行此操作。

SELECT COUNT(*) FROM messages WHERE message ILIKE '%term%'

然后,在您要搜索的列上创建一个所谓的 trigram 索引。你会这样做的。

CREATE EXTENSION IF NOT EXISTS pg_trgm;
CREATE INDEX CONCURRENTLY message_text ON messages
  USING GIN (message gin_trgm_ops);

这种索引设置是 postgreSQL 独有的,可加速

LIKE
ILIKE
谓词。

此技术返回包含“一个或多个”搜索词出现的消息数,而您的要求要求返回搜索词出现的“总数”。要获取总数,您可以使用子查询仅过滤出现该术语的消息,然后对这些消息进行计数。这比搜索所有消息要快。 select sum(array_length(string_to_array(LOWER(message), LOWER('term')), 1) -1) from ( SELECT message FROM messages WHERE message ILIKE '%term%' ) subset 如果这是我的应用程序,在将其投入生产之前,我将禁止搜索短于三个或四个字母的术语,我什至可能创建一个不允许的停用词表。这是因为这些查询在返回大量计数时会减慢速度。有人可能会使用像

'e'
 这样的简短搜索词来拒绝向您的用户提供服务。


© www.soinside.com 2019 - 2024. All rights reserved.