浅谈mysql fulltext全文索引优缺点

2019-04-30 13:55:13


参考链接 浅谈mysql fulltext全文索引优缺点


前言, 为什么会注意到mysql的fulltext?   nima, 还是上次innodb转成tokudb引擎的事,这次alter修改表引擎的时候,提示percona tokudb是不支持fulltext索引的.

报错信息是这样的.


1

2

3

4

#blog: xiaorui.cc

 

mysql> alter table weixin_master.page engine=TokuDB, row_format=TOKUDB_LZMA;

ERROR 1214 (HY000): The used table type doesn't support FULLTEXT indexes


FullText 全文索引? 我什么时候使用过这个索引类型了, 来看看他的表结构… 


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

#blog: xiaorui.cc

 

mysql> show create table page;

 

CREATE TABLE `page` (

  `id` bigint(20) NOT NULL AUTO_INCREMENT,

  `url` varchar(255) CHARACTER SET utf8 DEFAULT NULL,

  `title` text CHARACTER SET utf8,

  `content` blob,

  `ts` int(11) DEFAULT NULL,

  PRIMARY KEY (`id`),

  UNIQUE KEY `url_idx` (`url`) USING HASH,

  KEY `ts_idx` (`ts`) USING BTREE,

  FULLTEXT KEY `title_idx` (`title`) # FULLTEXT KEY

) ENGINE=InnoDB AUTO_INCREMENT=79808495 DEFAULT CHARSET=utf8mb4;


话说mysql innodb在5.6.4以后就有了fulltext全文索引, 虽然这个表的字段有全文索引,但我这边没用体验过,因为公司用Elasticsearch来做 “内容+标题”的索引。

文章写的不是很严谨,欢迎来喷,另外该文后续有更新的,请到原文地址查看更新。

http://xiaorui.cc/2016/02/03/%E6%B5%85%E8%B0%88mysql-fulltext%E5%85%A8%E6%96%87%E7%B4%A2%E5%BC%95%E7%9A%84%E4%BC%98%E7%BC%BA%E7%82%B9/


Mysql FullText全文索引语法是这样的.

SELECT * FROM articles WHERE match(aname,bname) against(‘+xiaorui -rfyiamcool‘ IN BOOLEAN MODE);

这种语法有3个关键字: + 代表 AND 含有,- 代表 not 不含有, no 代表 OR或 .  


in boolean mode 布尔模式,我推荐大家使用这个模式,往往不加这模式,你会发现啥都搜不到。 Boolean帮你做了一些匹配方面的适配,另外Boolean虽然可以拿到数据,但有些概率在里面的。 

in natural language mode 大小写模式

MySQL的FULLTEXT怎么分词的:


字母、数字、底线的组合视为一个字,不会把底线断字。会被分词的字符有:空白、逗号(,)与点(.),英文一般一个词一个空格,中文就不同了,所以中文需要自己分词了。

#我们先来验证下是否可以匹配到bmw.


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

mysql> select title from page where match(title) against('bmw') limit 10;

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

| title                                                                                          |

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

| 【宝诚二手车】BMW X1BMW 1系、BMW 5系、BMW 5GT                                            |

| 【宝诚二手车】BMW 1系、BMW 5GT、奔驰GLK300、凯迪拉克XTSBMW5系、君威                        |

| 【宝诚二手车】BMW 1系、BMW 5GT、奔驰GLK300、凯迪拉克XTSBMW5系、君威                        |

| 【宝诚二手车】BMW 1系、BMW 5GT、奔驰GLK300、凯迪拉克XTSBMW5系、君威                        |

| 全能王者再出击,BMW X5 xDrive28iBMW X6 xDrive28i即将上市                                     |

| BMW M | 2015 BMW M赛道体验日                                                                   |

| 【荣宝五周年】本周特价车新鲜出炉:BMW 335Li & BMW X3 20i                                   |

| 【宝诚二手车】BMW 1系、BMW 7系、奔驰GLK300、君威、凯迪拉克XTS                                  |

| BMWBMW 3系:缔造传奇 忠于纯粹                                                         |

| BMW X之旅 ▎丝路帝国简史 ——“BMW X之旅”丝路四部曲之一                                       |

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

10 rows in set (0.02 sec)


#我们再来搜索下bmw的bm字符, 结果是无法命中结果.

1

2

3

4

#blog: xiaorui.cc

 

mysql> select title from page where match(title) against('bm') limit 10;

Empty set (0.00 sec)


#同样的bm查询,如果使用in boolean mode查询的化,会发现速度快,而且可以准确的命中.


1

2

3

4

5

6

7

8

9

mysql> select title from page where match(title) against('*bm*' in boolean mode) limit 3;

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

| title                                                                                          |

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

| 【宝诚二手车】BMW X1BMW 1系、BMW 5系、BMW 5GT                                            |

| 【宝诚二手车】BMW 1系、BMW 5GT、奔驰GLK300、凯迪拉克XTSBMW5系、君威                        |

| 什么是#BMW延保#,为什么选择#BMW延保#。                                                         |

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

3 rows in set (0.02 sec)


# 通过boolean模式查询手机


1

2

3

4

5

6

7

8

9

10

#blog: xiaorui.cc

mysql> select title from page where match(title) against('*手机*' in boolean mode) limit 3;

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

| title                                                                                                                                |

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

| 【邮乐惠】重要的事情说三遍:手机银行转账免费啦!手机银行转账免费啦!手机银行转账免费啦!                                             |

| 【邮乐惠】重要的事情说三遍:手机银行转账免费啦!手机银行转账免费啦!手机银行转账免费啦!                                             |

| 【手机开户】足不出户,手机开户!                                                                                                     |

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

3 rows in set (0.35 sec)



另外match against也存有and not or的用法.   但问题是搜索出来的结果有些怪异,但还能接受.


1

2

3

4

5

6

7

8

9

10

#match against 把meizu的过滤出来,我们看到这结果是合理的。

mysql> select title from page where match(title) against('+meizu' in boolean mode) limit 3;

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

| title                                                                                               |

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

| MEIZU 魅蓝Note2(16G)4G全国套餐合约机                                                       |

| 【金色】Meizu/魅族  金色 MX5移动4G联通4G 大屏智能手机 包邮 2070像素 带指纹                          |

| 不忘初心,重回高端?MEIZU 魅族 更换品牌 Logo                                                        |

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

3 rows in set (0.00 sec)


#把含有meizu,不含有logo的取出来. 看起来这结果也是合理的.

1

2

3

4

5

6

7

8

9

mysql> select title from page where match(title) against('+meizu -logo' in boolean mode) limit 3;

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

| title                                                                                                   |

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

| MEIZU 魅蓝Note2(16G)4G全国套餐合约机                                                           |

| 【金色】Meizu/魅族  金色 MX5移动4G联通4G 大屏智能手机 包邮 2070像素 带指纹                              |

| 魅族(MEIZU)是中国智能手机厂商,致力于制造设计优雅、简单易用的智能手机。                                 |

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

3 rows in set (0.00 sec)


#我们需要注意的是,只要涉及到汉字查询就不行了,另外涉及到分词不合理的情况也是无法命中的. 

1

2

3

4

5

6

7

8

9

mysql> select title from page where match(title) against('+meizu -金色' in boolean mode) limit 3;

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

| title                                                                                               |

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

| MEIZU 魅蓝Note2(16G)4G全国套餐合约机                                                       |

| 【金色】Meizu/魅族  金色 MX5移动4G联通4G 大屏智能手机 包邮 2070像素 带指纹                          |

| 不忘初心,重回高端?MEIZU 魅族 更换品牌 Logo                                                        |

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

3 rows in set (0.00 sec)


#我们继续来看看由于分词情况引起的查询误差,下面的语句是含有meizu,不含有pro的匹配,但是我们看到结果里是有pro字符串的.  

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

mysql> select title from page where match(title) against('+meizu -pro' in boolean mode);

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

| title                                                                                                                   |

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

| MEIZU/魅族PRO 5全面开启预订,实体专卖店随时为你准备着...                                                                |

| <福利活动>““LOVE CHINA LOVE MEIZU                                                                                |

| 【手机】魅族手机pro5 MEIZU MX5 工艺                                                                                    |

| Meizu/魅族 MX5移动版八核时尚 智能拍照手机                                                                          |

| MEIZU 魅族 魅蓝note2 两个月体验                                                                                         |

| 关注公众号 冉子屋 Meizu/魅族 MX5智能大屏手机  地址:平遥县顺城路隆兴源6区东6                                |

| Meizu Pro/魅族 魅蓝2 2G+16G 1300M+500M 超强性价比                                                                           |

| MEIZU PRO5金色版本已经到货,您还在等什么!有它就够了。。。                                                         |

| MEIZU PRO5金色版本已经到货,您还在等什么!有它就够了。。。                                                         |

| MEIZU PRO5金色版本已经到货,您还在等什么!有它就够了!!!                                                    

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

30 rows in set (0.01 sec)


#我不想要xts,但是返回的结果确含有xts字符串. 


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

mysql> select title from page where match(title) against('+bmw -XTS') limit 10;

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

| title                                                                                                            |

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

| 【宝诚二手车】BMW X1BMW 1系、BMW 5系、BMW 5GT                                                              |

| 【每天一辆特价车】 凯迪拉克 XTS                                                                             |

| XTS.一部你能买到最舒适的豪华轿车                                                                                 |

| 20149 凯迪拉克 XTS 2.0T 28T 舒适型 白色 自动档                            |

| 克莱斯勒-300C 凯迪拉克 -XTS 丰田-皇冠 三款三厢豪华车,浔车团极速店等你来 !                                |

| 克莱斯勒-300C 凯迪拉克 -XTS 丰田-皇冠 三款三厢豪华车,浔车团玺沣店等你来 !                                |

| 克莱斯勒-300C 凯迪拉克 -XTS 丰田-皇冠 三款三厢豪华车,浔车团HAT动力店等你来 !                                  |

| 克莱斯勒-300C 凯迪拉克 -XTS 丰田-皇冠 三款三厢豪华车,浔车团酷车汇店等你来 !                                   |

| 克莱斯勒-300C 凯迪拉克 -XTS 丰田-皇冠 三款三厢豪华车,浔车团浔阳店等你来 !                                |

| 克莱斯勒-300C     凯迪拉克 -XTS      丰田-皇冠      三款三厢豪华车,浔车团等你来 !                             |

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


搜索中文的时候最好加上通配符*符号,不然是搜不到汉字.

1

2

3

4

5

6

7

8

9

10

11

12

mysql> select title from page where match(title) against('手机' in boolean mode) limit 3;

Empty set (0.00 sec)

 

mysql>  select title from page where match(title) against('*手机*' in boolean mode) limit 3;

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

| title                                                                                                                                |

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

| 【邮乐惠】重要的事情说三遍:手机银行转账免费啦!手机银行转账免费啦!手机银行转账免费啦!                                             |

| 【邮乐惠】重要的事情说三遍:手机银行转账免费啦!手机银行转账免费啦!手机银行转账免费啦!                                             |

| 【手机开户】足不出户,手机开户!                                                                                                     |

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

3 rows in set (0.35 sec)


最后总结:

Mysql这fulltext性能看起来还行,组合查询的精度有些差,mysql fulltext跟Elasticsearch的索引都有个打分机制,也就是匹配相似度. 经过我的测试发现fulltext在单个词或者字符查询命中率还是可以的。

其实我们这就算大量的使用Elasticsearch做全文索引,分词是使用Elasticsearch最火的ik加自定义的词库包,但还是经常有因为分词问题引起数据无法命中的情况。

现在不知道mysql5.7是否可以自定义中文分词词库,如果不能的话,果断推荐大家使用Sphinx或Lucene方案.


  • 2019-03-15 15:49:28

    win10远程桌面连接不上解决方法

    有朋友就感叹电脑的世界真的是很神奇,可以将整个世界连接在一起。如果别人想要摆弄你的电脑,即使不在一个地方也可以利用远程桌面来控制。而这就是所谓的远程控制操作了,大部分人都知道它的作用,不过这也不排除会遇到一些突发情况的时候,例如win10远程桌面连接不上,这该怎么去解决呢?为此,小编给大家带来了解决的图文操作。

  • 2019-03-15 16:49:18

    Win7无法进入家庭组提示“您的系统管理员不允许访问家庭组”怎么办

     家庭组是家庭网络上可以共享文件和打印机的一组计算机,可以方便用户们共享文件或者视频等,可是最近有win7纯净版系统用户却发现无法进入家庭组,提示“您的系统管理员不允许访问家庭组”,该怎么办呢?现在给大家分享一下Win7无法进入家庭组提示“您的系统管理员不允许访问家庭组”的解决方法。

  • 2019-03-17 22:19:28

    动态更新Toolbar Menu以及Menu中同时显示文字和图标

    我们经常会有这样的需求,在切换Fragment或者点击某个按钮后动态更新Toolbar上Menu项.但是onCreateOptionsMenu方法只在创建Activity的时候调用一次,以后就不再调用了,所以就不能在onCreateOptionsMenu中做处理了。 不过系统提供了另外的一个方法onPrepa

  • 2019-03-26 19:25:01

    Android studio 打包后安装闪退 Fatal Signal 6(SIGABRT)...

    项目上线前打包安装后闪退,查了很多原因,比如混淆文件的内容,第三方库不加入混淆等等,均未成功,后来关闭混淆打包后运行成功,原因可能是依赖工程中的库文件不能被混淆,关闭本工程混淆开关后,依赖工程的混淆开关也要关闭,关闭混淆后如果怕被反编译,可使用百度开发平台的app加固,加固的同时还能使用多渠道打包工具。

  • 2019-03-26 19:29:05

    Android NDK开发Crash错误定位

     在Android开发中,程序Crash分三种情况:未捕获的异常、ANR(Application Not Responding)和闪退(NDK引发错误)。其中未捕获的异常根据logcat打印的堆栈信息很容易定位错误。ANR错误也好查,Android规定,应用与用户进行交互时,如果5秒内没有响应用户的操作,则会引发ANR错误,并弹出一个系统提示框,让用户选择继续等待或立即关闭程序。并会在/data/anr目录下生成一个traces.txt文件,记录系统产生anr异常的堆栈和线程信息。如果是闪退,这问题比较难查, --------------------- 作者:xyang0917 来源:CSDN 原文:https://blog.csdn.net/xyang81/article/details/42319789 版权声明:本文为博主原创文章,转载请附上博文链接!

  • 2019-04-01 22:46:39

    电子签章的实施方案

    WORD/EXCEL签章模块,该部分实现与WORD/EXCEL的无缝结合,并提供给用户简单直观的菜单和工具条来实现文档签章验证等各种操作,其中,KHSC-64智能密码钥匙是签章模块中用户证书和图章的载体

  • 2019-04-01 22:48:25

    如何用 Java 对 PDF 文件进行电子签章

    印章是我国特有的历史文化产物,古代主要用作身份凭证和行驶职权的工具。它的起源是由于社会生活的实际需要。早在商周时代,印章就已经产生。如今的印章已成为一种独特的,融实用性和艺术性为一体的艺术瑰宝。传统的印章容易被坏人、小人私刻;从而新闻鲜有报道某某私刻公章,侵吞国家财产。随着计算机技术、加密技术及图像处理技术的发展,出现了电子签章。电子签章是电子签名的一种表现形式,利用图像处理技术、数字加密技术将电子签名操作转化为与纸质文件盖章操作相同的可视效果,同时利用电子签名技术保障电子信息的真实性和完整性以及签名人的不可否认性