Mat*_*ins 10 database postgresql indexing database-design full-text-search
我正在为我正在构建的网站创建自定义论坛软件,其中包括2个表(与此问题相关):topics
和posts
.帖子属于主题,主题包含主题,而每个帖子包含主体.
以下是与我的问题相关的列的基本表结构:
CREATE TABLE topics (
id bigserial NOT NULL,
title varchar(128) NOT NULL,
created timestamp with time zone NOT NULL default NOW(),
updated timestamp with time zone NOT NULL default NOW(),
PRIMARY KEY (id)
);
CREATE TABLE posts (
id bigserial NOT NULL,
topic_id bigint NOT NULL REFERENCES topics(id) ON DELETE CASCADE,
body text NOT NULL,
created timestamp with time zone NOT NULL default NOW(),
updated timestamp with time zone NOT NULL default NOW(),
PRIMARY KEY (id)
);
Run Code Online (Sandbox Code Playgroud)
以下是构建全文索引的两个选项.
选项1:在标题/正文列上创建动态tsvector索引.
CREATE INDEX topics_title_idx ON topics USING gin(to_tsvector(title));
CREATE INDEX posts_body_idx ON posts USING gin(to_tsvector(body));
Run Code Online (Sandbox Code Playgroud)
选项2:创建额外的列以保存tsvector化的标题/正文数据,并在其上添加索引.
ALTER TABLE topics ADD COLUMN topics_vector tsvector NOT NULL;
CREATE TRIGGER topics_ins BEFORE INSERT OR UPDATE ON topics FOR EACH ROW EXECUTE PROCEDURE tsvector_update_trigger(title_vector, 'pg_catalog.english', title);
CREATE INDEX topics_title_idx ON topics USING gin(title_vector);
ALTER TABLE posts ADD COLUMN posts_vector tsvector NOT NULL;
CREATE TRIGGER posts_ins BEFORE INSERT OR UPDATE ON posts FOR EACH ROW EXECUTE PROCEDURE tsvector_update_trigger(body_vector, 'pg_catalog.english', body);
CREATE INDEX posts_body_idx ON posts USING gin(body_vector);
Run Code Online (Sandbox Code Playgroud)
我在两者之间进行辩论,因为选项1将节省我的磁盘空间,但提供较慢的搜索,而选项2将需要额外的磁盘空间,同时提供更快的搜索.
让我们假装每天有20个新主题和100个新帖子.你会选哪个?如果每天主题/帖子数量的两倍怎么办?五倍呢?十次?您对一个与另一个的决定是否有所改变?
使用选项1不会使您的搜索更慢.
GIN
无论您是在实例化列还是计算表达式中创建,都将使用该索引.
您只需要更改查询语法:
SELECT *
FROM posts
WHERE TO_TSVECTOR('english', title) @@ myquery
Run Code Online (Sandbox Code Playgroud)
在第一种情况下,或
SELECT *
FROM posts
WHERE title_vector @@ myquery
Run Code Online (Sandbox Code Playgroud)
在第二种情况下.
使用TS_RANK
实例化列时,您可能可以节省一点时间.
小智 5
让我们假装每天有20个新主题和100个新帖子.你会选哪个?如果每天主题/帖子数量的两倍怎么办?五倍呢?十次?您对一个与另一个的决定是否有所改变?
这一年约有36,000个帖子.无所谓.即使在便宜的机器上,也可能十倍无关紧要.
但是,您可能希望第三个表包含将主题和正文组合在一起的显式tsvector.然后,您可以使用内置加权系统并运行一次搜索,以提供人们通常在论坛等上所期望的搜索类型.这意味着在更改任一源表时编写自定义触发器来更新您的tsvector.