Sql 可以使用多个表的视图进行全文搜索吗?

Sql 可以使用多个表的视图进行全文搜索吗?,sql,postgresql,full-text-search,Sql,Postgresql,Full Text Search,我很抱歉问这样一个noob问题,但是关于视图的讨论很少,我很难找到一个好的答案 我试图在Postgres上实现三个表的全文搜索。具体来说,用户的搜索查询将返回匹配的1)其他用户名、2)消息、3)主题 我担心使用视图进行此操作可能无法很好地扩展,因为它将三个表合并为一个表。这是合理的担忧吗?如果没有,我还能怎么做呢?您的要求可以实现。要获得一个实际示例(只有两个表),您可以: CREATE TABLE users ( user_id SERIAL PRIMARY KEY, user

我很抱歉问这样一个noob问题,但是关于视图的讨论很少,我很难找到一个好的答案

我试图在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文档。有关
至_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
。。。并得到以下响应(您应该主要忽略
可搜索的\u元素
)。您最感兴趣的是
origin\u表
id

origin_table | id | searchable_element :----------- | -: | :-------------------------------- users | 1 | 'alic':1 'cooper':2 topics | 3 | 'alic':1 'essay':4 'wonderland':3 |查询计划| | :----------------------------------------------------------------------------------------------------------------------------------------- | |追加(成本=12.05..49.04行=12宽度=68)(实际时间=0.017..0.031行=2圈=1)| |->用户上的位图堆扫描(成本=12.05..24.52行=6宽度=68)(实际时间=0.017..0.018行=1循环=1)| |重新检查条件:('alic'::tsquery@@to_tsvector('english'::regconfig,username))| |堆块:精确=1| |->idx用户用户名全文位图索引扫描(成本=0.00..12.05行=6宽度=0)(实际时间=0.005..0.005行=1循环=1)| |索引条件:('alic'::tsquery@@to_tsvector('english'::regconfig,username))| |->主题上的位图堆扫描(成本=12.05..24.52行=6宽度=68)(实际时间=0.012..0.012行=1循环=1)| |重新检查条件:('alic'::tsquery@@to_tsvector('english'::regconfig,topic))| |堆块:精确=1| |->idx主题全文上的位图索引扫描(成本=0.00..12.05行=6宽度=0)(实际时间=0.002..0.002行=1循环=1)| |索引条件:('alic'::tsquery@@to_tsvector('english'::regconfig,topic))| |计划时间:0.098毫秒| |执行时间:0.055毫秒| 真正使用索引(请参见idx上的
位图索引扫描\u主题\u主题\u全文
和idx上的
位图索引扫描\u用户\u用户名\u全文

你可以随时检查一切



注意:
'english'
是用于索引和查询的选项。根据你的情况选择合适的。如果现有的不能满足您的需要,您可以创建自己的。

您可以这样做。确保原始表上所需的列(或表达式)具有正确的索引。另外,测试查询视图时生成的执行计划,以确保它们显示索引使用情况。否则,它将起作用,但实际上非常缓慢。或者,您可以拥有一个物化视图,并将索引直接放在其上;并确保足够频繁地更新。谢谢,这真的很有帮助。但速度是个问题。您是否有过大量记录(如2M+)的演出经验?在物化视图的情况下,由于其更新的局限性,可以安全地说它不适用于搜索吗?似乎最好的解决方案是创建一个表并触发从其他表中提取的派生内容。我有100.000秒的经验。搜索速度很快。如果有100或1000个结果,问题通常是排序(使用
ts_rank
),因为该函数需要大量计算。如果您选择触发方式,我建议您仅将
to_tsvector
结果存储在该表中,并对其进行索引。我不认为它会更快,除非你处理超过5张桌子。
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 |