Hologres自V4.0版本起支援全文倒排索引,該功能基於高效能全文檢索索引引擎Tantivy構建,提供高效能檢索能力,同時支援BM25相似性評分演算法,提供文檔排序、關鍵詞檢索、短語檢索等多方面能力。
實現原理
將檢索源文本寫入Hologres後,Hologres會根據索引配置,對每個資料檔案,構建全文倒排索引檔案。該過程首先通過分詞器對文本進行分詞,得到若干分詞token,然後通過索引記錄每個token與檢索源文本的映射關係、位置和詞頻等相關資訊。
在對文本進行檢索時,先對檢索對象文本進行分詞,得到對象token集合。通過BM25演算法計算檢索源的每個文本與檢索對象token集合的相關性分數,實現高效能、高精度的全文檢索索引。
注意事項
僅支援Hologres V4.0及以上版本的列存表、行列共存表使用全文倒排索引功能,不支援行存表。
僅支援對TEXT/CHAR/VARCHAR類型的列建立全文倒排索引。
僅支援對單列構建全文倒排索引。每一列僅支援構建一個全文倒排索引。如果有多列需要構建,則需要建立多個索引。
在建立全文倒排索引後,針對錶中現有資料及後續批量寫入的新資料,索引檔案將隨著資料的合并(Compaction)過程進行非同步構建。在索引檔案構建完成之前,資料的BM25相關性分數為0。
針對建立全文倒排索引後的資料即時寫入情境,在Hologres V4.0.8版本之前,索引會在資料即時寫入時同步構建。從V4.0.8版本開始,為了保障資料即時寫入的效率與索引構建的效能,系統將以1秒為間隔,定時非同步重新整理記憶體中的即時索引,只有在重新整理後,才能通過索引查詢到相關資料。
全文檢索索引僅支援在已建立全文索引的列上執行,不支援在未構建索引的情況下進行暴力計算。
建議使用Serverless Computing資源執行資料的大量匯入,Serverless資源將在資料匯入時同步完成Compaction及全文索引構建,詳情請參見使用Serverless Computing執行讀寫任務、使用Serverless Computing執行Compaction任務。如不使用Serverless資源,建議在大量匯入資料或修改索引後,手動執行如下命令觸發Compaction。
VACUUM <schema_name>.<table_name>;BM25檢索演算法計算的相關性分數為檔案層級,如果您的資料匯入量較小,建議按需手動觸發Compaction,以完成檔案合并,提升檢索準確率。
支援使用Serverless Computing資源執行全文檢索索引的查詢。
推薦按下表情境選擇合適的分詞器:
情境
分詞器
備忘
長文章關鍵詞提取
Jieba
支援新詞發現、複雜模式切換。
中文描述類文本檢索
IK
精確識別中文術語。
英文標題類文本檢索
Simple、Whitespace、Standard
簡單高效,根據目標英文文本按需使用。
日誌類文本模糊檢索
Ngram
無需詞典,滿足文本的模糊查詢需求。
中文商品/人名拼音檢索
Pinyin
中文全拼、首字母、多音字推導等豐富的中文拼音情境。
管理索引
建立索引
文法格式
CREATE INDEX [ IF NOT EXISTS ] idx_name ON table_name
USING FULLTEXT (column_name [ , ... ])
[ WITH ( storage_parameter [ = value ] [ , ... ] ) ];參數說明
參數 | 描述 |
idx_name | 索引名。 |
table_name | 目標表名。 |
column_name | 構建全文倒排索引的目標列名。 |
storage_parameter | 配置全文倒排索引參數,有如下兩類參數:
說明 同一個索引中,僅支援設定一種tokenizer和analyzer_params。 |
使用樣本
建立全文倒排索引,分詞器及配置均為預設,即jieba分詞器。
CREATE INDEX idx1 ON tbl USING FULLTEXT (col1);顯式指定使用ik分詞器,分詞器使用預設配置。
CREATE INDEX idx1 ON tbl USING FULLTEXT (col1) WITH (tokenizer = 'ik');顯式指定使用自訂的分詞器配置: jieba分詞器+exact模式+僅用lowercase過濾器轉小寫。
CREATE INDEX idx1 ON tbl USING FULLTEXT (col1) WITH (tokenizer = 'jieba', analyzer_params = '{"tokenizer":{"type":"jieba","mode":"exact"}, "filter":["lowercase"]}');
建立全文倒排索引後,索引檔案將在資料匯入後的Compaction過程中構建。
建議使用Serverless Computing資源執行資料的大量匯入,Serverless資源將在資料匯入時同步完成Compaction及全文索引構建,參見使用Serverless Computing執行讀寫任務、使用Serverless Computing執行Compaction任務。
如不使用Serverless資源,建議在大量匯入資料或修改索引後,手動執行如下命令觸發Compaction,參見Compaction(Beta)。
VACUUM <schema_name>.<table_name>;
修改索引
文法格式
-- 修改索引配置
ALTER INDEX [ IF EXISTS ] <idx_name> SET ( <storage_parameter> = '<storage_value>' [ , ... ] );
-- 恢複預設配置
ALTER INDEX [ IF EXISTS ] <idx_name> RESET ( <storage_parameter> [ , ... ] );參數說明
參數詳細說明請參見參數說明。
使用樣本
修改全文倒排索引後,索引檔案將隨資料的Compaction過程非同步構建。建議在修改索引後,手動執行VACUUM <schema_name>.<table_name>;命令,同步觸發Compaction,詳情請參見Compaction。
將索引的分詞器改為standard。
ALTER INDEX idx1 SET (tokenizer = 'standard');將索引的分詞器改為ik,ik_max_word模式,不轉小寫,不加任何filter。
ALTER INDEX idx1 SET ( tokenizer = 'ik', analyzer_params = '{"tokenizer":{"type":"ik","mode":"ik_max_word","enable_lowercase": false}}' );恢複預設分詞器jieba,且使用jieba分詞器的預設analyzer_params配置。
ALTER INDEX idx1 RESET (tokenizer); ALTER INDEX idx1 RESET (tokenizer, analyzer_params);恢複到當前分詞器的預設analyzer_params配置。
ALTER INDEX idx1 RESET (analyzer_params);
刪除索引
文法格式
DROP INDEX [ IF EXISTS ] <idx_name> [ RESTRICT ];參數說明
參數詳細說明請參見參數說明。
查看索引
Hologres提供hologres.hg_index_properties系統資料表,可查看錶中已建立的全文倒排索引及對應位置。
SELECT * FROM hologres.hg_index_properties;執行如下SQL,可查看索引對應的表和列。
SELECT
t.relname AS table_name,
a.attname AS column_name
FROM pg_class t
JOIN pg_index i ON t.oid = i.indrelid
JOIN pg_class idx ON i.indexrelid = idx.oid
JOIN pg_attribute a ON a.attrelid = t.oid AND a.attnum = ANY(i.indkey)
WHERE t.relnamespace = (SELECT oid FROM pg_namespace WHERE nspname = '<namespace>')
AND idx.relname = '<indexname>'
LIMIT 1;參數說明:
namespace:為
SELECT * FROM hologres.hg_index_properties;命令執行結果中的table_namespace欄位值。indexname:為實際建立的索引名稱。
使用索引進行全文檢索索引
Hologres支援豐富的檢索模式,便於您按照商務邏輯,靈活進行全文檢索索引。
檢索模式 | 說明 |
關鍵詞匹配 | 按檢索對象的分詞結果關鍵詞進行檢索,支援定義關鍵詞間的AND/OR關係。 |
短語檢索 | 按檢索對象的短語進行檢索,需滿足多個詞之間的距離要求才可匹配。 |
自然語言檢索 | 支援自由定義複雜查詢條件,靈活實現檢索目標,如定義AND/OR關聯關係、定義必須出現詞/排除詞、定義短語等。 |
術語檢索 | 按檢索對象精確檢索,需要索引中精確包含查詢串才可匹配。 |
檢索函數TEXT_SEARCH
檢索函數TEXT_SEARCH可基於檢索對象文本,對檢索源文本計算BM相關性分數。
函數文法
TEXT_SEARCH (
<search_data> TEXT/VARCHAR/CHAR
,<search_expression> TEXT
[ ,<mode> TEXT DEFAULT 'match'
,<operator> TEXT DEFAULT 'OR'
,<tokenizer> TEXT DEFAULT ''
,<analyzer_params> TEXT DEFAULT ''
,<options> TEXT DEFAULT '']
)參數說明
參數 | 是否必填 | 描述 |
search_data | 是 | 檢索源。資料類型支援TEXT/VARCHAR/CHAR,僅支援列入參,且列上需已構建全文索引,否則會報錯。 |
search_expression | 是 | 檢索對象。資料類型支援TEXT/VARCHAR/CHAR,僅支援常量。 |
mode | 否 | 檢索模式。支援的模式如下:
|
operator | 否 | 關鍵詞之間的邏輯運算子。僅mode為match時生效。支援如下取值:
|
tokenizer、analyzer_params | 否 | 對檢索對象search_expression使用的分詞器及配置,一般無需配置。
|
options | 否 | 全文檢索索引的其他參數。入參格式為 目前僅支援slop參數,僅mode為phrase時生效,支援slop為0(預設)或正整數,用於定義短語中各個詞之間可容忍的距離。 說明 slop表示短語組成詞之間的最大允許間隔(或轉換開銷),對於jieba/keyword/icu等tokenizer來說,間隔的單位是字元數而不是tokens單詞數。對於standard/simple/whitespace等tokenizer,間隔的單位是tokens單詞數。 |
傳回值說明
返回非負的FLOAT類型,表示檢索源與檢索對象的BM25相關性分數。相關性越高,分數越大。當文本完全不相關時,分數為0。
樣本
使用關鍵詞匹配模式,並將運算子改為AND。
-- 建議指定參數名 SELECT TEXT_SEARCH (content, 'machine learning', operator => 'AND') FROM tbl; -- 不指定參數名,需按入參順序顯式指定 SELECT TEXT_SEARCH (content, 'machine learning', 'match', 'AND') FROM tbl;使用短語檢索模式,並將slop設為2。
SELECT TEXT_SEARCH (content, 'machine learning', 'phrase', options => 'slop=2;') FROM tbl;使用自然語言檢索模式。
-- 通過AND、OR運算子定義分詞檢索邏輯 SELECT TEXT_SEARCH (content, 'machine AND (system OR recognition)', 'natural_language') FROM tbl; -- 通過+(必須出現詞)、-(必須排除詞)定義分詞檢索邏輯 SELECT TEXT_SEARCH (content, '+learning -machine system', 'natural_language') FROM tbl;使用術語檢索模式。
SELECT TEXT_SEARCH (content, 'machine learning', 'term') FROM tbl;
分詞函數TOKENIZE
分詞函數TOKENIZE可按照分詞器配置,輸出分詞結果,以便對全文倒排索引的分詞效果進行調試。
函數文法
TOKENIZE (
<search_data> TEXT
[ ,<tokenizer> TEXT DEFAULT ''
,<analyzer_params> TEXT DEFAULT '']
)參數說明
search_data:必填。分詞目標文本,支援常量入參。
tokenizer、analyzer_params:選填。對分詞目標文本search_data使用的分詞器及配置。預設使用jieba分詞器。
傳回值說明
返回目標文本的分詞token集合,類型為TEXT數組。
索引使用驗證
可通過執行計畫查看SQL是否使用了全文倒排索引,若其中出現Fulltext Filter,表示已成功使用。執行計畫詳情請參見EXPLAIN和EXPLAIN ANALYZE。
樣本SQL:
EXPLAIN ANALYZE SELECT * FROM wiki_articles WHERE text_search(content, '長江') > 0;執行計畫如下:其中包含Fulltext Filter欄位,表示該SQL已成功使用全文倒排索引。
QUERY PLAN
Gather (cost=0.00..1.00 rows=1 width=12)
-> Local Gather (cost=0.00..1.00 rows=1 width=12)
-> Index Scan using Clustering_index on wiki_articles (cost=0.00..1.00 rows=1 width=12)
Fulltext Filter: (text_search(content, search_expression => '長江'::text, mode => match, operator => OR, tokenizer => jieba, analyzer_params => {"filter":["removepunct","lowercase",{"stop_words":["_english_"],"type":"stop"},{"language":"english","type":"stemmer"}],"tokenizer":{"hmm":true,"mode":"search","type":"jieba"}}, options => ) > '0'::double precision)
Query Queue: init_warehouse.default_queue
Optimizer: HQO version 4.0.0使用樣本
資料準備
執行以下SQL建立測試表、並寫入資料。
-- 建立表
CREATE TABLE wiki_articles (id int, content text);
-- 建立索引
CREATE INDEX ft_idx_1 ON wiki_articles
USING FULLTEXT (content)
WITH (tokenizer = 'jieba');
-- 寫入資料
INSERT INTO wiki_articles VALUES
(1, '長江是中國第一大河,世界第三長河,全長約6,300公裡。'),
(2, 'Li was born in 1962 in Wendeng County, Shandong.'),
(3, 'He graduated from the department of physics at Shandong University.'),
(4, '春節,即農曆新年,是中國最重要的傳統節日。'),
(5, '春節通常在西曆1月下旬至2月中旬之間。春節期間的主要習俗包括貼春聯、放鞭炮、吃年夜飯、拜年等。'),
(6, '2006年,春節被國務院批准為第一批國家級非物質文化遺產。'),
(7, 'Shandong has dozens of universities.'),
(8, 'ShanDa is a famous university of Shandong.');
-- Compaction
VACUUM wiki_articles;
-- 查詢表資料
SELECT * FROM wiki_articles limit 1;返回結果樣本如下:
id | content
---+---------------------------------------------------
1 | 長江是中國第一大河,世界第三長河,全長約6,300公裡。不同檢索樣本
關鍵詞匹配。
-- (K1) 關鍵詞匹配(預設operator=OR),包含'shandong'或'university'的文檔均能匹配。 SELECT * FROM wiki_articles WHERE TEXT_SEARCH(content, 'shandong university') > 0; --返回結果 id | content ----+--------------------------------------------------------------------- 2 | Li was born in 1962 in Wendeng County, Shandong. 3 | He graduated from the department of physics at Shandong University. 7 | Shandong has dozens of universities. 8 | ShanDa is a famous university of Shandong. -- (K2) 關鍵詞匹配(operator=AND),必須同時包含'shandong'和'university'才能匹配 SELECT * FROM wiki_articles WHERE TEXT_SEARCH(content, 'shandong university', operator => 'AND') > 0; -- 返回結果 id | content ----+--------------------------------------------------------------------- 3 | He graduated from the department of physics at Shandong University. 7 | Shandong has dozens of universities. 8 | ShanDa is a famous university of Shandong.短語檢索。
-- (P1) 短語檢索(預設slop = 0),即必須 shandong 後緊接 university 後才匹配 SELECT * FROM wiki_articles WHERE TEXT_SEARCH(content, 'shandong university', mode => 'phrase') > 0; -- 返回結果 id | content ----+--------------------------------------------------------------------- 3 | He graduated from the department of physics at Shandong University. (1 row) -- (P2) 短語檢索指定slop = 14,即 shandong 與 university 之間的距離不超過14個字元,那麼可以匹配“Shandong has dozens of universities.” SELECT * FROM wiki_articles WHERE TEXT_SEARCH(content, 'shandong university', mode => 'phrase', options => 'slop=14;') > 0; -- 返回結果 id | content ----+--------------------------------------------------------------------- 3 | He graduated from the department of physics at Shandong University. 7 | Shandong has dozens of universities. (2 rows) -- (P3) 短語檢索支援檢索不保序的短語,但slop計算方式不一樣,要比保序的slop要大。 -- 因此'university of Shandong'也能匹配以下查詢,但slop=22時不會匹配到 SELECT * FROM wiki_articles WHERE TEXT_SEARCH(content, 'shandong university', mode => 'phrase', options => 'slop=23;') > 0; -- 返回結果 id | content ----+--------------------------------------------------------------------- 3 | He graduated from the department of physics at Shandong University. 7 | Shandong has dozens of universities. 8 | ShanDa is a famous university of Shandong. (3 rows) -- (P4) standard分詞索引下的表現。(ALTER INDEX ft_idx_1 SET (tokenizer = 'standard');) -- 對於standard分詞來說,slop則是以tokens為計算單位。 -- 只要中間間隔0個tokens,不管有多少空格,都算作短語匹配。 SELECT * FROM wiki_articles WHERE TEXT_SEARCH(content, 'shandong university', mode => 'phrase') > 0; -- 返回結果 id | content ----+------------------------ 1 | shandong university 2 | shandong university 3 | shandong university 4 | shandong university (4 rows) -- (P5) 標點將被忽略。(jieba分詞器為例) -- 即使文本中,長河和全長之間是逗號,而查詢串是句號。 SELECT * FROM wiki_articles WHERE TEXT_SEARCH(content, '長河。全長', mode => 'phrase') > 0; -- 返回結果 id | content ----+----------------------------------------------------- 1 | 長江是中國第一大河,世界第三長河,全長約6,300公裡。 (1 row)自然語言查詢。
-- (N1) 自然語言查詢:不加任何符號,預設等同於關鍵詞匹配。與(K1)等價。 SELECT * FROM wiki_articles WHERE TEXT_SEARCH(content, 'shandong university', 'natural_language') > 0; id | content ----+--------------------------------------------------------------------- 7 | Shandong has dozens of universities. 2 | Li was born in 1962 in Wendeng County, Shandong. 3 | He graduated from the department of physics at Shandong University. 8 | ShanDa is a famous university of Shandong. -- (N2) 自然語言查詢:關鍵詞匹配,必須(同時包含'shandong'和'university')或者包含'文化'才匹配。AND運算子優先順序大於OR。 SELECT * FROM wiki_articles WHERE TEXT_SEARCH(content, '(shandong AND university) OR 文化', 'natural_language') > 0; -- 等價於 SELECT * FROM wiki_articles WHERE TEXT_SEARCH(content, 'shandong AND university OR 文化', 'natural_language') > 0; -- 等價於 SELECT * FROM wiki_articles WHERE TEXT_SEARCH(content, '(+shandong +university) 文化', 'natural_language') > 0; -- 返回結果 id | content ----+--------------------------------------------------------------------- 8 | ShanDa is a famous university of Shandong. 7 | Shandong has dozens of universities. 3 | He graduated from the department of physics at Shandong University. 6 | 2006年,春節被國務院批准為第一批國家級非物質文化遺產。 -- (N3) 自然語言查詢:關鍵詞匹配,必須包含'shandong',必須不包含'university',可以包含'文化'。 -- 在這個查詢中'文化'關鍵詞前沒有+, -符號,不會影響哪些行會匹配上,但會影響匹配分數,帶有'文化'的匹配分數更高。 SELECT * FROM wiki_articles WHERE TEXT_SEARCH(content, '+shandong -university 文化', 'natural_language') > 0; id | content ----+-------------------------------------------------- 2 | Li was born in 1962 in Wendeng County, Shandong. -- 必須包含'shandong',必須不包含'physics',可以包含'famous'。包含famous的相關性分數更高。 -- 註:此Query為單Shard下的分數計算結果,不同的Shard數,不同的檔案組織,計算出來的BM25分數可能不一樣。 SELECT id, content, TEXT_SEARCH(content, '+shandong -physics famous', 'natural_language') as score FROM wiki_articles WHERE TEXT_SEARCH(content, '+shandong -physics famous', 'natural_language') > 0 ORDER BY score DESC; -- 返回結果 id | content | score ----+--------------------------------------------------+---------- 8 | ShanDa is a famous university of Shandong. | 2.92376 7 | Shandong has dozens of universities. | 0.863399 2 | Li was born in 1962 in Wendeng County, Shandong. | 0.716338 -- (N4) 自然語言查詢:短語檢索,與(P1)等價,短語需用雙引號""包裹,如果中間有",則需使用\轉義。 SELECT * FROM wiki_articles WHERE TEXT_SEARCH(content, '"shandong university"', 'natural_language') > 0; -- 返回結果 id | content ----+--------------------------------------------------------------------- 3 | He graduated from the department of physics at Shandong University. -- (N5) 自然語言查詢:短語檢索,與(P2)等價,支援以~文法設定slop SELECT * FROM wiki_articles WHERE TEXT_SEARCH(content, '"shandong university"~23', 'natural_language') > 0; -- 返回結果 id | content ----+--------------------------------------------------------------------- 8 | ShanDa is a famous university of Shandong. 7 | Shandong has dozens of universities. 3 | He graduated from the department of physics at Shandong University. -- (N6) 自然語言查詢:匹配所有文檔 SELECT * FROM wiki_articles WHERE TEXT_SEARCH(content, '*', 'natural_language') > 0; -- 返回結果 id | content ----+---------------------------------------------------------------------------------------------- 1 | 長江是中國第一大河,世界第三長河,全長約6,300公裡。 2 | Li was born in 1962 in Wendeng County, Shandong. 3 | He graduated from the department of physics at Shandong University. 4 | 春節,即農曆新年,是中國最重要的傳統節日。 5 | 春節通常在西曆1月下旬至2月中旬之間。春節期間的主要習俗包括貼春聯、放鞭炮、吃年夜飯、拜年等。 6 | 2006年,春節被國務院批准為第一批國家級非物質文化遺產。 7 | Shandong has dozens of universities. 8 | ShanDa is a famous university of Shandong.術語查詢。
-- (T1) 術語查詢:分詞結果中,有明確包含"春節",可以檢索到 SELECT * FROM wiki_articles WHERE TEXT_SEARCH(content, '春節', 'term') > 0; -- 返回結果 id | content ----+---------------------------------------------------------------------------------------------- 4 | 春節,即農曆新年,是中國最重要的傳統節日。 5 | 春節通常在西曆1月下旬至2月中旬之間。春節期間的主要習俗包括貼春聯、放鞭炮、吃年夜飯、拜年等。 6 | 2006年,春節被國務院批准為第一批國家級非物質文化遺產。 -- (T2) 術語查詢:無法查詢到結果的樣本 -- 因為檢索源表wiki_articles列content預設使用jieba分詞器,會將"shandong university"拆分。 -- 推薦term術語查詢和keyword分詞器搭配,該情境即可檢索到目標資料。 SELECT * FROM wiki_articles WHERE TEXT_SEARCH(content, 'shandong university', 'term') > 0; -- 返回結果 id | content ----+---------
複雜查詢樣本
與PK聯集查詢。
-- 檢索源中包含shandong或university,且id=3的文本。 SELECT * FROM wiki_articles WHERE TEXT_SEARCH(content, 'shandong university') > 0 and id = 3; -- 返回結果 id | content ----+--------------------------------------------------------------------- 3 | He graduated from the department of physics at Shandong University. -- 檢索源中包含shandong或university,或id<2的文本。 SELECT * FROM wiki_articles WHERE TEXT_SEARCH(content, 'shandong university') > 0 OR id < 2; -- 返回結果 id | content ----+--------------------------------------------------------------------- 2 | Li was born in 1962 in Wendeng County, Shandong. 8 | ShanDa is a famous university of Shandong. 1 | 長江是中國第一大河,世界第三長河,全長約6,300公裡。 3 | He graduated from the department of physics at Shandong University. 7 | Shandong has dozens of universities.查出分數,並取TOP3。
SELECT id, content, TEXT_SEARCH(content, 'shandong university') AS score, TOKENIZE(content, 'jieba') FROM wiki_articles ORDER BY score DESC LIMIT 3; -- 返回結果 id | content | score | tokenize ----+---------------------------------------------------------------------+---------+-------------------------------------------------- 8 | ShanDa is a famous university of Shandong. | 2.74634 | {shanda,famous,univers,shandong} 7 | Shandong has dozens of universities. | 2.74634 | {shandong,has,dozen,univers} 3 | He graduated from the department of physics at Shandong University. | 2.38178 | {he,graduat,from,depart,physic,shandong,univers}同時在output和where中使用TEXT_SEARCH函數。
SELECT id, content, TEXT_SEARCH(content, 'shandong university') AS score, TOKENIZE(content, 'jieba') FROM wiki_articles WHERE TEXT_SEARCH(content, 'shandong university') > 0 ORDER BY score DESC; -- 返回結果 id | content | score | tokenize ----+---------------------------------------------------------------------+---------+-------------------------------------------------- 7 | Shandong has dozens of universities. | 2.74634 | {shandong,has,dozen,univers} 8 | ShanDa is a famous university of Shandong. | 2.74634 | {shanda,famous,univers,shandong} 3 | He graduated from the department of physics at Shandong University. | 2.38178 | {he,graduat,from,depart,physic,shandong,univers} 2 | Li was born in 1962 in Wendeng County, Shandong. | 1.09244 | {li,born,1962,wendeng,counti,shandong}檢索wiki來源中,和shandong university最相關的文檔。
-- 來源表,用於JOIN。 CREATE TABLE article_source (id int primary key, source text); INSERT INTO article_source VALUES (1, 'baike'), (2, 'wiki'), (3, 'wiki'), (4, 'baike'), (5, 'baike'), (6, 'baike'), (7, 'wiki'), (8, 'paper'), (9, 'http_log'), (10, 'http_log'), (11, 'http_log'); SELECT a.id, source, content, TEXT_SEARCH(content, 'shandong university') AS score, TOKENIZE(a.content, 'jieba') FROM wiki_articles a JOIN article_source b ON (a.id = b.id) WHERE TEXT_SEARCH(a.content, 'shandong university') > 0 AND b.source = 'wiki' ORDER BY score DESC; -- 返回結果 id | source | content | score | tokenize ----+--------+---------------------------------------------------------------------+---------+-------------------------------------------------- 7 | wiki | Shandong has dozens of universities. | 2.74634 | {shandong,has,dozen,univers} 3 | wiki | He graduated from the department of physics at Shandong University. | 2.38178 | {he,graduat,from,depart,physic,shandong,univers} 2 | wiki | Li was born in 1962 in Wendeng County, Shandong. | 1.09244 | {li,born,1962,wendeng,counti,shandong}
不同分詞器樣本
使用預設jieba分詞器,預設為search模式,會多分詞型提高搜尋效果。
SELECT TOKENIZE('他來到北京清華大學', 'jieba'); -- 返回結果 tokenize -------------------------------------- {他,來到,北京,清華,華大,大學,清華大學}使用自訂的exact模式的jieba分詞器,不會多分出詞型。
SELECT TOKENIZE('他來到北京清華大學', 'jieba', '{"tokenizer": {"type": "jieba", "mode": "exact"}}'); -- 返回結果 tokenize ----------------------- {他,來到,北京,清華大學}分詞器對比(各自使用預設配置)。
SELECT TOKENIZE('他來到北京清華大學', 'jieba') as jieba, TOKENIZE('他來到北京清華大學', 'ik') as ik, TOKENIZE('他來到北京清華大學', 'keyword') as keyword, TOKENIZE('他來到北京清華大學', 'whitespace') as whitespace, TOKENIZE('他來到北京清華大學', 'simple') as simple, TOKENIZE('他來到北京清華大學', 'standard') as standard, TOKENIZE('他來到北京清華大學', 'icu') as icu, TOKENIZE('他來到北京清華大學', 'ngram') as ngram, TOKENIZE('他來到北京清華大學', 'pinyin') as pinyin; -- 返回結果 -[ RECORD 1 ]-------------------------------------------------------------------- jieba | {他,來到,北京,清華,華大,大學,清華大學} ik | {他,來到,北京,清華大學,清華,大學} keyword | {他來到北京清華大學} whitespace | {他來到北京清華大學} simple | {他來到北京清華大學} standard | {他,來,到,北,京,清,華,大,學} icu | {他,來到,北京,清華大學} ngram | {他,他來,來,來到,到,到北,北,北京,京,京清,清,清華,華,華大,大,大學,學} pinyin | {ta,tldbjqhdx,lai,dao,bei,jing,qing,hua,da,xue}對http_logs的分詞效果對比。
SELECT TOKENIZE('211.11.X.X - - [1998-06-21T15:00:01-05:00] \"GET /english/index.html HTTP/1.0\" 304 0', 'jieba') as jieba, TOKENIZE('211.11.X.X - - [1998-06-21T15:00:01-05:00] \"GET /english/index.html HTTP/1.0\" 304 0', 'ik') as ik, TOKENIZE('211.11.X.X - - [1998-06-21T15:00:01-05:00] \"GET /english/index.html HTTP/1.0\" 304 0', 'keyword') as keyword, TOKENIZE('211.11.X.X - - [1998-06-21T15:00:01-05:00] \"GET /english/index.html HTTP/1.0\" 304 0', 'whitespace') as whitespace, TOKENIZE('211.11.X.X - - [1998-06-21T15:00:01-05:00] \"GET /english/index.html HTTP/1.0\" 304 0', 'simple') as simple, TOKENIZE('211.11.X.X - - [1998-06-21T15:00:01-05:00] \"GET /english/index.html HTTP/1.0\" 304 0', 'standard') as standard, TOKENIZE('211.11.X.X - - [1998-06-21T15:00:01-05:00] \"GET /english/index.html HTTP/1.0\" 304 0', 'icu') as icu, TOKENIZE('211.11.X.X - - [1998-06-21T15:00:01-05:00] \"GET /english/index.html HTTP/1.0\" 304 0', 'ngram') as ngram, TOKENIZE('211.11.X.X - - [1998-06-21T15:00:01-05:00] \"GET /english/index.html HTTP/1.0\" 304 0', 'pinyin') as pinyin; -- 返回結果 -[ RECORD 1 ]------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- jieba | {211.11,9.0,1998-06,21t15,00,01-05,00,get,english,index,html,http,1.0,304,0} ik | {211.11.X.X,1998-06-21t15,1998,06,21,t,15,00,01-05,01,05,00,get,english,index.html,index,html,http,1.0,304,0} keyword | {"211.11.X.X - - [1998-06-21T15:00:01-05:00] \\\"GET /english/index.html HTTP/1.0\\\" 304 0"} whitespace | {211.11.X.X,-,-,[1998-06-21T15:00:01-05:00],"\\\"GET",/english/index.html,"HTTP/1.0\\\"",304,0} simple | {211,11,9,0,1998,06,21t15,00,01,05,00,get,english,index,html,http,1,0,304,0} standard | {211.11.X.X,1998,06,21t15,00,01,05,00,get,english,index.html,http,1.0,304,0} icu | {211.11.X.X,1998,06,21t15,00,01,05,00,get,english,index.html,http,1.0,304,0} ngram | {2,21,1,11,1,1.,.,.1,1,11,1,1.,.,.9,9,9.,.,.0,0,"0 "," "," -",-,"- "," "," -",-,"- "," "," [",[,[1,1,19,9,99,9,98,8,8-,-,-0,0,06,6,6-,-,-2,2,21,1,1T,T,T1,1,15,5,5:,:,:0,0,00,0,0:,:,:0,0,01,1,1-,-,-0,0,05,5,5:,:,:0,0,00,0,0],],"] "," "," \\","\\","\\\"","\"","\"G",G,GE,E,ET,T,"T "," "," /",/,/e,e,en,n,ng,g,gl,l,li,i,is,s,sh,h,h/,/,/i,i,in,n,nd,d,de,e,ex,x,x.,.,.h,h,ht,t,tm,m,ml,l,"l "," "," H",H,HT,T,TT,T,TP,P,P/,/,/1,1,1.,.,.0,0,"0\\","\\","\\\"","\"","\" "," "," 3",3,30,0,04,4,"4 "," "," 0",0} pinyin | {211119019980621,211119019980621t,t,1500010500,ge,teng,li,shi,n,de,x,h,t,m,l,h,t,t,p,103040}
使用建議
使用Serverless資源重建索引
如果表屬性修改,可能觸發Compaction並重建索引,帶來大量CPU消耗。如有下列表屬性修改需求,建議按下文步驟操作:
修改bitmap_columns、dictionary_encoding_columns、向量索引,均會觸發Compaction並重建索引,因此不建議使用ALTER TABLE xxx SET文法修改,建議執行如下命令,通過Rebuild文法、使用Serverless Computing資源執行,詳情參見REBUILD。
ASYNC REBUILD TABLE <table_name>
WITH (
rebuild_guc_hg_computing_resource = 'serverless'
)
SET (
bitmap_columns = '<col1>,<col2>',
dictionary_encoding_columns = '<col1>:on,<col2>:off',
vectors = '{
"<col_vector>": {
"algorithm": "HGraph",
"distance_method": "Cosine",
"builder_params": {
"base_quantization_type": "rabitq",
"graph_storage_type": "compressed",
"max_degree": 64,
"ef_construction": 400,
"precise_quantization_type": "fp32",
"use_reorder": true,
"max_total_size_to_merge_mb" : 4096
}
}
}'
);修改列式JSONB列、全文索引列,也會觸發Compaction並重建索引,暫不支援通過Rebuild文法執行,建議通過建立暫存資料表方案修改,詳見如下步驟:
BEGIN ;
-- 清理潛在的暫存資料表
DROP TABLE IF EXISTS <table_new>;
-- 建立暫存資料表
SET hg_experimental_enable_create_table_like_properties=on;
CALL HG_CREATE_TABLE_LIKE ('<table_new>', 'select * from <table>');
COMMIT ;
-- 對應列開啟列式JSONB
ALTER TABLE <table_new> ALTER COLUMN <column_name> SET (enable_columnar_type = ON);
-- 對應列建立全文索引
CREATE INDEX <idx_name> ON <table_new> USING FULLTEXT (column_name);
-- 向暫存資料表插入資料,使用Serverless資源執行,並同步完成索引構建
SET hg_computing_resource = 'serverless';
INSERT INTO <table_new> SELECT * FROM <table>;
ANALYZE <table_new>;
BEGIN ;
-- 刪除舊錶
DROP TABLE IF EXISTS <table>;
-- 暫存資料表改名
ALTER TABLE <table_new> RENAME TO <table>;
COMMIT ;修改其他屬性,如distribution_key、clustering_key、segment_key、儲存格式等,均建議通過Rebuild文法、使用Serverless Computing資源執行。
進階操作:自訂分詞器配置
Hologres建議使用分詞器的預設配置,但在全文倒排索引的實際使用過程中,可能出現分詞器預設配置不滿足業務需求的情況。您可自訂分詞器配置,以滿足業務更靈活的分詞需要。
analyzer_params配置要求
分詞器配置參數analyzer_params的配置要求如下:
僅支援JSON格式字串。
JSON頂層支援tokenizer、filter兩個鍵,取值如下:
filter:選填,值為JSON數組,用於配置分詞過濾屬性。如需配置多個分詞過濾屬性,將嚴格遵循配置順序作用到每一個分詞token上。
tokenizer:必填,值為JSON對象,用於配置分詞器屬性。JSON對象中支援如下鍵:
type:必填,分詞器名稱
tokenizer對象的其他參數,不同分詞器支援的參數不同,詳見下表:
分詞器
tokenizer對象
的其他參數參數說明
參數取值
jieba
mode
定義分詞模式。
search(預設):分詞時列舉多種可能的組合,允許冗餘。如“傳統節日”的分詞結果為“傳統”、“節日”和“傳統節日”共3個token。
exact:分詞時不冗餘切分。如“傳統節日”的分詞結果僅為“傳統節日”1個token。
hmm
定義是否使用隱馬爾可夫模型來識別詞典中沒有的詞,以提高新詞識別能力。
true(預設):使用
false:不使用
standard
max_token_length
最大token長度。
正整數,預設值255。如果遇到超過此長度的token,則會以 max_token_length 為間隔進行拆分。
ik
mode
定義分詞模式。
ik_max_word(預設):細粒度分詞,輸出所有可能的短詞。如“南京市”的分詞結果為“南京”和“市”。
ik_smart:粗粒度分詞,優先輸出長詞,減少切分數量。分詞輸出的token之間不會產生重疊。會嘗試將數詞和量片語合,作為一個token輸出。如“南京市”、“1千米”均不繼續分詞。
enable_lowercase
是否將Token轉換成小寫。
true(預設)
false
ngram
min_ngram
Token最小字元長度。
預設為1。正數。與max_ngram差距最大為3。
說明:可通過設定如下GUC,調整最大差距值,如
SET hg_fulltext_index_max_ngram_diff = 5max_ngram
Token最大字元長度。
預設為2。取值範圍[1, 255]。與min_ngram差距最大為3。
說明當max_ngram與min_ngram差距過大時,ngram分詞器會產生大量分詞token,導致資源消耗增大、索引儲存增加、索引構建時間長度增加等問題。
prefix_only
是否只考慮首碼。
true
false(預設)
pinyin
keep_first_letter
是否保留每個漢字的首字母。
true(預設):保留。如“李明”分詞結果包含“lm”。
false:不保留。
keep_separate_first_letter
是否單獨保留每個漢字的首字母。
true:保留。如“李明”分詞結果包含“l,m”。
false(預設):不保留。
limit_first_letter_length
首字母結果Token的最大長度。
保留的首字母串的最大長度。Int類型,預設為16。
keep_full_pinyin
是否保留每個漢字的完整拼音。
true(預設):保留。如“李明”分詞結果包含“li,ming”。
false:不保留。
keep_joined_full_pinyin
是否串連每個漢字的完整拼音。
true:串連。如“李明”分詞結果包含“liming”。
false(預設):不串連。
keep_none_chinese
是否保留結果中的非漢字字母或數字。
true(預設):保留。
false:不保留。
keep_none_chinese_together
是否將非漢字字母或數字保留在一起。
true(預設):保留。如“DJ李明”分詞結包含“DJ,li,ming”,“DJ”串連在一起。
false:不保留如“DJ李明”分詞結果包含“D,J,li,ming”。
說明該參數需將keep_none_chinese設為true才生效。
keep_none_chinese_in_first_letter
是否在首字母Token中保留非漢字字母或數字。
true(預設):保留。如“李明AT2025”分詞結果包含“lmat2025”。
false:不保留。
keep_none_chinese_in_joined_full_pinyin
是否在完整拼音串連的Token中保留非漢字字母或數字。
true:保留。如“李明AT2025”分詞結果包含“limingat2025”。
false(預設):不保留。
none_chinese_pinyin_tokenize
如果非漢字字母是拼音,是否拆分為單獨的拼音詞項。
true(預設):拆分。如“limingalibaba2025”分詞結果包含“li,ming,a,li,ba,ba,2025”
false:不拆分
說明該參數需將keep_none_chinese、keep_none_chinese_together設為true才生效。
keep_original
是否保留原始輸入。
true:保留
false(預設):不保留
lowercase
是否將非漢字字母小寫化處理。
true(預設)
false
trim_whitespace
是否裁剪空白字元。
true(預設)
false
remove_duplicated_term
是否移除重複詞項。
true,移除。如“de的”分詞結果為“de”,但會影響對“de的”的短語查詢結果。
false(預設),不移除。
keep_separate_chinese
是否保留單獨漢字。
true:保留。如“李明”分詞結果包含“李,明”2個Token。
false(預設):不保留。
analyzer_params預設配置
不同分詞器對應的analyzer_params預設配置如下:
分詞器名稱 | analyzer_params預設配置 | 分詞樣本 |
jieba(預設分詞器) | | |
whitespace | | |
keyword | | |
simple | | |
standard | | |
icu | | |
ik | | |
ngram | | |
pinyin | | |
analyzer_params中的filter配置
Hologres支援在analyzer_params中配置如下filter(分詞過濾屬性)。
如果配置了多個分詞過濾屬性,將嚴格遵循配置順序作用到每一個分詞token上。
屬性名稱 | 屬性說明 | 參數格式 | 使用樣本 |
lowercase | 將token中的大寫字母轉為小寫。 | 僅需聲明lowercase。 |
|
stop | 移除停用詞token。 |
|
|
stemmer | 根據對應語言的文法規則,將token轉化為其對應的詞幹。 |
|
|
length | 移除超過指定長度的token。 |
|
|
removepunct | 移除只包含標點符號字元的token。 | 僅需聲明removepunct。 說明 自4.0.8開始, removepunct新增mode參數,定義移除模式,取值如下:
|
|
pinyin | 拼音Token Filter。 | | Filter配置屬性同Pinyin分詞器。 |