全文索引在 MySQL 中是一個FULLTEXT類型索引。FULLTEXT索引用於MyISAM表,可以在CREATE TABLE時或之後使用ALTER TABLE或CREATE INDEX在CHAR、VARCHAR或TEXT列上創建。對於大的數據庫,將數據裝載到一個沒有FULLTEXT索引的表中,然後再使用ALTER TABLE(或CREATE INDEX) 創建索引,這將是非常快的。將數據裝載到一個已經有FULLTEXT索引的表中,將是非常慢的。
全文搜索通過MATCH()函數完成。
mysql> CREATE TABLE articles (
-> id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY,
-> title VARCHAR(200),
-> body TEXT,
-> FULLTEXT (title,body)
-> );
Query OK, 0 rows affected (0.00 sec)
mysql> INSERT INTO articles VALUES
-> (NULL,MySQL Tutorial, DBMS stands for DataBase ...),
-> (NULL,How To Use MySQL Efficiently, After you went through a ...),
-> (NULL,Optimising MySQL,In this tutorial we will show ...),
-> (NULL,1001 MySQL Tricks,1. Never run mysqld as root. 2. ...),
-> (NULL,MySQL vs. YourSQL, In the following database comparison ...),
-> (NULL,MySQL Security, When configured properly, MySQL ...);
Query OK, 6 rows affected (0.00 sec)
Records: 6 Duplicates: 0 Warnings: 0
mysql> SELECT * FROM articles
-> WHERE MATCH (title,body) AGAINST (database);
+----+-------------------+------------------------------------------+
| id | title | body |
+----+-------------------+------------------------------------------+
| 5 | MySQL vs. YourSQL | In the following database comparison ... |
| 1 | MySQL Tutorial | DBMS stands for DataBase ... |
+----+-------------------+------------------------------------------+
2 rows in set (0.00 sec)函數MATCH()對照一個文本集(包含在一個FULLTEXT索引中的一個或多個列的列集)執行一個自然語言搜索一個字符串。搜索字符串做為AGAINST()的參數被給定。搜索以忽略字母大小寫的方式執行。對於表中的每個記錄行,MATCH()返回一個相關性值。即,在搜索字符串與記錄行在MATCH()列表中指定的列的文本之間的相似性尺度。
當MATCH()被使用在一個WHERE子句中時 (參看上面的例子),返回的記錄行被自動地以相關性從高到底的次序排序。相關性值是非負的浮點數字。零相關性意味著不相似。相關性的計算是基於:詞在記錄行中的數目、在行中唯一詞的數目、在集中詞的全部數目和包含一個特殊詞的文檔(記錄行)的數目。
它也可以執行一個邏輯模式的搜索。這在下面的章節中被描述。
前面的例子是函數MATCH()使用上的一些基本說明。記錄行以相似性遞減的順序返回。
下一個示例顯示如何檢索一個明確的相似性值。如果即沒有WHERE也沒有ORDER BY子句,返回行是不排序的。
mysql> SELECT id,MATCH (title,body) AGAINST (Tutorial) FROM articles;
+----+-----------------------------------------+
| id | MATCH (title,body) AGAINST (Tutorial) |
+----+-----------------------------------------+
| 1 | 0.64840710366884 |
| 2 | 0 |
| 3 | 0.66266459031789 |
| 4 | 0 |
| 5 | 0 |
| 6 | 0 |
+----+-----------------------------------------+
6 rows in set (0.00 sec)下面的示例更復雜一點。查詢返回相似性並依然以相似度遞減的次序返回記錄行。為了完成這個結果,你應該指定MATCH()兩次。這不會引起附加的開銷,因為 MySQL 優化器會注意到兩次同樣的MATCH()調用,並只調用一次全文搜索代碼。
mysql> SELECT id, body, MATCH (title,body) AGAINST
-> (Security implications of running MySQL as root) AS score
-> FROM articles WHERE MATCH (title,body) AGAINST
-> (Security implications of running MySQL as root);
+----+-------------------------------------+-----------------+
| id | body | score |
+----+-------------------------------------+-----------------+
| 4 | 1. Never run mysqld as root. 2. ... | 1.5055546709332 |
| 6 | When configured properly, MySQL ... | 1.31140957288 |
+----+-------------------------------------+-----------------+
2 rows in set (0.00 sec)MySQL 使用一個非常簡單的剖析器來將文本分隔成詞。一個“詞”是由文字、數據、“”和“_”組成的任何字符序列。任何在 stopword 列表上出現的,或太短的(3 個字符或更少的)的 “word” 將被忽略。
在集和查詢中的每個合適的詞根據其在集與查詢中的重要性衡量。這樣,一個出現在多個文檔中的詞將有較低的權重(可能甚至有一個零權重),因為在這個特定的集中,它有較低的語義值。否則,如果詞是較少的,它將得到一個較高的權重。然後,詞的權重將被結合用於計算記錄行的相似性。
這樣一個技術工作可很好地工作與大的集(實際上,它會小心地與之諧調)。 對於非常小的表,詞分類不足以充份地反應它們的語義值,有時這個模式可能產生奇怪的結果。
mysql> SELECT * FROM articles WHERE MATCH (title,body) AGAINST (MySQL);
Empty set (0.00 sec)在上面的例子中,搜索詞MySQL卻沒有得到任何結果,因為這個詞在超過一半的記錄行中出現。同樣的,它被有效地處理為一個 stopword (即,一個零語義值的詞)。這是最理想的行為 -- 一個自然語言的查詢不應該從一個 1GB 的表中返回每個次行(second row)。
匹配表中一半記錄行的詞很少可能找到相關文檔。實際上,它可能會發現許多不相關的文檔。我們都知道,當我們在互聯網上通過搜索引擎試圖搜索某些東西時,這會經常發生。因為這個原因,在這個特殊的數據集中,這樣的行被設置一個低的語義值。
到 4.0.1 時,MySQL 也可以使用IN BOOLEAN MODE修飾語來執行一個邏輯全文搜索。
mysql> SELECT * FROM articles WHERE MATCH (title,body)
-> AGAINST (+MySQL -YourSQL IN BOOLEAN MODE);
+----+------------------------------+-------------------------------------+
| id | title | body |
+----+------------------------------+-------------------------------------+