我很抱歉问这样一个noob问题,但postgres documentation的意见是稀疏的,我很难找到一个很好的答案。多个表格视图可以用于全文搜索吗?
我试图在Postgres上实现全文搜索三个表。具体来说,用户的搜索查询将返回匹配1)其他用户名,2)消息,3)主题。
我担心为此使用视图可能无法很好地扩展,因为它将三个表合并为一个。这是一个合理的担忧吗?如果不是,我还可以怎样处理这个问题?
我很抱歉问这样一个noob问题,但postgres documentation的意见是稀疏的,我很难找到一个很好的答案。多个表格视图可以用于全文搜索吗?
我试图在Postgres上实现全文搜索三个表。具体来说,用户的搜索查询将返回匹配1)其他用户名,2)消息,3)主题。
我担心为此使用视图可能无法很好地扩展,因为它将三个表合并为一个。这是一个合理的担忧吗?如果不是,我还可以怎样处理这个问题?
你可以做什么。为了有一个实际的例子(只有两个表),你可以有:
CREATE TABLE users
(
user_id SERIAL PRIMARY KEY,
username text
) ;
-- Index to find usernames
CREATE INDEX idx_users_username_full_text
ON users
USING GIN (to_tsvector('english', username)) ;
CREATE TABLE topics
(
topic_id SERIAL PRIMARY KEY,
topic text
) ;
-- Index to find topics
CREATE INDEX idx_topics_topic_full_text
ON topics
USING GIN (to_tsvector('english', topic)) ;
见PostgreSQL的文档。请致电Controlling Text Search获取to_tsvector
的解释。
...填充表
INSERT INTO users
(username)
VALUES
('Alice Cooper'),
('Boo Geldorf'),
('Carol Burnet'),
('Daniel Dafoe') ;
INSERT INTO topics
(topic)
VALUES
('Full text search'),
('Fear of void'),
('Alice in Wonderland essays') ;
...创建两个表
CREATE VIEW search_items AS
SELECT
text 'users' AS origin_table, user_id AS id, to_tsvector('english', username) AS searchable_element
FROM
users
UNION ALL
SELECT
text 'topics' AS origin_table, topic_id AS id, to_tsvector('english', topic) AS searchable_item
FROM
topics ;
我们寻找这一观点结合值的观点:
SELECT
*
FROM
search_items
WHERE
plainto_tsquery('english', 'alice') @@ searchable_element
..并获得以下回复(你应该大多忽略searchable_element
)。你最感兴趣的是origin_table
和id
。
origin_table | id | searchable_element :----------- | -: | :-------------------------------- users | 1 | 'alic':1 'cooper':2 topics | 3 | 'alic':1 'essay':4 'wonderland':3
见解析查询的plainto_tsquery
功能的说明,也@@
operator。
要确保使用索引:
EXPLAIN ANALYZE
SELECT
*
FROM
search_items
WHERE
plainto_tsquery('english', 'alice') @@ searchable_element
| QUERY PLAN | | :----------------------------------------------------------------------------------------------------------------------------------------- | | Append (cost=12.05..49.04 rows=12 width=68) (actual time=0.017..0.031 rows=2 loops=1) | | -> Bitmap Heap Scan on users (cost=12.05..24.52 rows=6 width=68) (actual time=0.017..0.018 rows=1 loops=1) | | Recheck Cond: ('''alic'''::tsquery @@ to_tsvector('english'::regconfig, username)) | | Heap Blocks: exact=1 | | -> Bitmap Index Scan on idx_users_username_full_text (cost=0.00..12.05 rows=6 width=0) (actual time=0.005..0.005 rows=1 loops=1) | | Index Cond: ('''alic'''::tsquery @@ to_tsvector('english'::regconfig, username)) | | -> Bitmap Heap Scan on topics (cost=12.05..24.52 rows=6 width=68) (actual time=0.012..0.012 rows=1 loops=1) | | Recheck Cond: ('''alic'''::tsquery @@ to_tsvector('english'::regconfig, topic)) | | Heap Blocks: exact=1 | | -> Bitmap Index Scan on idx_topics_topic_full_text (cost=0.00..12.05 rows=6 width=0) (actual time=0.002..0.002 rows=1 loops=1) | | Index Cond: ('''alic'''::tsquery @@ to_tsvector('english'::regconfig, topic)) | | Planning time: 0.098 ms | | Execution time: 0.055 ms |
索引是真正使用(见Bitmap Index Scan on idx_topics_topic_full_text
和Bitmap Index Scan on idx_users_username_full_text
)。
您可以在检查一切dbfiddle here
注:'english'
是选择索引和查询的text search configuration。为你的情况选择一个合适的。如果现有的不满足您的需求,您可以创建自己的。
你可以做这样的事情。确保原始表上所需的列(或表达式)具有正确的索引。另外,测试查询视图时产生的执行计划,以确保它们显示索引使用情况。否则,它会工作,但真的很慢。或者,你可以有一个*物化视图*,并直接在它上面有索引;并确保足够频繁地更新它。 – joanolo