mysql中文全文索引
MySQL在高並發連接、數據庫記錄數較多的情況下,SELECT ... WHERE ... LIKE '%...%'的全文搜索方式不僅效率差,而且以通配符%和_開頭作查詢時,使用不到索引,需要全表掃描,對數據庫的壓力也很大。MySQL針對這一問題提供了一種全文索引解決方案,這不僅僅提高了性能和效率(因為MySQL對這些字段做了索引來優化搜索),而且實現了更高質量的搜索。但是,至今為止,MySQL對中文全文索引無法正確支持。 www.2cto.com
中文與西方文字如英文的一個重要區別在於,西方文字以單詞為單位,單詞與單詞之間以空格分隔。而中文以字為單位,詞由一個或多個字組成,詞與詞之間沒有空格分隔。當試圖在一個含有中文字符的字段中使用全文搜索時,不會得到正確的結果,原因在於中文中沒有像英文空格那樣對詞定界,不能以空格作為分割,對中文詞語進行索引。
一、MySQL中文全文索引插件mysqlcft的特點:
1、優點:
①、精准度很高:采用自創的“三字節交叉切分算法”,對中文語句進行分割,無中文分詞詞庫,搜索精准度遠比中文分詞算法高,能達到LIKE '%...%"的准確率。
②、查詢速度快:查詢速度比LIKE '%...%"搜索快3~50倍,文章末尾有測試結果;
③、標准插件式:以MySQL 5.1全文索引的標准插件形式開發,不修改MySQL源代碼,不影響MySQL的其他功能,可快速跟進MySQL新版本;
④、支持版本多:支持所有的MySQL 5.1 Release Candidate版本,即MySQL 5.1.22 RC~最新的MySQL 5.1.25 RC;
⑤、支持字符集:支持包括GBK、GB2312、UTF-8、Latin1、BIG5在內的MySQL字符集(其他字符集沒有測試過);
⑥、系統兼容好:具有i386和x86_64兩個版本,支持32位(i386)和64位(x86_64)CPU及Linux系統; www.2cto.com
⑦、適合分布式:非常適合MySQL Slave分布式系統架構,無詞庫維護成本,不存在詞庫同步問題。
2、缺點:
①、mysqlcft中文全文索引只適用於MyISAM表,因為MySQL只支持對MyISAM表建立FULLTEXT索引;
②、MySQL不能靜態編譯安裝,否則無法安裝mysqlcft插件;
③、基於“三字節交叉切分算法”的索引文件會比海量、ft-hightman等基於“中文分詞算法”的索引文件稍大,但不是大很多。根據我的測試,mysqlcft全文索引的.MYI索引文件是.MYD數據文件的2~5倍。
配置文件中添加
[mysqld]
ft_min_word_len = 1
附:MySQL配置文件在全文索引應用中的優化
[mysqld]
# key_buffer 指定用於索引的緩沖區大小,在全文索引中,增加它可得到更好的索引處理與查詢性能
key_buffer = 512M
# sort_buffer_size 為查詢排序時所能使用的緩沖區大小,全文索引的SQL語句之後通常會使用ORDER BY排序,增加它可以加快SQL語句執行時間。該參數對應的分配內存是每連接獨占,100個連接使用的內存將是32M*100=3200M
sort_buffer_size = 32M
# 對大於可用內存的表執行GROUP BY或ORDER BY操作,應增加read_rnd_buffer_size的值以加速排序操作後面的行讀取
read_rnd_buffer_size = 64M
# 如果表出現故障或索引出錯,REPAIR TABLE時用到的緩沖區大小
myisam_sort_buffer_size = 128M
# 確定使用的filesort算法的索引值大小的限值
max_length_for_sort_data = 64
# MySQL全文索引查詢所用關鍵詞最小長度限制(不要改變這項值)
ft_min_word_len = 1
# 降低UPDATE優先級,設置查詢優先
low_priority_updates = 1
wget http://mysqlcft.googlecode.com/files/mysqlcft-1.0.0-i386-bin.tar.gz
tar zxvf mysqlcft-1.0.0-i386-bin.tar.gz
cp mysqlcft.so /usr/local/mysql1/lib/mysql/plugin/
--安裝引擎
INSTALL PLUGIN mysqlcft SONAME 'mysqlcft.so';
--查看是否安裝成功 www.2cto.com
SELECT * FROM mysql.plugin;
SHOW PLUGINS;
--創建索引
use test
ALTER IGNORE TABLE pa_gposts ADD FULLTEXT INDEX full_text_title(title) WITH PARSER mysqlcft;
--修復索引
REPAIR TABLE pa_gposts QUICK;
性能比較
沒有添加索引之前
SELECT * FROM pa_gposts WHERE MATCH(title) AGAINST ('醫院' IN BOOLEAN MODE) limit 0,30;
4 rows in set (1 min 12.69 sec)
這種查詢出的結果單詞的前後都要有停止字,查詢速度還是很慢,因為沒有索引
mysql> explain SELECT * FROM pa_gposts WHERE MATCH(title) AGAINST ('醫院' IN BOOLEAN MODE) limit 0,30;
+----+-------------+-----------+------+---------------+------+---------+------+--------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-----------+------+---------------+------+---------+------+--------+-------------+
| 1 | SIMPLE | pa_gposts | ALL | NULL | NULL | NULL | NULL | 213193 | Using where |
+----+-------------+-----------+------+---------------+------+---------+------+--------+-------------+
創建索引後
SELECT * FROM pa_gposts WHERE MATCH(title) AGAINST ('醫院' IN BOOLEAN MODE) limit 0,30;
30 rows in set (1.07 sec)
SELECT * FROM pa_gposts WHERE title LIKE '%醫院%' limit 0,30;
30 rows in set (4.81 sec)
mysql> explain SELECT * FROM pa_gposts WHERE title LIKE '%醫院%' limit 0,30;
+----+-------------+-----------+------+---------------+------+---------+------+--------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-----------+------+---------------+------+---------+------+--------+-------------+
| 1 | SIMPLE | pa_gposts | ALL | NULL | NULL | NULL | NULL | 213193 | Using where |
+----+-------------+-----------+------+---------------+------+---------+------+--------+-------------+
mysql> explain SELECT * FROM pa_gposts WHERE MATCH(title) AGAINST ('醫院' IN BOOLEAN MODE) limit 0,30; www.2cto.com
+----+-------------+-----------+----------+-----------------+-----------------+---------+------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-----------+----------+-----------------+-----------------+---------+------+------+-------------+
| 1 | SIMPLE | pa_gposts | fulltext | full_text_title | full_text_title | 0 | | 1 | Using where |
+----+-------------+-----------+----------+-----------------+-----------------+---------+------+------+-------------+
SELECT * FROM pa_gposts WHERE MATCH(title) AGAINST ('情侶' IN BOOLEAN MODE) limit 0,30;
30 rows in set (1.93 sec)
SELECT * FROM pa_gposts WHERE title LIKE '%情侶%' limit 0,30;
30 rows in set (10.17 sec)
SELECT * FROM pa_gposts WHERE MATCH(title) AGAINST ('月光' IN BOOLEAN MODE) limit 0,30;
13 rows in set (0.56 sec)
SELECT * FROM pa_gposts WHERE title LIKE '%月光%' limit 0,30;
13 rows in set (50.98 sec)
布爾全文搜索具有以下特點:
它們不使用 50% 域值。.
它們不會按照相關性漸弱的順序將行進行分類。你可以從上述問詢結果中看到這一點:相關性最高的行是一個包含兩個“MySQL” 的行,但它被列在最後的位置,而不是開頭位置。
即使沒有FULLTEXT,它們仍然可以工作,盡管這種方式的搜索執行的速度非常之慢。
最小單詞長度全文參數和最大單詞長度全文參數均適用。
停止字適用。
布爾全文搜索的性能支持以下操作符:
+
一個前導的加號表示該單詞必須 出現在返回的每一行的開頭位置。
-
一個前導的減號表示該單詞一定不能出現在任何返回的行中。
(無操作符)
在默認狀態下(當沒有指定 + 或–的情況下),該單詞可有可無,但含有該單詞的行等級較高。這和MATCH() ... AGAINST()不使用IN BOOLEAN MODE修改程序時的運作很類似。
> <
這兩個操作符用來改變一個單詞對賦予某一行的相關值的影響。 > 操作符增強其影響,而 <操作符則減弱其影響。請參見下面的例子。
www.2cto.com
( )
括號用來將單詞分成子表達式。括入括號的部分可以被嵌套。
~
一個前導的代字號用作否定符, 用來否定單詞對該行相關性的影響。 這對於標記“noise(無用信息)”的單詞很有用。包含這類單詞的行較其它行等級低,但因其可能會和-號同時使用,因而不會在任何時候都派出所有無用信息行。
*
星號用作截斷符。於其它符號不同的是,它應當被追加到要截斷的詞上。
"
一個被括入雙引號的短語 (‘"’) 只和字面上包含該短語輸入格式的行進行匹配。全文引擎將短語拆分成單詞,在FULLTEXT索引中搜索該單詞。 非單詞字符不需要嚴密的匹配:短語搜索只要求符合搜索短語包含的單詞且單詞的排列順序相同的內容。例如, "test phrase" 符合 "test, phrase"。
若索引中不存在該短語包含的單詞,則結果為空。例如,若所有單詞都是禁用詞,或是長度都小於編入索引單詞的最小長度,則結果為空。
以下例子展示了一些使用布爾全文符號的搜索字符串:
'apple banana'
尋找包含至少兩個單詞中的一個的行。
'+apple +juice'
尋找兩個單詞都包含的行。
'+apple macintosh'
尋找包含單詞“apple”的行,若這些行也包含單詞“macintosh”, 則列為更高等級。
'+apple -macintosh'
尋找包含單詞“apple” 但不包含單詞 “macintosh”的行。
'+apple +(>turnover <strudel)'
www.2cto.com
尋找包含單詞“apple”和“turnover” 的行,或包含“apple” 和“strudel”的行 (無先後順序),然而包含 “apple turnover”的行較包含“apple strudel”的行排列等級更為高。
'apple*'
尋找包含“apple”、“apples”、“applesauce”或“applet”的行。
'"some words"'
尋找包含原短語“some words”的行 (例如,包含“some words of wisdom” 的行,而非包含 “some noise words”的行)。注意包圍詞組的‘"’ 符號是界定短語的操作符字符。它們不是包圍搜索字符串本身的引號。