数据库

RUM:基于GIN索引改进的全文搜索倒排索引


RUM 是一个为Postgres添加RUM索引的扩展。

RUM索引基于GIN索引,在posting tree中存储了额外的每项信息。例如词素的位置信息或时间戳。与GIN相比,它能够利用这些信息实现更快的仅索引扫描,适用于:

  • 短语搜索
  • 通过文本距离运算符进行排名的文本搜索
  • 按某些非索引附加列(如时间戳)排序的文本SELECT查询

RUM在键值高度可重复的场景下表现最佳。也就是说,所有文本都由有限数量的单词组成,因此按词素建立索引可以显著提高包含单词组合或短语的文本搜索速度。

主要的排序运算符包括:

tsvector <=> tsquery | float4 | tsvectortsquery之间的距离 value <=> value | float8 | 两个值之间的距离

其中value可以是timestamptimestamptzint2int4int8float4float8moneyoid类型

使用方法

启用扩展

您可以通过在Supabase仪表板中启用扩展来开始使用rum。

  1. 进入仪表板的数据库页面
  2. 点击侧边栏中的扩展
  3. 搜索"rum"并启用该扩展

语法

对于类型: tsvector

要理解以下内容,您可能需要先查看 Postgres官方文档关于文本搜索的部分

rum_tsvector_ops

1
2
3
4
5
6
7
8
9
10
11
CREATE TABLE test_rum(t text, a tsvector);CREATE TRIGGER tsvectorupdateBEFORE UPDATE OR INSERT ON test_rumFOR EACH ROW EXECUTE PROCEDURE tsvector_update_trigger('a', 'pg_catalog.english', 't');INSERT INTO test_rum(t) VALUES ('The situation is most beautiful');INSERT INTO test_rum(t) VALUES ('It is a beautiful');INSERT INTO test_rum(t) VALUES ('It looks like a beautiful place');CREATE INDEX rumidx ON test_rum USING rum (a rum_tsvector_ops);

我们可以执行带有文本距离运算符排序的 tsvector 查询:

1
2
3
4
5
6
7
8
9
10
SELECT t, a `<=>` to_tsquery('english', 'beautiful | place') AS rank FROM test_rum WHERE a @@ to_tsquery('english', 'beautiful | place') ORDER BY a `<=>` to_tsquery('english', 'beautiful | place'); t | rank---------------------------------+--------- It looks like a beautiful place | 8.22467 The situation is most beautiful | 16.4493 It is a beautiful | 16.4493(3 rows)

rum_tsvector_addon_ops

1
2
3
CREATE TABLE tsts (id int, t tsvector, d timestamp);CREATE INDEX tsts_idx ON tsts USING rum (t rum_tsvector_addon_ops, d) WITH (attach = 'd', to = 't');

现在我们可以对附加列执行带有距离运算符排序的查询:

1
2
3
4
5
6
7
8
9
SELECT id, d, d `<=>` '2016-05-16 14:21:25' FROM tsts WHERE t @@ 'wr&qh' ORDER BY d `<=>` '2016-05-16 14:21:25' LIMIT 5; id | d | ?column?-----+---------------------------------+--------------- 355 | Mon May 16 14:21:22.326724 2016 | 2.673276 354 | Mon May 16 13:21:22.326724 2016 | 3602.673276 371 | Tue May 17 06:21:22.326724 2016 | 57597.326724 406 | Wed May 18 17:21:22.326724 2016 | 183597.326724 415 | Thu May 19 02:21:22.326724 2016 | 215997.326724(5 rows)

针对类型:anyarray

rum_anyarray_ops

此操作符类存储带有数组长度的anyarray元素。它支持操作符&&@><@=%。同时支持通过<=>操作符进行排序。

1
2
3
CREATE TABLE test_array (i int2[]);INSERT INTO test_array VALUES ('{}'), ('{0}'), ('{1,2,3,4}'), ('{1,2,3}'), ('{1,2}'), ('{1}');CREATE INDEX idx_array ON test_array USING rum (i rum_anyarray_ops);

现在我们可以使用索引扫描执行查询:

1
2
3
4
5
6
7
8
SELECT * FROM test_array WHERE i && '{1}' ORDER BY i `<=>` '{1}' ASC; i----------- {1} {1,2} {1,2,3} {1,2,3,4}(4 rows)

rum_anyarray_addon_ops

该操作符类对anyarray索引的作用与rum_tsvector_addon_ops相同,即允许通过附加列使用距离操作符对查询结果进行排序。

限制

相比GIN索引,RUM的构建和插入时间较慢,原因如下:

  1. 由于索引中存储了额外的属性,它体积更大
  2. 它使用通用的WAL记录

相关资源