mysql中文進行全文索引支持問題

先來看看對一個字段作全文索引,做爲一個數據庫系統須要作哪些工做?html

假設一個文章表裏面包含幾個字段:文章id、文章做者、文章標題、文章內容mysql

 

好比,咱們對文章內容這個字段artilce_content創建全文索引,這樣方便對文章裏面的內容使用關鍵詞搜索。算法

 

數據庫系統首先須要從文章內容(這個字段內容)中提取關鍵詞,由於只有提取了關鍵詞,纔好創建相似索引目錄—相似於新華字典那樣的筆畫頁碼對應關係,當你搜索一個詞語」beijing」的時候,就直接去索引中查找,而後就能夠定位到數據行的具體位置了,不須要掃描文章表不少行。sql

 

這就像,若是我想去新華字典中查找一個漢字,我直接按照筆畫或者按照拼音來查找(這個就是新華字典的索引),避免把新華字典從頭翻到尾部,這樣的效率多低。沒錯,若是沒有索引,數據庫系統就是須要這樣子遍歷掃描整個表才能獲得數據的。數據庫

 

 

ps:機器實際上是死的,你寫的代碼讓他作什麼就作什麼。而人有眼睛,能夠經過眼睛來看,好比大致翻看一下新華字典,也許眼睛就看到我須要的漢字了呢。服務器

 

 

 

數據庫系統中的關於那個索引結構大致能夠這樣理解:this

 

關鍵詞  包含此關鍵詞的文檔列表(也能夠理解成行)搜索引擎

beijing    1,2,3…插件

 

索引就是方便快速查找,根據這個索引結構,搜索的時候就能夠快速定位到數據位置了。htm

 

mysql對一個字段作全文索引的時候,他從文章內容中提取關鍵詞,

mysql的全文檢索解析器在提取關鍵詞默認是按照空格來識別單詞的。也就是中文」我喜歡打籃球」 這一串文字中沒有空格,那麼mysql不會把這個當成好幾個單詞的。

若是故意進行空格分開,mysql就容易識別處理關鍵詞,好比變成」我 喜歡 打 籃球」

 

像上面這樣子,mysql可能會把籃球當成關鍵詞提取出來進入索引中去。爲何只是可能?有空格只是保證mysql識別成單詞,但會不會創建成索引,其實我不是很清楚。由於沒看過mysql源碼,不是很清楚。

 

由於對文章表的」文章內容」字段創建了成了全文索引,那麼每次往表中新加入一行數據,數據庫系統都會去提取文章新行數據中的文章內容字段,看有沒有關鍵詞,繼續往索引表裏面加單詞或者更新數據。好比原來的索引文件有個單詞」beijing」,如今新加入的文章內容中提取到有beijing這個詞語,那要更新索引表了,意思是記錄下新加的文檔哪裏存在beijing這個詞語。

 

beijing  8,9,10

新加入的文檔id爲20,恰好其中文章內容被提取到了詞語beijing

 

那麼索引就要更新成以下形式:

 

beijing 8,9,20

 

這樣解釋是方便理解,理解就好。

大致是這樣子的模式。具體實現會跟這個存在差別的。把複雜的問題解釋得通俗化,簡單化是而容易理解,是我進行總結的目的。

 

 

ps:mysql的一個表的全部字段的索引數據都在一張一個」表名稱.MYI」文件中。

 

理解了上面的實現原理,

如今也好理解一句話了,這是從mysql手冊中中的一句話:

對於較大的數據集,將你的資料輸入一個沒有FULLTEXT索引的表中,而後建立索引, 其速度比把資料輸入現有FULLTEXT索引的速度更爲快。

 

 

 

我是這麼理解,好比,把100行數據同時插入文章表中,而文章內容字段是創建成全文索引,那麼新插入的數據在入庫的同時,要提取關鍵詞(對文章內容字段),而後更新索引,速度固然會慢下來。關鍵問題就是在插入數據的時候就會去分詞和更新索引。整個insert 操做就會延長時間了。

 

 

 

 

 

 

 

上面已經創建文章內容字段爲全文索引,如今mysql是怎麼進行全文查詢的呢?

 

select  id,title FROM 文章表 WHERE MATCH(article_content) AGAINST ('search keyword')

 

match()中指定字段名稱。表示against()中出現的字符串要去哪一個字段中匹配。這裏能夠指定多個字段

 

against()中的字符串,難道不是單個詞語,mysql會自動對受到的字符串進行分詞嗎?

 

AGAINST ('+MySQL -YourSQL' IN BOOLEAN MODE);

+號表示,MYSQL這個單詞必須出如今每一行的開頭位置?

‘’裏面是單詞,多個單詞之間須要使用空格分開嗎?

 

 

 

 

 

 

來看看對英文進行分詞有什麼自然優點

 

 

英文的特色,每一個英文單詞就是一個詞語,單詞與單詞之間有很是明顯的分割符號—空格

 

好比

my  name is wangxiaoming

this city is beijing…..

 

 

 

citye 和beijing能夠當作是兩個關鍵詞,用來搜索

 

mysql內部對要提取關鍵詞的時候,哪些能夠做爲關鍵詞來創建索引呢?

它能夠以空格來分割開來。把city 和 beijing都當成是兩個關鍵詞來創建索引(理解成新華字典中的筆畫與頁數的目錄結構)。

 

 

總結一下

 

英文:除了少數特殊字符和標點幾乎都是以空格分隔的,因此要對一段英文進行分詞(也就是從中提取關鍵詞),這樣子比較容易。按照空格、逗號等特別的符號來識別便可。

 

 

 

 

來看看,中文分詞爲何就比較麻煩

 

 

 

 

因爲中文比較特殊,像」理髮師」 理髮能夠是一個關鍵詞,理髮師也能夠是一個關鍵詞。關鍵詞之間並無明顯的分割符號,咱們看到緊挨着的。這就須要mysql去提取哪些是關鍵詞。是把」理」發做爲關鍵詞來索引,仍是」理髮」或者」理髮師」都算關鍵詞,無法識別。

通常百度這些搜索引擎是怎麼提取關鍵詞,他們有個專門的關鍵詞庫的,也就是中文關鍵詞詞庫。這樣就知道把什麼當成是關鍵詞。顯然,mysql是又國外人作的一個軟件,它不會單獨給你去作一個關鍵詞庫。

 

計算機怎麼知道哪一個算是詞語呢?好比輸入一串文字 」我來自北京,我很喜歡運動、聽音樂…,喜歡聽周華健的歌曲」

 

在這一句話中,北京算不算關鍵詞呢。」周華健」算不算關鍵詞呢?

 

像咱們常見的中文切詞,我瞭解到有幾種分詞算法:

 

一、  就是根據詞庫來進行對比的。

二、  二元分詞法

三、  統計法

 

對比:二元分詞方法和統計方法是不依賴於詞典的,而最大匹配法分詞方法是依賴於詞典的,詞典的內容決定分詞結構的好壞。

 

 

 

 

 

 

 

如今總結一下:MySQL不會斷中文字:MySQL內建的字依據是空白、逗號和點來斷詞語。

 

mysql手冊中原文以下:

FULLTEXT分析程序會經過尋找某些分隔符來肯定單詞的起始位置和結束位置,例如' ' (間隔符號)、 , (逗號)以及 . (句號 )。假如單詞沒有被分隔符分開,(例如在中文裏 ), 則 FULLTEXT 分析程序不能肯定一個詞的起始位置和結束位置。爲了可以在這樣的語言中向FULLTEXT 索引添加單詞或其它編入索引的術語,你必須對它們進行預處理,使其被一些諸如"之類的任意分隔符分隔開

…………………

諸如漢語和日語這樣的表意語言沒有自定界符。所以, FULLTEXT分析程序不能肯定在這些或其它的這類語言中詞的起始和結束的位置。其隱含操做及該問題的一些工做區在12.7節,「全文搜索功能」有詳細論述。

 

==================================結束

中文與西方文字如英文的一個重要區別在於,西方文字以單詞爲單位,單詞與單詞之間以空格分隔。而中文以字爲單位,詞由一個或多個字組成,詞與詞之間沒有空格分隔。當試圖在一個含有中文字符的字段中使用全文搜索時,不會獲得正確的結果,緣由在於中文中沒有像英文空格那樣對詞定界,不能以空格做爲分割,(因而不方便)對中文詞語進行索引。

 

 

 

 

 

 

 

如今概括一下,mysql不能很好地支持中文全文索引的解決辦法

 

一、針對對myql全文檢索解析器內建機制特色,白癡解決方法是,存中文字時自行塞入空白斷字。

這樣就適應了mysql的切詞機制了。不過這樣子作比較彆扭。由於哪有把」我是中國人」古意分開成」我 是 中國人」這樣的形式呢。

顯示文章內容的時候就比較彆扭,不能顯示成」我 是 中國人」給用戶看,須要須要本身再次處理。

 

 

二、使用切詞插件。mysql應該是意識到單靠本身來提供分詞,永遠沒法知足世界上各類各樣語言的特殊需求。因而從5.1版本開始,Mysql全文檢索的解析器以插件的方式提供。讓你們能夠以插件的形式掛到mysql下面去(實際上就是做爲mysql的一個存儲引擎,好比sphinx就是插件掛上去)

 

 

掛載到mysql中的插件所完成是一個什麼樣的角色呢?

 使用插件,就是能夠按照你本身的方式去分詞

 

當數據量很大的時候,比較成熟的作法是使用專門的全文索引系統,用這些專業的全文索引系統來分詞,以mysql數據庫中的數據做爲數據源,來分詞創建索引結構。查詢的時候,先從全文索引系統中查詢,獲取文檔編號,而後根據文檔編號去mysql中查詢數據。對於全文搜索插件sphinx-for-chinese,曾經在公司的服務器上配置過,經過那次配置加深了對它的理解。中途遇到一些問題,一直想以文字的形式總結出來,以備忘。有時間會上一篇關於它的操做總結出來。

 

我的理解不正確之處,歡迎指正!

本文未完待補充

相關文章
相關標籤/搜索