1. 程式人生 > >mysql百萬級全文索引及match快速查詢

mysql百萬級全文索引及match快速查詢

建立全文索引的表的儲存引擎型別必須為MyISAM

問題是match   against對中文模糊搜尋支援不是太好

新建一個utf8 MyISAM型別的表並建立一個全文索引  :

  1. CREATE TABLE articles (
  2.     id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY,
  3.     title VARCHAR(200),
  4.     body TEXT,
  5.     FULLTEXT (title,body)
  6. ) ENGINE=MyISAM  DEFAULT >

其中FULLTEXT(title, body) 給title和body這兩列建立全文索引,之後檢索的時候注意必須同時指定這兩列。

給這個表新增點測試資料

  1. INSERT INTO articles (title,body) VALUES
  2.     ('MySQL Tutorial','DBMS stands for DataBase ...'),
  3.     ('How To Use MySQL Well','After you went through a ...'),
  4.     ('Optimizing MySQL','In this tutorial we will show ...'),
  5.     ('1001 MySQL Tricks','1. Never run mysqld as root. 2. ...'),
  6.     ('MySQL vs. YourSQL','In the following database comparison ...'),
  7.     ('MySQL Security','When configured properly, MySQL ...');

3. 全文檢索測試

  1. SELECT * FROM articles   WHERE MATCH (title,body) AGAINST ('database'); 

注意 MATCH (title,body) 裡面的值必須是前面建立全文索引的兩個欄位不能少。

mysql 預設支援全文檢索的字元長度是4,可以用SHOW VARIABLES LIKE 'ft_min_word_len' 來檢視指定的字元長度,也可以在mysql配置檔案my.ini 更改最小字元長度,方法是在my.ini 增加一行 比如:ft_min_word_len = 2,改完後重啟mysql即可。  

另外,MySQL還會計算一個詞的權值,以決定是否出現在結果集中,具體如下:

mysql在集和查詢中的對每個合適的詞都會先計算它們的權重,一個出現在多個文件中的詞將有較低的權重(可能甚至有一個零權重),因為在這個特定的集中,它有較低的語義值。否則,如果詞是較少的,它將得到一個較高的權重,mysql預設的閥值是50%,上面‘you’在每個文件都出現,因此是100%,只有低於50%的才會出現在結果集中。

全文檢索語法

SELECT * FROM articles WHERE MATCH (title,body)     AGAINST ('+apple -banana' IN BOOLEAN MODE);   + 表示AND,即必須包含。- 表示NOT,即不包含。

SELECT * FROM articles WHERE MATCH (title,body)     AGAINST ('apple banana' IN BOOLEAN MODE);   apple和banana之間是空格,空格表示OR,即至少包含apple、banana中的一個。

SELECT * FROM articles WHERE MATCH (title,body)     AGAINST ('+apple banana' IN BOOLEAN MODE);   必須包含apple,但是如果同時也包含banana則會獲得更高的權重。

SELECT * FROM articles WHERE MATCH (title,body)     AGAINST ('+apple ~banana' IN BOOLEAN MODE);   ~ 是我們熟悉的異或運算子。返回的記錄必須包含apple,但是如果同時也包含banana會降低權重。但是它沒有 +apple -banana 嚴格,因為後者如果包含banana壓根就不返回。

SELECT * FROM articles WHERE MATCH (title,body)     AGAINST ('+apple +(>banana <orange)' IN BOOLEAN MODE);   返回同時包含apple和banana或者同時包含apple和orange的記錄。但是同時包含apple和banana的記錄的權重高於同時包含apple和orange的記錄

最後如果要模糊搜尋只要在在搜尋的詞後面加上*號就可以,如

"SELECT * FROM table_name WHERE MATCH(column) AGAINST('search*' IN BOOLEAN MODE)"

經測試,非常快速!