postgresql - 多列上的 trigram 索引是否会使搜索更快以及如何正确进行此类搜索?
问题描述
假设我有一个包含多列的表。例如:
id int
name text
surname text
cars json
示例记录将是
+----+------+---------+------------------------------------+
| id | name | surname | cars |
+----+------+---------+------------------------------------+
| 1 | John | Doe | {"values":["Ford", "BMW", "Fiat"]} |
+----+------+---------+------------------------------------+
我想搜索所有这些表数据的相关性,如下所示:
select *,
similarity(
'Malcolm Joe likes Ferrary, but hates BMW',
(name || (cars ->> 'values') || surname)
) sim
from public.test_table
where similarity(
'Malcolm Joe likes Ferrary, but hates BMW',
(name || (cars ->> 'values') || surname)
) > 0.05
order by sim desc;
有什么方法可以加快搜索速度吗?创建三元索引?如果是这样 - 如何更好地创造它?在一列上,在每一列上,在连接表达式上?另外,我不明白哪种类型的索引更好——GIN 或 GiST。我读过 GIN 通常更适合常规全文搜索,但 GiST 更适合 trigram 搜索。那是对的吗?
我还想问是否有更好的方法来编写上述查询?
如果有人想知道我为什么选择 trigram 而不是常规的全文搜索 - 这是因为搜索字符串将来自处理一些用户输入,因此可能会出现错误,甚至可能会出现错误,甚至会出现英文“o”或“c”被西里尔字母替换的情况。我的数据库记录或搜索也可以包含字母数字数据,这也可以用三元组更好地处理。
解决方案
在这种情况下,您需要一个 GiST 索引,因为只有它才能用于ORDER BY
使用三元距离运算符的查询:
CREATE INDEX ON public.test_table USING gist
((name || (cars ->> 'values') || surname) gist_trgm_ops);
然后应将查询重写为:
SELECT *,
similarity(
'Malcolm Joe likes Ferrary, but hates BMW',
(name || (cars ->> 'values') || surname)
) sim
FROM public.test_table
WHERE ((name || (cars ->> 'values') || surname)
<->
'Malcolm Joe likes Ferrary, but hates BMW')
< 0.95
ORDER BY (name || (cars ->> 'values') || surname)
<-> /* trigram distance */
'Malcolm Joe likes Ferrary, but hates BMW'
LIMIT 50;
查询必须重写,因为索引支持<->
,但不支持similarity()
inORDER BY
表达式。
我添加了LIMIT
提示优化器,并酌情设置限制。
我认为通常 GIN 索引对于大型表的性能更好,但我不确定。无论如何,您对这个查询别无选择,因为 GIN 索引不支持该ORDER BY
子句。
推荐阅读
- delphi - Indy 10.6.0.5169 + OpenSSL 1.0.2u + Delphi XE7,握手错误
- c# - WPF Visibilty 绑定仅适用于 Constructor、Caliburn Micro
- function - Powershell,将变量从函数内的开关传递给其余部分
- flutter - 在 Flutter 中使用单例与提供者?
- discord.py - 类型错误:get_member() 缺少 1 个必需的位置参数:'self'
- wordpress - 使用 Divi & Tickera 隐藏但不删除页面上的特定类别
- python-3.x - 在谷歌云应用引擎中为自定义域启用“https”
- c# - 这是一个错误的“PossibleMultipleEnumeration”吗?
- c# - 将图像保存到位于 wwwroot 的文件夹中
- jquery - 在使用 laravel 时将变量传递给 javascript 中的路由