MySQL5.6 InnoDB中文全文索引測試
阿新 • • 發佈:2018-12-25
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]
+-------+--------------------------------------------+------------+---------+
| id | register_name | brand_name | en_name |
+-------+--------------------------------------------+------------+---------+
| 28161 | 北京·松下彩色顯象管有限公司 | NULL | NULL |
| 28162 | 北京·松下電子部品有限公司 | NULL | NULL |
| 28164 | 松下電氣機器(北京)有限公司 | NULL | NULL |
+-------+--------------------------------------------+------------+---------+
[localhost]
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/163http://imysqldba.blog.51cto.com/1222376/d-2
http://blog.csdn.net/zyz511919766/article/details/12780173