我很抱歉問這樣一個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