MySQL-全文本搜索(學習如何使用MySQL的全文本搜索功能進行高級的數據查詢。)

  並不是全部引擎都支持全文本搜索MySQL。與全部其餘的DBMS同樣,MySQL具備一個具體管理和處理數據的內部引擎。在你使用CREATE TABLE語句時,該引擎具體建立表,而在你使用SELECT語句或進行其它的數據庫處理時,該引擎在內部處理你的請求。多數時候,該引擎都隱藏在DBMS內,不須要過多關注它。html

  但MySQL與其它的DBMS不同,它具備多種引擎。它打包多個引擎,這些引擎都隱藏在MySQL服務器內,全都能執行CREATE TABLE與SELECT命令。mysql

  爲何要發行多種引擎呢?由於它們具備不一樣的功能和特性,爲不一樣的任務選擇正確的引擎得到良好的功能和靈活性。正則表達式

  固然,你能夠忽略這些數據庫引擎。若是省略ENGINE=語句,則使用默認引擎(極可能是MyISAM),多數SQL語句都會默認使用它。但不是全部的語句都默認使用它,這就是爲何ENGINE=語句很重要的緣由。sql

  如下是幾個須要知道的引擎:數據庫

  1.InnoDB是一個可靠的事務處理引擎,它不支持全文本搜索。服務器

  2.MEMORY在功能等同於MyISAM,但因爲數據存儲在內存(不是磁盤)中,速度很快(特別適合於臨時表)函數

  3.MyISAM是一個性能極高的引擎,它支持全文本搜索,但不支持事務處理。性能

  所支持引擎的完整列表(及它們之間的不一樣),請參閱(http://dev.mysql.com/doc/refman/5.0/en/storage_engines.html)spa

 

  LIKE關鍵字,利用通配操做符匹配文本(和部分文本)。使用LIKE,可以查找包含特殊值或部分值得行(無論這些值位於列內的什麼位置)。設計

  用基於文本的搜索做爲正則表達式匹配列值,使用正則表達式,能夠編寫查找所需行的很是複雜的匹配模式。

  雖然這些搜索機制很是有用,但存在幾個重要的機制。

  1.性能:通配符和正則表達式匹配一般要求MySQL嘗試匹配表中全部行(並且這些搜索極少使用表索引)。所以,因爲被搜索行數不斷增長,這些搜索可能很是耗時。

  2.明確控制:使用通配符和正則表達式匹配,很難(並且並不老是能)明確地控制匹配什麼和不匹配什麼。例如,指定一個詞匹配和指定一個詞不匹配....

  3.智能化的結果:雖然基於通配符和正則表達式的搜索提供了很是靈活的搜索,但它們都不能提供一種智能化的選擇結果的方法。例如:一個特殊詞的搜索將會返回包含這些詞的全部行,而不區分包含單個匹配的行和包含多個匹配的行(按照多是更好地匹配來排列它們)。相似,一個特殊詞的搜索將不會找出不包含該詞但包含其餘相關詞的行。

  全部這些限制以及更多的限制均可以用全文本搜索來解決,在使用全文本搜索時,MySQL不須要分別查看每一個行,不須要分別分析和處理每一個詞。MySQL建立指定列中各詞的一個索引,搜索能夠針對這些詞進行。這樣,MySQL能夠快速有效的決定那些詞分配(那些行包含它們),那些詞不匹配,它們匹配的頻率,等等。

  使用全文本搜索

  爲了進行全文本搜索,必須索引被搜索的列,並且要隨着數據的改變不斷從新索引。在對錶列進行適當的設計後,MySQL會自動進行全部的索引和從新索引。

  在索引以後,SELECT可與Match()和Against()一塊兒使用以實際執行搜索。

  啓用全文本搜索

  通常在建立表時啓用全文本搜索。CREATE TABLE接受FULLTEXT字句,它給出被索引列的一個逗號分隔的列表。

  下面的CREATE語句演示了FULLTEXT字句的使用:

CREATE TABLE productnotes           
(
    note_id int NOT NULL AUTO_INCREMENT,
    prod_id char(10) NOT NULL,
    note_text text NOT NULL,
    note_date datetime NOT NULL,
    PRIMARY KEY(note_id),
    FULLTEXT(note_text)
)ENGINE=MyISAM;

  這些列中有一個名爲note_text的列,爲了進行全文本搜索,MySQL根據字句FULLTEXT(note_text)的指示對它進行了索引,這裏的FULLTEXT索引單個列,若是須要也能夠指定多個列。

  在定義以後,MySQL自動維護該索引。在增長、更新或刪除行時,索引隨之自動更新。

  能夠在建立表時指定FULLTEXT,或者在稍後指定。可是不要在導入數據時使用FULLTEXT,由於更新索引須要時間,雖然不是不少,但畢竟要花時間。若是正在導入數據到一個新表,此時不該該啓用FULLTEXT索引。應該首先導入全部數據,而後在修改表,定義FULLTEXT,這要有助於更快地導入數據(並且使索引的總時間小於在導入每行每行時分別進行索引所需的總時間)。

  進行全文本搜索

  在索引以後,使用兩個函數Match()和Against()函數執行全文本搜索,其中Match指定被搜索的列,Against指定要使用的搜索表達式。

SELECT note_text
 FROM productnotes
WHERE Match(note_text) Against('rabbit');

  輸出:note_text

  此SELECT語句檢索單個列note_text。因爲WHERE子句,一個全文本搜索被執行。Match(note_text)指示MySQL針對指定的列進行搜索,Against('rabbit')指定詞rabbit做爲搜索文本)。因爲有兩行包含詞rabbit,這兩個行被返回。

  注意:使用完整的Match()說明,傳遞給Match()的值必須與FULLTEXT()定義中的相同。若是指定多個列,則必須列出它們(並且次序必須正確)。

  搜索不區分大小寫,除非使用BINARY方式,不然全文本搜索不區分大小寫。

  事實是剛纔的搜索能夠簡單的用LIKE子句完成,以下所示:

SELECT note_text
FROM productnotes
WHERE note_text LIKE '%rabbit%';

  檢索結果相同,可是次序不一樣!(雖然並非老是出現這種狀況);

  已知上述兩條SELECT語句都不包含ORDER BY子句。後者(LIKE)以不特別有用的順序返回數據。前者(使用全文本搜索)返回以文本匹配的良好程度排序的數據。兩個行都包含詞rabbit,但包含詞rabbit做爲第3個詞的行的等級比做爲第20個詞的行高。這很重要,全文本搜索的一個重要部分就是對結果進行排序,具備較高等級的行先返回(由於這些多是你真正想要的行)。

  如何查看等級呢?以下所示:

SELECT note_text,Match(note_text) Against('rabbit') AS rank
FROM productnotes

  這裏,在SELECT而不是WHERE子句中石油Match()和Against()。這使全部行都被返回(由於沒有WHERE子句)。Match()和Against()用來簡歷一個計算列(別名爲rank),此列包含全文本搜索計算出的等級值。等級由MySQL根據行的數目計算出來。正如縮減,不包含rabbit的行等級爲0。確實包含rabbit的兩行都有一個等級值,文本中詞靠前的行等級比詞靠後的行的等級值高。

  這個例子有助於說明全文本搜索如何排除行(排除那些等級爲0的行),如何排序結果(按等級以降序排序)

  排序多個搜索項:若是指定多個搜索項,則包含多數匹配詞的那些航將具備比包含較少詞(或僅有一個匹配)的哪些行高的等級值。

  正如所見,全文本搜索提供了簡單的LIKE搜索所不能提供的功能。並且,因爲數據時索引的,全文本搜索還至關快

  使用查詢擴展

  查詢擴展是用來設法放寬所返回的全文本搜索結果的範圍。在使用查詢擴展時,MySQL對數據和索引進行兩邊掃描來完成搜索。

  1.首先,進行一個基本的全文本搜索,找出與搜索條件匹配的全部行。

  2.其次,MySQL檢查這些匹配行並選擇全部有用的詞。(什麼是有用?無用?

  3.再其次,MySQL再次進行全文本搜索,此次不只使用原來的條件,並且還使用有用的詞。

  利用查詢擴展,能找出全部可能相關的結果,即時它們並不精確包含全部查找的詞。

  查詢擴展功能是MySQL4.1.1中引入的。所以不能用於以前的版本。

SELECT note_text
FROM productnotes
WHERE Match(note_text) Against('anvils' WITH QUERY EXPANSION)

  布爾文本搜索

  MySQL支持全文本搜索的另外一種形式:稱爲布爾方式(boolean mode)。以布爾方式,能夠提供關於以下內容的細節:

  1.要匹配的詞;

  2.要排斥的詞(若是某行包含這個詞,則不反含該行,即時它包含其餘指定的詞也是如此);

  3:排列提示:(指定某些詞比其它詞更重要,更重要的詞的等級高);

  4:表達式分組;

  5:另一些內容;

  布爾文本搜索即便沒有FULLTEXT索引也可使用,布爾方式不一樣於迄今爲止使用的全文本搜索搜索語法的地方在於,即便沒有定義FULLTEXT索引,也可使用它。但這是一種很是緩慢的操做(其性能將隨着數據量的添加而下降)。

  爲演示IN BOOLEAN MODE的做用,例子以下:

SELECT note_text
FROM productnotes
WHERE Match(note_text) Against('heavy' IN BOOLEAN MODE);

  此全文本搜索檢索包含詞heavy的全部行(有兩行)。其中使用了關鍵字IN BOOLEAN MODE,但實際上沒有指定布爾操做符,所以,其結果與沒有指定布爾方式的結果相同。

  爲了匹配包含heavy但不包含任意以rope開始的詞的全部行,可以使用以下查詢:

SELECT note_text
FROM productnotes
WHERE Match(note_text) Against('heavy -rope*' IN BOOLEAN MODE);

  咱們已經看到可兩個全文本搜索布爾操做符 - 和 * ,- 排除一個詞,而 * 是截斷操做符(可想象爲用於詞尾的一個通配符)。下列所見爲MySQL支持的布爾操做符:

                             全文本布爾操做符

布爾操做符 說明
+ 包含,詞必須存在
- 排除,詞必須不出現
> 包含,並且增長等級值
< 包含,且減小等級值
() 把詞組成子表達式(容許這些子表達式做爲一個組被包含、排除、排列等)
~ 取消一個詞的牌謔值
* 詞尾的通配符
"" 定義一個短語(與單個詞的列表不同,它匹配整個短語以便包含或排除這個短語)

  

 下面舉幾個例子,說明這些操做符如何使用:

  

SELECT note_text
FROM productnotes
WHERE Match(note_text) Against('+rabbit +bait' IN BOOLEAN MODE);
這個搜索匹配包含詞rabbit和bait的行


SELECT note_text
FROM productnotes
WHERE Match(note_text) Against('rabbit bait' IN BOOLEAN MODE);
沒有指定操做符,這個搜索匹配包含詞rabbit和bait中的至少一個詞的行;


SELECT note_text
FROM productnotes
WHERE Match(note_text) Against('「rabbit bait」' IN BOOLEAN MODE);
這個搜索匹配短語rabbit bait,而不是匹配兩個詞;



SELECT note_text
FROM productnotes
WHERE Match(note_text) Against('>rabbit <carrot' IN BOOLEAN MODE);
這個搜索匹配rabbit 和carrot,增長前者的等級,下降後者的等級;


SELECT note_text
FROM productnotes
WHERE Match(note_text) Against('+safe +(<combination)' IN BOOLEAN MODE);
這個搜索匹配safe 和combination,下降後者的等級;

  全文本搜索數據時,短詞被忽略並且從索引中刪除。短詞定義爲那些具備3個或者3個如下字符的詞(若是須要,這個數目能夠修改)。

  許多詞出現的頻率高,搜索它們沒有用處(返回太多的結果),所以,MySQL定義了一條50%的規則,若是一個詞出如今50%以上的行中,則將它做爲一個非用詞忽略。50%規則不用於IN BOOLEAN MODE

  若是表中的行數小於3行,則全文本搜索將不返回結果(由於每一個詞或者不出現,或者至少出如今50%的行中)。

  忽略詞中的單引號 ' 。

  盡在MyISAM的數據庫引擎中支持全文本搜索。

相關文章
相關標籤/搜索