全文本搜索
MySQL支持幾種基本的數據庫引擎,但並非所有的引擎都支持全文本搜索。兩個最常使用的引擎為MyISAM和InnoDB,前者支持全文本搜索,后者就不支持。
理解全文本搜索
在前面的學習中,我們都知道有兩種方式來匹配文本。一種是使用like關鍵字來進行匹配,另外一種就是使用正則表達式來進行匹配。
雖然使用正則表達式就可以編寫查找所需行的足夠復雜的匹配模式。但是,這些存在幾個重要的限制影響:
1、性能:通配符和正則表達式時嘗試匹配表中所有行,而這些搜索極少使用了表索引,因此,相當慢
2、明確控制:在匹配過程中,我們很少會相當的明確的知道我們想匹配什么,不匹配什么。
3、具有優先級的結果:在使用通配符和正則表達式進行匹配時,只是返回包含該匹配條件的結果,而不區分匹配程度(多個匹配和單個匹配的區別,在前面就匹配和在后面匹配的區別)。
上面提到的這些限制,都可以利用全文本搜索來進行解決。
使用全文本搜索
為了進行全文本搜索,必須索引被搜索的列,而且要隨着數據的改變不斷地重新索引。
在對表進行適當的設計之后,MySQL會自動進行所有的索引和重新索引。
在索引之后,select可與match() 和against()一起使用以實際執行索引。
那么,在建表的時候,如何啟用全文本搜索支持呢???
如下:
上面就這樣通過fulltext 為指定行建立的相應的索引,如果,想指定多個列,將多個列都放入fulltext里面即可。
在定義之后,MySQL會自動維護該索引。無論是在增加、更新還是刪除,索引也會隨之更新。
進行全文本搜索
上面在建表后此表就有了全文本搜索的能力了,下面我們開始嘗試下全文本搜索。
在索引之前,我為test_text表增加了如下內容:
當我們想利用全文本搜索得到 包含MySQL內容的數據。
如下:
select * from test_text where match(content) against('MySQL');
上面語句中 match(content) 指示MySQL針對指定的列進行搜索,注意:傳遞給match()的值必須與fulltext()定義中的相同。against(‘MySQL’)指定詞MySQL作為搜索文本。
從結果可以看出,我們得到了兩行包括MySQL字符串的數據。
上面的搜索利用我們學過的Like也可以完成,如下:
這兩種方法的結果是一樣的。次序也一樣,理論上來說,利用全文本搜索會對出來的結果按照優先級來進行排序輸出,但是從結果可以看出,在第一條語句中MySQL出現的位置相比第二條語句中的MySQL的位置還要滯后,為什么會出現在前面呢??,與MySQL必知必會上面介紹的有一點出入
為了驗證上面出現的問題,我們可以查下結果的優先級。在查看優先級之前,我又加入了一個以MySQL開頭的行數據。下面舉來看下優先級。
select id,content,match(content) against('MySQL') from test_text ;
從結果可以看出,確實是id=7的行的優先級大於id=8的優先級,原因在於優先級並不至於出現的先后位置有關系,還與諸如文本長度等因素也有關系。
在增加了一行以MySQL開頭的行數據之后,我們來一起觀察下上面這兩種方法的結果。
從上面兩圖可以明顯看出,確實,利用全文本搜索對搜索到的內容進行一定的排序,而通配符卻沒有進行排序。至於全文本搜索對搜索到的內容進行排序由很多因素來進行決定,比如:出現的位置、出現的次數、文本自身的長度等等。
等級越高,出現的位置就越靠前,在我們生活中使用的搜索引擎(例如百度、google等)進行搜索東西的時候,我相信也是按照這樣的邏輯來出現結果,當然除了百度公司收了別人錢把不匹配的內容人為的放在更前面。
使用查詢擴展:with query expansion
前面介紹的只是普通的全文本搜索。
但是,我們在生活中常常有更嚴格的要求,例如,我希望搜索 的內容包括MySQL字符串,你還想得到與MySQL相關的內容(即使沒有出現MySQL字眼),應該怎么來做呢??
這就需要我們使用查詢擴展了。
用法 :在against(關鍵字 with query expansion) 即可
從結果可以看出,當我們使用了查詢擴展之后,就得到了更多相關的內容,即使這些內容不包括MySQL字眼。
至於MySQL是如何根據MySQL來得到與之相關的關鍵字,目前我還不清楚。
布爾文本搜索
MySQL支持全文本搜索的另外一種形式,稱為布爾方式。以布爾方式,可以提供如下內容的細節:
- 要匹配的詞;
- 要排斥的詞、
- 排列提示(指定某些詞比其他詞更重要,更重要的詞等級更高)
- 表達式分組。
要說明的是:即使沒有fulltext索引也可以使用,只是速度相當相當的慢。
為顯示 in boolean mode的作用,以一個簡單的例子來進行說明。
select * from test_text where match(content) against('MySQL -interesting' in boolean mode);//返回必須包含MySQL不能包含interesting內容的數據。
關於全文本布爾操作符,見下表(來源於:《MySQL必知必會》這本書)
關於全文本布爾操作符的具體使用實例,與上面的例子類似,這里不在進行具體介紹。
全文本搜索的使用說明
1、MySQL帶有一個內建的非用詞列表。這些詞在索引全文本數據時總是被忽略。如果需要,可以覆蓋這個列表。
2、許多詞出現的頻率很高,搜索他們沒有用處(因為返回太多的結果)。因此,MySQL規定了一條50%規則,如果一個詞出現在50%以上的行中,則將它作為一個非用詞忽略。50%規則不用於in boolean mode.
3、如果表中的數據的行數小於3行,則全文本搜索不返回結果。因此每個詞要么不出現,出現就至少為50%。
4、忽略詞中的單引號。例如:don’t 索引為dont。