程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 數據庫知識 >> MYSQL數據庫 >> 關於MYSQL數據庫 >> 適宜做簡單搜索的MySQL數據庫全文索引

適宜做簡單搜索的MySQL數據庫全文索引

編輯:關於MYSQL數據庫

 全文索引在 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 |

+----+------------------------------+-------------------------------------+

| 1 | MySQL Tutorial | DBMS stands for DataBase ... |

| 2 | How To Use MySQL EfficIEntly | After you went through a ... |

| 3 | Optimising MySQL | In this tutorial we will show ... |

| 4 | 1001 MySQL Tricks | 1. Never run MySQLd as root. 2. ... |

| 6 | MySQL Security | When configured properly, MySQL ... |

+----+------------------------------+-------------------------------------+

 


這個查詢返回所有包含詞 MySQL 的記錄行(注意: 50% 的阈值沒有使用),但是它沒有包含詞 YourSQL。注意,一個邏輯模式的搜索不會自動地以相似值的降序排序記錄行。你可以從上面的結果出看得出來,最高的相似值(包含 MySQL 兩次的那個) 最列在最後,而不是第一位。一個邏輯全文搜索即使在沒有一個 FULLTEXT 索引的情況下也可以工作,然而它慢些。


邏輯全文搜索支持下面的操作符:“+” 一個領頭的加號表示,該詞必須出現在每個返回的記錄行中,“-” 一個領頭的減號表示,該詞必須不出現在每個返回的記錄行中。


缺省的 (當既沒有加號也沒有負號被指定時)詞是隨意的,但是包含它的記錄行將被排列地更高一點。這個模仿沒有 IN BOLEAN MODE 修飾詞的 MATCH() ... AGAINST() 的行為。


< > 這兩個操作符用於改變一個詞的相似性值的基值。< 操作符減少基值,> 操作符則增加它。參看下面的示例。


( ) 圓括號用於對子表達式中的詞分組。


~一個領頭的否定號的作用象一個否定操作符,引起行相似性的詞的基值為負的。它對標記一個噪聲詞很有用。一個包含這樣的詞的記錄將被排列得低一點,但是不會被完全的排除,因為這樣可以使用 - 操作符。


* 一個星號是截斷操作符。不想其它的操作符,它應該被追加到一個詞後,不加在前面。


" 短語,被包圍在雙引號"中,只匹配包含這個短語(字面上的,就好像被鍵入的)的記錄行。


這裡是一些示例:


apple banana


找至少包含上面詞中的一個的記錄行


1.+apple +juice ... 兩個詞均在被包含

2.+apple macintosh ... 包含詞 “apple”,但是如果同時包含 “Macintosh”,它的排列將更高一些

3.+apple -macintosh ... 包含 “apple” 但不包含 “Macintosh”

4.+apple +(>pIE 5.apple* ... 包含 “apple”,“apples”,“applesauce” 和 “applet”

6."some words" ... 可以包含 “some words of wisdom”,但不是 “some noise Words”


全文的限制


* MATCH() 函數的所有參數必須是從來自於同一張表的列,同時必須是同一個FULLTEXT 索引中的一部分,除非 MATCH() 是 IN BOOLEAN MODE 的。


* MATCH() 列列表必須確切地匹配表的某一 FULLTEXT 索引中定義的列列表,除非 MATCH() 是 IN BOOLEAN MODE 的。


* AGAINST() 的參數必須是一個常量字符串。


微調MySQL全文搜索


不幸地,全文搜索仍然只有很少的用戶可調參數,雖然增加一些在 TODO 上排列很高。如果你有一個 MySQL 源碼發行(查看章節 2.3 安裝一個 MySQL 源碼發行),你可以發揮對全文搜索的更多控制。


注意,全文搜索為最佳的搜索效果,被仔細地調整了。修改默認值的行為,在大多數情況下,只會使搜索結果更糟。不要修改 MySQL 的源代碼,除非你知道你在做什麼!


* 被索引的詞的最小長度由 MySQL 變量 ft_min_Word_len 指定。查看章節 4.5.6.4 SHOW VARIABLES。將它改為你所希望的值,並重建你的 FULLTEXT 索引。 (這個變量只從 MySQL 4.0 開始被支持)


* stopword 列表可以從 ft_stopword_file 變量指定的文件中讀取。查看章節 4.5.6.4 SHOW VARIABLES。在修改了 stopWord 列表後,重建你的 FULLTEXT 索引。(這個變量只從 MySQL 4.0.10 開始被支持)


* 50% 阈值選擇由所選擇的特殊的衡量模式確定。為了禁止它,修改 `myisam/ftdefs.h' 文件中下面的一行:

#define GWS_IN_USE GWS_PROB


改為:


#define GWS_IN_USE GWS_FREQ


然後重新編譯 MySQL。在這種情況下,不需要重建索引。 注意:使用了這個,將嚴重地減少 MySQL 為 MATCH() 提供足夠的相似性值的能力。如果你確實需要搜索這樣的公共詞,最好使用 IN BOOLEAN MODE 的搜索代替,它不遵守 50% 的阈值。


* 有時,搜索引擎維護員希望更改使用於邏輯全文搜索的操作符。這些由變量 ft_boolean_syntax 定義。然而,這個變量是只讀的,它的值在 `myisam/ft_static.c' 中被設置。


對於這些更改,要求你重建你的 FULLTEXT 索引,對於一個 MyISAM 表,最容易的重建索引文件的方式如下面的語句:

MySQL> REPAIR TABLE tbl_name QUICK;


全文搜索 TODO * 使所有對 FULLTEXT 索引的操作更快


* 鄰近(Proximity)操作符


* 對 "always-index Words" 的支持。他們可以是用戶希望視為一個詞處理的任意字符串,例如 "C++"、"AS/400"、"TCP/IP",等等


* 支持在 MERGE 表中的全文搜索


* 對多字節字符的支持


* 依照數據的語言建立 stopWord 列表


* Stemming (當然,依賴於數據的語言)


* Generic user-suppliable UDF preparser.


* 使模式更加靈活 (通過為 CREATE/ALTER TABLE 中的 FULLTEXT 增加某些可調整參數)

 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved