1. 程式人生 > >MySQL5.6 InnoDB中文全文索引測試

MySQL5.6 InnoDB中文全文索引測試

InnoDB引擎對FULLTEXT索引的支援是MySQL5.6新引入的特性,之前只有MyISAM引擎支援FULLTEXT索引。對於FULLTEXT索引的內容可以使用MATCH()…AGAINST語法進行查詢。但是無法支援中文全文索引,本文將進行簡單測試

中文全文索引測試

表結構如下

CREATE TABLE `tb_customer_3` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `register_name` varchar(100) NOT NULL COMMENT '工商名',
  `brand_name` varchar(100) DEFAULT NULL COMMENT '品牌名',
  `en_name` varchar(100) DEFAULT NULL COMMENT '英文名',
  PRIMARY KEY (`id`),
  FULLTEXT KEY `fidx` (`register_name`,`brand_name`,`en_name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
資料如下
mysql> select * from tb_customer_3;
+-------+--------------------------------------------------+------------+---------+
| id    | register_name                                    | brand_name | en_name |
+-------+--------------------------------------------------+------------+---------+
| 28152 | 蕪湖美的廚衛電器製造有限公司                     | NULL       | NULL    |
| 28153 | 北京凡客尚品電子商務有限公司                     | NULL       | NULL    |
| 28154 | 凡客誠品(北京)科技有限公司                     | NULL       | NULL    |
| 28155 | 瞬聯訊通科技(北京)有限公司                     | NULL       | NULL    |
| 28156 | 北京暢捷通訊有限公司                             | NULL       | NULL    |
| 28157 | 北京暢捷通支付技術有限公司                       | NULL       | NULL    |
| 28158 | 暢捷通資訊科技股份有限公司                       | NULL       | NULL    |
| 28159 | 北京暢捷科技有限公司                             | NULL       | NULL    |
| 28160 | 中國航天工業科學技術諮詢有限公司                 | NULL       | NULL    |
| 28161 | 北京·松下彩色顯象管有限公司                      | NULL       | NULL    |
| 28162 | 北京·松下電子部品有限公司                        | NULL       | NULL    |
| 28163 | 北京松下照明光源有限公司                         | NULL       | NULL    |
| 28164 | 松下電氣機器(北京)有限公司                     | NULL       | NULL    |
| 28165 | 中新航天科技有限公司                             | NULL       | NULL    |
| 28166 | 北京賓士汽車有限公司                             | NULL       | NULL    |
| 28167 | 阿莫斯特環保科技(北京)有限公司                 | NULL       | NULL    |
| 28168 | 北京低碳清潔能源研究所                           | NULL       | NULL    |
| 28169 | 北京未來科技城開發建設有限公司                   | NULL       | NULL    |
| 28170 | 北京諾華製藥有限公司                             | NULL       | NULL    |
| 28171 | 北京信元電信維護有限責任公司                     | NULL       | NULL    |
+-------+--------------------------------------------------+------------+---------+
顯式指定全文檢索表源
set global innodb_ft_aux_table="test/tb_customer_3";
通過系統表,就可以檢視到底是怎麼劃分tb_customer_3裡的資料
mysql> SELECT * FROM information_schema.INNODB_FT_INDEX_CACHE;
+--------------------------------------------------+--------------+-------------+-----------+--------+----------+
| WORD                                             | FIRST_DOC_ID | LAST_DOC_ID | DOC_COUNT | DOC_ID | POSITION |
+--------------------------------------------------+--------------+-------------+-----------+--------+----------+
| 中國航天工業科學技術諮詢有限公司                 |            9 |           9 |         1 |      9 |        0 |
| 中新航天科技有限公司                             |           14 |          14 |         1 |     14 |        0 |
| 凡客誠品                                         |            3 |           3 |         1 |      3 |        0 |
| 北京低碳清潔能源研究所                           |           17 |          17 |         1 |     17 |        0 |
| 北京信元電信維護有限責任公司                     |           20 |          20 |         1 |     20 |        0 |
| 北京凡客尚品電子商務有限公司                     |            2 |           2 |         1 |      2 |        0 |
| 北京賓士汽車有限公司                             |           15 |          15 |         1 |     15 |        0 |
| 北京未來科技城開發建設有限公司                   |           18 |          18 |         1 |     18 |        0 |
| 北京松下照明光源有限公司                         |           12 |          12 |         1 |     12 |        0 |
| 北京暢捷科技有限公司                             |            8 |           8 |         1 |      8 |        0 |
| 北京暢捷通支付技術有限公司                       |            6 |           6 |         1 |      6 |        0 |
| 北京暢捷通訊有限公司                             |            5 |           5 |         1 |      5 |        0 |
| 北京諾華製藥有限公司                             |           19 |          19 |         1 |     19 |        0 |
| 有限公司                                         |            4 |          16 |         3 |      4 |       30 |
| 有限公司                                         |            4 |          16 |         3 |     13 |       30 |
| 有限公司                                         |            4 |          16 |         3 |     16 |       36 |
| 松下彩色顯象管有限公司                           |           10 |          10 |         1 |     10 |        8 |
| 松下電子部品有限公司                             |           11 |          11 |         1 |     11 |        8 |
| 松下電氣機器                                     |           13 |          13 |         1 |     13 |        0 |
| 暢捷通資訊科技股份有限公司                       |            7 |           7 |         1 |      7 |        0 |
| 瞬聯訊通科技                                     |            4 |           4 |         1 |      4 |        0 |
| 科技有限公司                                     |            3 |           3 |         1 |      3 |       24 |
| 蕪湖美的廚衛電器製造有限公司                     |            1 |           1 |         1 |      1 |        0 |
| 阿莫斯特環保科技                                 |           16 |          16 |         1 |     16 |        0 |
+--------------------------------------------------+--------------+-------------+-----------+--------+----------+
檢索資料
[localhost]
[email protected]
:10:59>select * from tb_customer_3 where match(register_name,brand_name,en_name) against ('*松下*' IN BOOLEAN MODE);
+-------+--------------------------------------------+------------+---------+
| id    | register_name                              | brand_name | en_name |
+-------+--------------------------------------------+------------+---------+
| 28161 | 北京·松下彩色顯象管有限公司                | NULL       | NULL    |
| 28162 | 北京·松下電子部品有限公司                  | NULL       | NULL    |
| 28164 | 松下電氣機器(北京)有限公司               | NULL       | NULL    |
+-------+--------------------------------------------+------------+---------+
[localhost]
[email protected]
:12:43>select * from tb_customer_3 where match(register_name,brand_name,en_name) against ('*賓士*' IN BOOLEAN MODE);
Empty set (0.00 sec)
說明:
第一個SQL能夠檢索到資料,是因為分詞中包括了松下開頭的關鍵字,第二個SQL無法檢索出來資料是因為分詞中不包括賓士開頭的關鍵字。
MySQL 5.6不支援中文全文索引,原因很簡單:與英文不同,中文的文字是連著一起寫的,中間沒有MySQL能找到分詞的地方,但是有變通的辦法,就是將整句的中文分詞,並按urlencode、區位碼、base64、拼音等進行編碼使之以"字母+數字"的方式儲存於資料庫中。
或者將MySQL升級至5.7版本,MySQL 5.7開始,MySQL內建了ngram全文檢索外掛,用來支援中文分詞,並且對MyISAM和InnoDB引擎有效。

全文索引和like效率對比(下面是在虛擬機器上測試的結果)

tb_customer_1和tb_customer_2索引完全相同,只不過一個是KEY `idx_register` (`register_name`),一個是FULLTEXT KEY `fidx` (`register_name`)
select sql_no_cache count(*) from tb_customer_1 where register_name like '%中國航天工業科學技術諮詢有限公司%';
select sql_no_cache count(*) from tb_customer_2 where match(register_name) against ('*中國航天工業科學技術諮詢有限公司*' IN BOOLEAN MODE);
第一個SQL查詢多次,分別耗費0.09、0.07、0.10、0.12秒
第二個SQL查詢多次,分別耗費0.00、0.00、0.00、0.00秒

全文索引和like效率對比(線上測試結果)
select sql_no_cache count(*) from tb_customer t0 where (t0.register_name like '%北京互聯企信資訊科技有限公司南寧分公司%'  or t0.brand_name like '%北京互聯企信資訊科技有限公司南寧分公司%'  or t0.en_name like '%北京互聯企信資訊科技有限公司南寧分公司%' );
多次查詢測試結果:0.18、0.34、0.35、0.34
新增全文索引
alter table tb_customer add fulltext fidx (register_name,brand_name,en_name);
select sql_no_cache count(*) from tb_customer t0 where match(t0.register_name,t0.brand_name,t0.en_name) against ('*北京互聯企信資訊科技有限公司南寧分公司*');
多次查詢測試結果:0.00、0.00、0.01、0.00

注意事項
<1>MATCH()函式中的列必須與FULLTEXT索引中的列相同。如MATCH(register_name,brand_name,en_name)與FULLTEXT(register_name,brand_name,en_name)。若要單獨搜尋某列,如register_name列,則需另外單獨為該列建全文索引FULLTEXT(register_name),然後用MATCH(register_name)搜尋。
<2>innodb全文索引最小分詞長度由引數innodb_ft_min_token_size控制,一般修改為1。最大分詞長度由innodb_ft_max_token_size控制,一般不需要修改 
innodb_ft_min_token_size最小值預設是3,也就是說,mysql fulltext只會使用3個字或者3個字以上的關鍵字進行建立索引操作。
<3>建立全文索引時會加共享鎖,不支援併發DML,即會鎖表
<4>目前MySQL支援在CHAR、VARCHAR、TEXT型別的列上定義全文索引
<5>預設全文索引不區分大小寫,若要分大小寫,column的character set要從utf8修改成utf8_bin
<6>全文索引並不是能搜尋出字串裡面的任意字元,只能搜尋出有ft_boolean_syntax變數的片段開頭的字串。如ba,無法通過a進行搜尋,但是b,a卻可以通過a進行搜尋;b,abc可以通過布林模式下的a*進行搜尋,也可以通過布林模式下的b*進行搜尋,但是無法通過布林模式下的c*進行搜尋。
<7>MySQL5.6不支援中文全文索引,原因很簡單:與英文不同,中文的文字是連著一起寫的,中間沒有MySQL能找到分詞的地方,但是有變通的辦法,就是將整句的中文分詞,並按urlencode、區位碼、base64、拼音等進行編碼使之以"字母+數字"的方式儲存於資料庫中。
從MySQL5.7開始,MySQL內建了ngram全文檢索外掛,用來支援中文分詞,並且對MyISAM和InnoDB引擎有效。

參考文章

http://www.actionsky.com/docs/archives/163
http://imysqldba.blog.51cto.com/1222376/d-2
http://blog.csdn.net/zyz511919766/article/details/12780173