近日,OceanBase 4.3.5 BP1 版本正式推出了企業級全文索引功能。該版本在中文分詞、查詢效率及混合檢索能力上進行了全面提升。經過自然語言模式和布爾模式在不同場景下的對比測試,OceanBase 的全文索引性能明顯優于 MySQL。?
點擊下載? OceanBase 社區版 4.3.5 BP1 >>?
全文索引(Full-Text Index),是一種專為加速數據庫中文本數據檢索而設計的特殊索引類型,尤其擅長處理包含大量文本字段(例如文章內容、評論、博客等)的查詢請求。它能夠支持高效的關鍵詞匹配查詢,允許在文本中搜索一個或多個詞語,并迅速返回相關結果。全文索引廣泛應用于搜索引擎和文本分析系統中,助力企業和用于迅速查找關鍵信息,顯著提升搜索效率。
在企業的實際生產中,全文索引功能可以應用于系統日志分析、用戶分析等眾多場景,全文索引能夠對數據做到高效率過濾篩選、或是高質量相關性評估。在 AI 領域,OceanBase 基于稀疏稠密向量與全文索引相結合的多路召回架構,能在具有特殊知識領域的?RAG?系統中實現更高效、更精準的召回效果。本文將深入解析其背后的技術原理,并展示其在實踐中的表現。
一、全文索引企業級功能四大核心價值
最新版本的全文索引,在以下方面幫助用戶解決更多搜索使用上的痛點:
🚩 支持分區表,索引數據和分區數據就近存儲,提高性能。
🚩 支持主表上建立多種混合索引(普通二級、全文、多值、向量等),一套數據應對不同查詢目標和加速場景。
🚩 支持 IK 中文分詞器和詞典修改,在一些需要中文專業術語的業務里,字典維護和匹配更加易用和精準。
🚩 支持常用的自然語言和布爾模式,性能優于 MySQL,功能與性能兩方面支撐業務做平替。
二、核心技術解析:BM25算法與查詢優化
數據庫中全文索引要解決的基本問題是如何通過查詢里的關鍵詞快速有效地找到對應的文檔。在 OceanBase ?存儲引擎內部,用戶的文檔(doc)會被分詞器(parser)拆分成若干關鍵詞(word/token)。這些關鍵詞連同文檔的統計信息特征被存儲在內部的輔助表(tablet)上,用于信息檢索階段的相關性評估算法(ranking)。OceanBase 采用能夠更好評估信息關聯性的 BM25 算法,對用戶查詢語句中的關鍵詞和存儲的文檔計算相關性分數,并最終輸出有關聯的文檔和其評分。
結合 OceanBase 已有的高性能查詢引擎能力,在全文索引查詢流程內,我們針對性地做了 TAAT/DAAT 流程優化、對標 Oracle 的 functional lookup 功能以及多索引間的 index merge 等,讓全文能結合更多復雜的查詢特性,完成用戶想要的數據檢索。
三、實戰測評:以中文體育新聞搜索為例
接下來,我們以中文體育新聞搜索為例,動手體驗 OceanBase 的全文索引,同時展示常用的視圖和查詢技巧。
集群部署與數據導入
首先用最新版 OceanBase 4.3.5 BP1 搭建兩副本,一個 2C4G 的 MySQL 模式租戶。
OceanBase 內置支持中文語言的 IK 分詞器,以及比傳統自然語言模式更好用的布爾模式。所以實驗的數據集使用中文足球體育新聞(https://github.com/ej0cl6/SportsSum)。在 OceanBase 內創建一張無主鍵分區表,包含三列變長字符串(event,date,news)。對 news 字段使用了 IK 中文分詞器,并指定 max_word 模式。IK 分詞器的另一種 smart 模式,和 max_word 的區別是,其在匹配到最長詞語后就停止匹配更短的詞語。
OceanBase 內置分詞器還包括適合英語的 space 和 beng。以及按照字符長度分割的 ngram。
-- 建表語句
CREATE?TABLE?sport_data_whole(
? event?varchar(64),
??date?varchar(16),
? news?varchar(65535),
? fulltext INDEX (news)?WITH?parser ik PARSER_PROPERTIES?=(ik_mode?=?"max_word")
);
通過客戶端本地文件的方式,將新聞數據集導入到表格內,時間大概在十五秒左右。
-- 導入語句
load data?/*+ parallel(8) */
??local?infile "/home/jiahua.cjh/sports_data_whole.csv"
??into?table?sport_data_whole
? fields terminated?by?','?lines terminated?by?'\n';
導入后共 5268 條新聞,平均文檔長度在 2700 個中文字。原始數據是 57MB 左右。實際存儲的總空間大小,在經過存儲引擎的壓縮后,連同索引不到 30MB。可以看到其中比較大的是全文索引中倒排和正排輔助表,內部存儲了比較多的分詞記錄。
-- 體育新聞數據集
select
? avg(length(news)),
? count(*)
from
? sport_data_whole;
+-------------------+----------+
| avg(length(news)) | count(*) |
+-------------------+----------+
| ? ? ? ? 2781.6900 | ? ? 5268 |
+-------------------+----------+
1 row in set (0.03 sec)
select
? *
from
? oceanbase.DBA_OB_TABLE_SPACE_USAGE\G
*************************** 1. row ***************************
? ? ?TABLE_ID: 500007
DATABASE_NAME: test
? ?TABLE_NAME: sport_data_whole
? OCCUPY_SIZE: 8349796
REQUIRED_SIZE: 10489856
*************************** 2. row ***************************
? ? ?TABLE_ID: 500008
DATABASE_NAME: test
? ?TABLE_NAME:?__idx_500007_news
? OCCUPY_SIZE: 30247553
REQUIRED_SIZE: 31461376
*************************** 3. row ***************************
? ? ?TABLE_ID: 500009
DATABASE_NAME: test
? ?TABLE_NAME: __idx_500007_fts_rowkey_doc
? OCCUPY_SIZE: 70125
REQUIRED_SIZE: 77824
*************************** 4. row ***************************
? ? ?TABLE_ID: 500010
DATABASE_NAME: test
? ?TABLE_NAME: __idx_500007_fts_doc_rowkey
? OCCUPY_SIZE: 73171
REQUIRED_SIZE: 77824
*************************** 5. row ***************************
? ? ?TABLE_ID: 500011
DATABASE_NAME: test
? ?TABLE_NAME:?__idx_500007_news_fts_doc_word
? OCCUPY_SIZE: 28302737
REQUIRED_SIZE: 29364224
利用全文索引查詢
利用存儲進數據庫中的新聞數據集和索引,可以做多條件自由組合,達到高過濾性信息檢索的目的。例如作為球迷,想搜索包含有 “拜仁” 和 “烏龍球” 的新聞,推薦使用布爾模式。相較于沒有索引的字符串 like 匹配,布爾模式語法上更簡潔易懂,查詢速度也會更快。
-- 布爾模式
select
??count(*)
from
? sport_data_whole
where
??match?(news) against ('+烏龍球 +拜仁'?in?boolean?mode);
+----------+
|?count(*)?|
+----------+
|? ? ? ??2?|
+----------+
1?row?in?set?(0.03?sec)
select
??count(*)
from
? sport_data_whole
where
? news?like?'%烏龍球%'
??and?news?like?'%拜仁%';
+----------+
|?count(*)?|
+----------+
|? ? ? ??2?|
+----------+
1?row?in?set?(0.08?sec)
對于返回的多條新聞,在輸出結果中增加分值,能用來幫助判斷哪條新聞更有關聯。OceanBase 的全文支持經過 BM25 算法計算得到的相關性分數。下面可以看到 date 是 0278 的新聞,和我們查詢的目的更具關聯性。
-- ranking
select
? event,
??date,
??match?(news) against ('烏龍球 拜仁')?as?score
from
? sport_data_whole
where
??match?(news) against ('+烏龍球 +拜仁'?in?boolean?mode);
+-------+------+---------------------+
|?event?|?date?|?score ? ? ? ? ? ? ??|
+-------+------+---------------------+
|?ucl ??|?0278?|??0.4657063867776557?|
|?ucl ??|?0201?|?0.41760566608994765?|
+-------+------+---------------------+
2?rows?in?set?(0.04?sec)
布爾模式相較于自然語言,還能反向剔除一些關鍵詞。例如每場足球比賽中幾乎都有犯規行為,如果想知道哪些比賽很激烈,但是沒有紅黃牌甚至沒有犯規,則可以用到布爾模式里的 “-” 運算符。
-- 布爾模式運算
select
??count(*)
from
? sport_data_whole
where
??match?(news) against ('+激烈 -黃牌 -紅牌 -犯規'?in?boolean?mode);
+----------+
|?count(*)?|
+----------+
|? ? ? ?31?|
+----------+
1?row?in?set?(0.04?sec)
一個調試的小技巧,當發現全文索引的查詢結果不符合預期時,通常是因為分詞結果不理想。OceanBase 提供了一個快速的 TOKENIZE 函數來輔助測試分詞結果。函數支持所有分詞器和對應屬性。例如下面手動的分詞結果,反映了詞典中對于國外體育明星人名的支持還不是很好(博阿滕、格策),因此用這些人名去檢索新聞的效果可能達不到預期。
-- tokenize 函數
select
? tokenize(
? ??'博阿滕右路反擊人球分過傳中,格策后點停球轉身閃開角度,在門前8米處低射從皮亞托夫襠下鉆進門內',
? ??'ik',
? ??'[{"additional_args": [{"ik_mode": "smart"}]}]'
? );
+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|?tokenize('博阿滕右路反擊人球分過傳中,格策后點停球轉身閃開角度,在門前8米處低射從皮亞托夫襠下鉆進門內',?'ik',?'[{"additional_args": [{"ik_mode": "smart"}]}]') ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?|
+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|?["亞", "格", "夫", "阿", "門內", "從", "下鉆", "后點", "右路", "分過", "傳中", "低", "轉身", "球", "射", "閃開", "博", "進", "反擊", "門前", "停", "人", "皮", "襠", "策", "滕", "8米處", "托", "在", "角度"] ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??|
+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1?row?in?set?(0.03?sec)
select
??count(*)
from
? sport_data_whole
where
??match?(news) against ('+格策 +博阿滕'?in?boolean?mode);
+----------+
|?count(*)?|
+----------+
|? ? ? ??0?|
+----------+
1?row?in?set?(0.04?sec)
如果想提升分詞器的精準性,OceanBase 支持修改系統詞典表。當我們將上述中文人名插入到系統詞典表后,重新分詞的效果立竿見影。
🧡 注意:詞典修改后,原索引分詞效果不變,需要重建索引生效。
-- 中文人名分詞效果
select
? tokenize(
? ??'博阿滕右路反擊人球分過傳中,格策后點停球轉身閃開角度,在門前8米處低射從皮亞托夫襠下鉆進門內',
? ??'ik',
? ??'[{"additional_args": [{"ik_mode": "smart"}]}]'
? );
+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|?tokenize('博阿滕右路反擊人球分過傳中,格策后點停球轉身閃開角度,在門前8米處低射從皮亞托夫襠下鉆進門內',?'ik',?'[{"additional_args": [{"ik_mode": "smart"}]}]') ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?|
+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|?["門內", "從", "下鉆", "后點", "右路", "分過", "傳中", "低", "轉身", "球", "皮亞托夫", "射", "閃開", "進", "反擊", "門前", "停", "人", "襠", "8米處", "在", "角度", "格策", "博阿滕"] ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??|
+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1?row?in?set?(0.04?sec)
select
??count(*)
from
? sport_data_whole
where
??match?(news) against ('+格策 +博阿滕'?in?boolean?mode);
+----------+
|?count(*)?|
+----------+
|? ? ? ?79?|
+----------+
1?row?in?set?(0.05?sec)
實驗最后,對全文索引與普通索引混合查詢下 union merge 帶來的性能提升做一個對比。對 sport_data_whole 表的 date 列再建立一個普通局部索引。可以通過 show index 觀察索引生效情況。
-- 構建普通索引
alter table sport_data_whole add index (date);
show index from sport_data_whole\G
*************************** 1. row ***************************
? ? ? ? Table: sport_data_whole
? ?Non_unique: 1
? ? ?Key_name: news
?Seq_in_index: 1
? Column_name: news
? ? Collation: A
? Cardinality: NULL
? ? ?Sub_part: NULL
? ? ? ?Packed: NULL
? ? ? ? ?Null: YES
? ?Index_type: FULLTEXT
? ? ? Comment: available
Index_comment:
? ? ? Visible: YES
? ?Expression: NULL
*************************** 2. row ***************************
? ? ? ? Table: sport_data_whole
? ?Non_unique: 1
? ? ?Key_name: date
?Seq_in_index: 1
? Column_name: date
? ? Collation: A
? Cardinality: NULL
? ? ?Sub_part: NULL
? ? ? ?Packed: NULL
? ? ? ? ?Null: YES
? ?Index_type: BTREE
? ? ? Comment: available
Index_comment:
? ? ? Visible: YES
? ?Expression: NULL
2 rows in set (0.00 sec)
當兩個索引條件使用 OR 連接時,過濾性好的情況下,union merge 帶來的收益會比掃描普通索引后再過濾(計劃中有 has_functional_lookup=true)更快。從兩種計劃最后預估的時間上可以看到有數量級的提升。
-- union merge 計劃對比
explain
select
??/*+UNION_MERGE(sport_data_whole date news)*/
??*
from
? sport_data_whole
where
??date?=?'0322'
??or?(match?(news) against ('+烏龍球'?in?boolean?mode));
+-------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|?Query Plan ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?|
+-------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|?===================================================================================? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?|
|?|ID|OPERATOR ? ? ? ? ? ? ? ? ? ?|NAME ? ? ? ? ? ? ? ? ? ? ??|EST.ROWS|EST.TIME(us)|? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?|
|?----------------------------------------------------------------------------------- ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? |
|?|0?|DISTRIBUTED INDEX?MERGE?SCAN|sport_data_whole(date,news)|45? ? ??|9102? ? ? ??|? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?|
|?===================================================================================? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?|
|?Outputs?&?filters: ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?|
|?------------------------------------- ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? |
|? ?0?-?output([sport_data_whole.event], [sport_data_whole.date], [sport_data_whole.news]),?filter([sport_data_whole.date?=?'0322'?OR?MATCH(sport_data_whole.news) ?|
|? ? ? ?AGAINST('+烏龍球'?IN?BOOLEAN?MODE)]), rowset=256? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??|
|? ? ? ?access([sport_data_whole.__pk_increment], [sport_data_whole.date], [sport_data_whole.news], [sport_data_whole.event]), partitions(p0) ? ? ? ? ? ? ? ? ? ? ??|
|? ? ? ?is_index_back=true, is_global_index=false, keep_ordering=true, use_index_merge=true, filter_before_indexback[false], ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?|
|? ? ? ?index_name:?date, range_cond([sport_data_whole.date?=?'0322']),?filter(nil) ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??|
|? ? ? ?index_name: news, range_cond(nil),?filter(nil) ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?|
|? ? ? ?lookup_filter([sport_data_whole.date?=?'0322'?OR?MATCH(sport_data_whole.news) AGAINST('+烏龍球'?IN?BOOLEAN?MODE)]) ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?|
+-------------------------------------------------------------------------------------------------------------------------------------------------------------------+
14?rows?in?set?(0.03?sec)
explain
select
??*
from
? sport_data_whole
where
??date?=?'0322'
??or?(match?(news) against ('+烏龍球'?in?boolean?mode));
+-------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|?Query Plan ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?|
+-------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|?===========================================================? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?|
|?|ID|OPERATOR ? ? ??|NAME ? ? ? ? ? ?|EST.ROWS|EST.TIME(us)|? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?|
|?----------------------------------------------------------- ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? |
|?|0?|TABLE?FULL?SCAN|sport_data_whole|79? ? ??|526939? ? ??|? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?|
|?===========================================================? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?|
|?Outputs?&?filters: ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?|
|?------------------------------------- ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? |
|? ?0?-?output([sport_data_whole.event], [sport_data_whole.date], [sport_data_whole.news]),?filter([sport_data_whole.date?=?'0322'?OR?MATCH(sport_data_whole.news) ?|
|? ? ? ?AGAINST('+烏龍球'?IN?BOOLEAN?MODE)]), rowset=256? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??|
|? ? ? ?access([sport_data_whole.__pk_increment], [sport_data_whole.date], [sport_data_whole.news], [sport_data_whole.event]), partitions(p0) ? ? ? ? ? ? ? ? ? ? ??|
|? ? ? ?is_index_back=false, is_global_index=false, filter_before_indexback[false], ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??|
|? ? ? ?range_key([sport_data_whole.__pk_increment]),?range(MIN ; MAX)always?true, has_functional_lookup=true? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?|
+-------------------------------------------------------------------------------------------------------------------------------------------------------------------+
12?rows?in?set?(0.04?sec)
四、性能對比:OceanBase 遠超 MySQL
OceanBase 的全文索引性能橫向比較如何?我們以 MySQL 的全文索引為例。MySQL 的中文分詞能力不是很好,因此對比數據集選定在英文數據集 wikir1k(369721行,平均每行100詞)上。以下分別是自然語言模式,以及布爾模式下多種場景的對比結果。
結果上:
💡 OceanBase 在需要大量分詞或是返回結果的場景中,都遠優于 MySQL。
💡 小結果集上,因為計算量占比不高,查詢引擎的優勢不明顯,兩者十分接近。
測試環境如下:
-
OceanBase 租戶規格 8c 16g
-
MySQL Ver 8.0.36 for Linux on x86_64 (MySQL Community Server - GPL)
自然語言模式???????
# Query
# q1
select?*?from?wikir1k?where?match?(document)?against?('and');
# q2
select?*?from?wikir1k?where?match?(document)?against?('and') limit 10;
# q3
select?*?from?wikir1k?where?match?(document)?against?('librettists');
# q4
select?*?from?wikir1k?where?match?(document)?against?('librettists') limit 10;
# q5
select?*?from?wikir1k?where?match?(document)?against?('alleviating librettists');
# q6
select?*?from?wikir1k?where?match?(document)?against?('black spotted white yellow');
# q7
select?*?from?wikir1k?where?match?(document)?against?('black spotted white yellow') limit 10;
# q8
select?*?from?wikir1k?where?match?(document)?against?('between up and down');
# q9
select?*?from?wikir1k?where?match?(document)?against?('between up and down') limit 10;
# q10
select?*?from?wikir1k?where?match?(document)?against?('alleviating librettists modifications retelling intangible hydrographic administratively berwickshire strathaven dumfriesshire lesmahagow transhumanist musselburgh prestwick cardiganshire montgomeryshire');
# q11
select?*?from?wikir1k?where?match?(document)?against?('alleviating librettists modifications retelling intangible hydrographic administratively berwickshire strathaven dumfriesshire lesmahagow transhumanist musselburgh prestwick cardiganshire montgomeryshire and');
# q12
select?*?from?wikir1k?where?match?(document)?against?('alleviating librettists modifications retelling intangible hydrographic administratively berwickshire strathaven dumfriesshire lesmahagow transhumanist musselburgh prestwick cardiganshire montgomeryshire and') limit 10;
布爾模式
# Query
# q1: +高頻詞 -中頻詞
select?*?from?wikir1k?where?match?(document)?against?('+and -which -his'?IN BOOLEAN MODE);?
# q2: +高頻詞 -低頻詞
select?*?from?wikir1k?where?match?(document)?against?('+which ?(+and -his)'?IN BOOLEAN MODE);?
# q3: +中頻詞 (+高頻詞 -中頻詞)
select?*?from?wikir1k?where?match?(document)?against?('+and -carabantes -bufera'?IN BOOLEAN MODE);
# q4: +高頻詞 +低頻詞?
select?*?from?wikir1k?where?match?(document)?against?('+and +librettists'? IN BOOLEAN MODE);
五、未來路線:OceanBase 全文索引將持續演進
OceanBase 全文索引的能力還遠不止于此,結合新的技術趨勢和新的數據檢索場景,在后續版本,我們還會推出更多易用性功能。例如:
🔎 能支持交集能力的全面的 index merge;
🔎 以插件方式支持更豐富流行的多語言分詞器;
🔎 更靈活的用戶自定義詞典和停詞;
🔎 更常用的 term query、phrase query,compound query 功能;
🔎 在檢索方面,結合 OceanBase 的多模稀疏向量,進一步增強文檔的語義理解力;
🔎 使用多路召回、動態剪裁以及底層例如 WAND 的加速算法,在質量和速度兩個方面提升檢索體驗等等。
全文索引不僅是數據庫能力的延伸,更是企業實現數據智能化的關鍵基礎設施。經過全面升級的 OceanBase 全文索引,在中文處理能力、混合查詢性能、生產可用性等方面已建立顯著優勢。
無論是在傳統日志分析場景,還是結合 AI 的智能檢索需求,OceanBase 的全文索引都能提供企業級解決方案。未來,OceanBase 將持續深化"數據庫+搜索+AI"的技術融合,助力企業構建新一代智能數據平臺。