資料庫 MySQL 全文檢索 開放原始碼

介接專攻中日韓語系引擎 行欄位面向高效資料庫索引

MySQL外掛Mroonga 全文檢索搜尋中文更有力

2022-05-18
開放原始碼MySQL是非常歡迎的資料庫管理系統,但是當使用全文檢索的方式來搜尋中文字時,效能表現上似乎差強人意,為此本文將介紹一款MySQL的外掛程式Mroonga。結合Mroonga之後,MySQL伺服器就能夠提供高效能的中文全文檢索功能。

相信提起開源碼社群上的資料庫解決方案,許多人腦海裡的第一時間應該會浮現MySQL(官方網址:https://www.mysql.com/),挾其優異的性能,早已大量運用在資料庫解決方案上。但就筆者的使用經驗而言,MySQL對於使用全文檢索(Full Index)在搜尋中文字的應用上表現似乎比較不理想。因此,在本文中將說明如何利用Mroonga(官方網址為https://mroonga.org/)為MySQL伺服器加上高效能的中文全文檢索功能。

什麼是全文檢索

一般來說,若要增進資料庫的效率,最方便有效的方法就是利用索引(Index)的方式,先從原有資料中取出部分資料,再重新加以組織為索引資料,使其能對應到原始資料,在要尋找資料時即可採用搜尋索引資料的方式,再利用其對應的資訊來找到原始資料。

由於索引的資料量遠小於原始資料量,因此可大幅地提升搜尋的效率。就如同查詢字典的用法,如果要搜索字典中的某個單字時,若此字典未建立相關的索引資料(如拼音表或部首檢字表),那就只能整本字典從頭查詢到尾。

反之,如果有建立如部首檢字表的資料,便可利用查詢部首檢字表中的資訊,很快地查詢到相對應的資料。而全文檢索即是利用相同的概念,首先對原始資料進行分詞(亦即須區分原始資料中個別的單詞)並建立相關索引資訊,但因為須多增加儲存索引資料的額外空間,所以在儲存作業上會增加相關的處理時間及儲存空間等成本。但在建立完成後,就能夠有效地利用索引資料來增進查詢資料的效率。

上述的分詞作業,會因不同的語言,而面臨到不同的困難,因此通常會將自然語言分為以下兩種類型:

‧Use word delimiter language:此類語言單詞與單詞之間有天然的分隔符(Delimiter),以英語為例,在每個單字之間均以空格符號來區分。要處理此種語言僅須以空格符號來當做分隔符進行分詞(Tokenize)操作即可。

‧Ideographic language:不同於有天然的分隔符的語言,此類語言單詞之間沒有分隔符,例如CJK(Chinese、Japanese、Korean)語言,因此必須使用外掛的處理模組,才能有效地處理,如本文中所介紹的mroonga模組就能夠用來處理CJK語言的分詞。

全文檢索方式

在建立相關索引資料後,即可利用資料庫所提供的全文檢索指令來查詢資料,以MySQL為例,便提供了兩種全文檢索的方式,如下所述:

關鍵字查詢

此為簡單的字串查詢,查詢資料庫內是否有符合關鍵字的紀錄,如下例即為以全文檢索的方式來查詢是否有符合關鍵字的紀錄:

SELECT  *  FROM  [資料庫表格名稱]  WHERE MATCH (“全文檢索的欄位”) AGAINST(“關鍵字”);

布林查詢(IN BOOLEAN MODE)

此種查詢表示可利用運算子(例如+或-)進行邏輯(如AND、OR)的查詢,如下例表示查詢符合關鍵字1及關鍵字2的紀錄:

SELECT  *  FROM  [資料庫表格名稱]  WHERE MATCH (全文檢索的欄位) AGAINST(“+關鍵 字1” “+關鍵字2 “  IN BOOLEAN MODE)

以下例子為表示查詢符合關鍵字1但不會包含關鍵字2的紀錄:

SELECT  *  FROM  [資料庫表格名稱]  WHERE MATCH (全文檢索的欄位) AGAINST(“+關鍵 字1” “-關鍵字2” IN BOOLEAN MODE)

在了解查詢模式後,接著可利用「show variables like  'ft%'」來查詢MySQL所提供的全文檢索組態設定值,如圖1所示,相關組態的說明如下:

圖1  查詢MySQL所提供的全文檢索組態設定值。

ft_boolean_syntax:表示在使用布林查詢所支援的運算子,例如加號(+)代表須符合而減號(-)代表不須符合。

ft_max_word_len:表示能夠用來分詞的最長索引字串,預設為84個字元,在修改此組態值後,必須再重新建立索引檔案。

ft_min_word_len:表示能夠用來分詞的最短索引字串,預設為4個字元,在修改此組態值後,必須再重新建立索引檔案。

ft_stopword_file:設定不進行全文檢索的過濾詞資料,而相關的過濾詞並不會被全文檢索所搜尋,可利用下列指令來查看目前系統上的過濾詞資料(圖2):

圖2  查看目前系統上的過濾詞資料。

SELECT * FROM INFORMATION_SCHEMA. INNODB_FT_DEFAULT_STOPWORD

何謂Groonga

從系統架構來說,或許可將Mroonga視為Groonga(https://groonga.org/)的外接介面,當Mroonga接收到要求時,便會透過Groonga來完成相關的要求。

Groonga是一套從2012年開始發展,並支援行欄位面向(Column-oriented)的儲存方式及中日韓(CJK)語言全文檢索功能的搜尋引擎。

首先來說明什麼是行欄位面向,資料庫的儲存方式可分為列欄位面向(Row-oriented)和行欄位面向(Column-oriented),相關說明簡述如下:

列欄位面向(Row-oriented)

這是一般最熟悉的資料庫儲存方式,一筆紀錄即為一列儲存完整的資訊,如以個人資料(包含id、姓名及電話欄位)為例:

每一列就是一筆完整的紀錄,在運用上可以快速取得整筆完整紀錄的場合,以此而言,使用者可以id欄位來快速取得整筆完整紀錄。一般熟悉的資料庫如MySQL、MSSQL,均是採用此種的資料儲存方式。

行欄位面向(Column-oriented)

不同於列面向的儲存方式,行欄位面向是以單個欄位的方式來儲存。以上例而言,便會單獨地將「姓名」、「電話」等資料個別儲存起來,未來在取用資料時,就不必像列欄位面向的資料一樣,每次均須掃描整列資料後才能取到相關的資料,因此可大幅減少資料查詢的時間。

除此之外,一般在對資料庫做資料分析時,通常僅會針對某些欄位做分析,而行欄位面向的資料會將資料儲存在不同的檔案或文件,所以在做分析時可直接取得所要的資訊,因此處理資料的效率較高。

認識Mroonga

簡單說明Groonga後,接著繼續來說明Mroonga。Mroonga提供了以存儲引擎模式(Storage Mode)及外接介面模式(Wrapper)的方式來運作,相關說明如下:

存儲模式

本文即是利用將Mroonga實作成MySQL伺服器存儲引擎(如同InnoDB、MyISAM)的方式來存取Mroonga的全文檢索功能,此種方式可完整地與MySQL結合,支援大部分的資料庫操作,並以優異的效能取代如like指令(模糊查詢)。

但要特別注意的是,Mroonga並非為真實的存儲引擎,因此相關的資料,實際上並不會直接儲存在MySQL資料庫上,而是儲存在Groonga中。除此之外,此模式並不支援事務性(Transaction)操作。因此,若有事務性功能需求的作業,並不適用此種模式。

外接介面模式

在此模式下,Mroonga將作為SQL處理模組(SQL Handler)與存儲引擎之間的一個外接介面,並且會處理全文檢索指令,當使用者下達SQL指令後,如果為全文檢索指令,就會將相關指令轉發到Mroonga執行,其他的指令則照原有的流程執行。

安裝Mroonga

在介紹Mroonga後,接著示範如何安裝Mroonga。這裡將以存儲引擎的方式來安裝Mroonga,因此必須先取得MySQL的原始碼,以8.0.26版本為例進行示範。連結至MySQL官方網站取得該版本的原始碼,並且到Mroonga的官方網站(https://packages.groonga.org/source/mroonga/)下載原始碼,(本文使用的版本為11.13)。

在解壓縮後,執行下列指令進行安裝(其中#為註解):

./configure --with-mysql-source=[mysql原 始碼的位置]  --with-mysql-config=[mysql_ config所在位置] make       #編譯相關程式 make install  #安裝至MySQL的模組 (plugin)目錄

成功安裝後,將會在MySQL的模組目錄下產生名稱為「ha_mroonga.so」等檔案。接著,重新啟動MySQL伺服器以便載入mroonga模組。

最後,再匯入Mroonga所提供的install.sql(位於「data」目錄下),來新增相關需要的資料庫表格(Table)。

整個安裝完成後,利用「show engines」指令來查詢MySQL伺服器是否已新增mroonga型態的存儲引擎,如圖3所示。

圖3  查詢MySQL伺服器是否已新增mroonga型態的存儲引擎。

接著執行「SHOW VARIABLES LIKE 'mroonga%'」指令,取得Mroonga所提供相關的組態資訊,如圖4所示。

圖4  取得Mroonga所提供相關的組態資訊。

Mroonga常用組態

以下簡單說明幾個Mroonga常用的組態資訊:

mroonga_action_on_fulltext_query_error

設定當Mroonga運作發生錯誤時,所要執行的動作,提供下列四種選項:

ERROR:當發生錯誤時,僅會告警錯誤而不會將相關資訊記錄下來。

ERROR_AND_LOG:此為預設的選項,在發生錯誤時,不僅告警錯誤,並且會將相關資訊記錄下來。

IGNORE:在發生錯誤時不執行任何動作,即不告警錯誤也不記錄相關資訊。

IGNORE_AND_LOG:在發生錯誤時,僅記錄相關資訊但不會告警錯誤。

mroonga_dry_write

設定是否要將資料實際寫入至Mroonga的資料庫。預設為OFF,表示要實際將資料寫入至資料庫,一般來說,除非是要進行測試,否則並不須要更改此組態選項。

mroonga_database_path_prefix

設定Mroonga資料庫名稱是否要使用前置詞(Prefix),預設為off,這代表不使用。

mroonga_enable_operations_recording

是否啟用回復Groonga資料庫的記錄操作。預設為ON,表示啟用回復功能,在更動相關設定後,須使用FLUSH TABLES讓設定生效。

mroonga_enable_optimization

是否啟用Groonga效能最佳化設定功能,預設為ON,表示啟用最佳化功能。

mroonga_libgroonga_support_lz4

設定是否要支援lz4資料壓縮演算法。

mroonga_libgroonga_support_zlib 

設定是否要支援zlib資料壓縮演算法。

mroonga_libgroonga_version

顯示Mroonga的版本資訊。

mroonga_log_file

設定儲存Mroonga相關紀錄(Log)資訊的檔案位置。

mroonga_log_level

顯示記錄資訊的層級(Level),提供下列層級:

NONE:表示不記錄任何的資料。

EMERG:僅記錄如資料庫毁損等緊急事件資訊的紀錄。

ALERT:記錄如內部發生錯誤等事件資訊的紀錄。

CRIT:記錄如系統發生嚴重錯誤事件資訊的紀錄。

ERROR:將會記錄系統一般錯誤等級的資訊。

WARNING:記錄系統所發生警告等級,但尚未到錯誤等級的資訊。

NOTICE:記錄系統所發生注意等級,但尚未到警告等級的資訊。

INFO:記錄系統所發生的一般資訊。

DEBUG:記錄偵錯所需要的資訊。

DUMP:記錄全部的資訊。

實際測試

安裝至此,MySQL伺服器應已具備Mroonga全文檢索功能,可以實際新建測試資料庫表格來驗證。以下示範便是新建一個具有全文檢索欄位且為mroonga類型的資料庫表格:

CREATE TABLE fulltestable (   id INT NOT NULL AUTO_INCREMENT,   title VARCHAR(255) NOT NULL,   body TEXT,     PRIMARY KEY (id),   FULLTEXT KEY (body)   #設定body為全文檢   索欄位)     ENGINE = mroonga ;   #設定此資料庫表格   為mroonga類型

然後,利用相關的全文檢索指令「SELECT  * FROM fulltestable   WHERE MATCH (body) AGAINST('關鍵字');」來確認是否已成功安裝Mroonga,到這裡就算大功告成了。

<本文作者:吳惠麟,多年資安經驗,喜好利用開源碼建構相關解決方案,著有「資訊安全原理與實驗」等書。>


追蹤我們Featrue us

本站使用cookie及相關技術分析來改善使用者體驗。瞭解更多

我知道了!