最近要使用mysql的全文索引,一直没能成功,一个是只有MyISAM引擎支持,创建表时需要指定,而是需要对my.ini进行配置。

前言:本文简单讲述全文索引的应用实例,MYSQL演示版本5.5.24。
Q:全文索引适用于什么场合?
A:全文索引是目前实现大数据搜索的关键技术。
至于更详细的介绍请自行百度,本文不再阐述。
--------------------------------------------------------------------------------
一、如何设置?

二、设置条件
1.表的存储引擎是MyISAM,默认存储引擎InnoDB不支持全文索引(新版本MYSQL5.6的InnoDB支持全文索引)
2.字段类型:char、varchar和text

三、配置
my.ini配置文件中添加
# MySQL全文索引查询关键词最小长度限制
[mysqld]
ft_min_word_len = 1
保存后重启MYSQL,执行SQL语句

SHOW VARIABLES

查看ft_min_word_len是否设置成功,如果没设置成功请确保
1.确认my.ini正确配置,注意不要搞错my.ini的位置
2.确认mysql已经重启,实在不行重启电脑
其他相关配置请自行百度。
注:重新设置配置后,已经设置的索引需要重新设置生成索引
 
四、SQL语法
首先生成temp表

CREATE TABLE IF NOT EXISTS `temp` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`char` char(50) NOT NULL,
`varchar` varchar(50) NOT NULL,
`text` text NOT NULL,
PRIMARY KEY (`id`),
FULLTEXT KEY `char` (`char`),
FULLTEXT KEY `varchar` (`varchar`),
FULLTEXT KEY `text` (`text`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=2 ;
INSERT INTO `temp` (`id`, `char`, `varchar`, `text`) VALUES
(1, 'a bc 我 知道 1 23', 'a bc 我 知道 1 23', 'a bc 我 知道 1 23');

  

搜索`char`字段 'a' 值

SELECT * FROM `temp` WHERE MATCH(`char`) AGAINST ('a')

但是你会发现查询无结果?!
这时你也许会想:哎呀怎么回事,我明明按照步骤来做的啊,是不是那里漏了或者错了?
你不要着急,做程序是这样的,出错总是有的,静下心来,着急是不能解决问题的。

如果一个关键词在50%的数据出现,那么这个词会被当做无效词。
如果你想去除50%的现在请使用IN BOOLEAN MODE搜索

SELECT * FROM `temp` WHERE MATCH(`char`) AGAINST ('a' IN BOOLEAN MODE)

这样就可以查询出结果了,但是我们不推荐使用。
全文索引的搜索模式的介绍自行百度。

我们先加入几条无用数据已解除50%限制

INSERT INTO  `temp` (
`id` ,
`char` ,
`varchar` ,
`text`
)
VALUES (
NULL , '7', '7', '7'
), (
NULL , '7', '7', '7'
), (
NULL , 'a,bc,我,知道,1,23', 'a,bc,我,知道,1,23', 'a,bc,我,知道,1,23'
), (
NULL , 'x', 'x', 'x'
);

这时你执行以下SQL语句都可以查询到数据

SELECT * FROM `temp` WHERE MATCH(`char`) AGAINST ('a');
SELECT * FROM `temp` WHERE MATCH(`char`) AGAINST ('bc');
SELECT * FROM `temp` WHERE MATCH(`char`) AGAINST ('我');
SELECT * FROM `temp` WHERE MATCH(`char`) AGAINST ('知道');
SELECT * FROM `temp` WHERE MATCH(`char`) AGAINST ('1');
SELECT * FROM `temp` WHERE MATCH(`char`) AGAINST ('23');

以下SQL搜索不到数据

SELECT * FROM `temp` WHERE MATCH(`char`) AGAINST ('b');
SELECT * FROM `temp` WHERE MATCH(`char`) AGAINST ('c');
SELECT * FROM `temp` WHERE MATCH(`char`) AGAINST ('知');
SELECT * FROM `temp` WHERE MATCH(`char`) AGAINST ('道');
SELECT * FROM `temp` WHERE MATCH(`char`) AGAINST ('2');
SELECT * FROM `temp` WHERE MATCH(`char`) AGAINST ('3'); 

如果搜索多个词,请用空格或者逗号隔开

SELECT * FROM `temp` WHERE MATCH(`char`) AGAINST ('a x');
SELECT * FROM `temp` WHERE MATCH(`char`) AGAINST ('a,x');

上面的SQL都可以查询到三条数据

全文检索搜索模式

1. MySQL 4.x版本及以上版本提供了全文检索支持,但是表的存储引擎类型必须为MyISAM,以下是建表SQL,注意其中显式设置了存储引擎类型

CREATE TABLE articles (
id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY,
title VARCHAR(200),
body TEXT,
FULLTEXT (title,body)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

其中FULLTEXT(title, body) 给title和body这两列建立全文索引,之后检索的时候注意必须同时指定这两列。

2. 插入测试数据

INSERT INTO articles (title,body) VALUES
('MySQL Tutorial','DBMS stands for DataBase ...'),
('How To Use MySQL Well','After you went through a ...'),
('Optimizing MySQL','In this tutorial we will show ...'),
('1001 MySQL Tricks','1. Never run mysqld as root. 2. ...'),
('MySQL vs. YourSQL','In the following database comparison ...'),
('MySQL Security','When configured properly, MySQL ...');

3. 全文检索测试

SELECT * FROM articles
WHERE MATCH (title,body) AGAINST ('database');

检索结果如下:

5        MySQL vs. YourSQL        In the following database comparison ...
1 MySQL Tutorial DBMS stands for DataBase ...

说明全文匹配时忽略大小写。

4. 可能遇到的困扰

到目前为止都很顺利,但是如果检索SQL改为下面会怎样呢?

SELECT * FROM articles
WHERE MATCH (title,body) AGAINST ('well');

结果让人大跌眼镜,开始我也困惑了许久,后来去网上查了下才知道原来是这么回事:

mysql指定了最小字符长度,默认是4,必须要匹配大于4的才会有返回结果,可以用SHOW VARIABLES LIKE 'ft_min_word_len' 来查看指定的字符长度,也可以在mysql配置文件my.ini 更改最小字符长度,方法是在my.ini 增加一行 比如:ft_min_word_len = 2,改完后重启mysql即可。

所以上面不能返回结果。但是我用上面的方法改配置文件并重启MySQL服务器后,再用show命令查看,并没有改变。

另外,MySQL还会计算一个词的权值,以决定是否出现在结果集中,具体如下:

mysql在集和查询中的对每个合适的词都会先计算它们的权重,一个出现在多个文档中的词将有较低的权重(可能甚至有一个零权重),因为在这个特定的集中,它有较低的语义值。否则,如果词是较少的,它将得到一个较高的权重,mysql默认的阀值是50%,上面‘you’在每个文档都出现,因此是100%,只有低于50%的才会出现在结果集中。

但是如果不考虑权重,那么该怎么办呢?MySQL提供了布尔全文检索(BOOLEAN FULLTEXT SEARCH)

假设well在所有记录中都出现,并且ft_min_word_len已经改为2,那么下面的SQL检索语句得到的结果集将包含所有记录:

SELECT * FROM articles WHERE MATCH (title,body)
AGAINST ('well' IN BOOLEAN MODE );

5. 布尔全文检索语法

上面通过IN BOOLEAN MODE指定全文检索模式为布尔全文检索。MySQL还提供了一些类似我们平时使用搜索引擎时用到的的语法:逻辑与、逻辑或、逻辑非等。具体通过几个SQL语句例子来说明

SELECT * FROM articles WHERE MATCH (title,body)
AGAINST ('+apple -banana' IN BOOLEAN MODE);

+ 表示AND,即必须包含。- 表示NOT,即不包含。

SELECT * FROM articles WHERE MATCH (title,body)
AGAINST ('apple banana' IN BOOLEAN MODE);

apple和banana之间是空格,空格表示OR,即至少包含apple、banana中的一个。

SELECT * FROM articles WHERE MATCH (title,body)
AGAINST ('+apple banana' IN BOOLEAN MODE);

必须包含apple,但是如果同时也包含banana则会获得更高的权重。

SELECT * FROM articles WHERE MATCH (title,body)
AGAINST ('+apple ~banana' IN BOOLEAN MODE);

~ 是我们熟悉的异或运算符。返回的记录必须包含apple,但是如果同时也包含banana会降低权重。但是它没有 +apple -banana 严格,因为后者如果包含banana压根就不返回。

SELECT * FROM articles WHERE MATCH (title,body)
AGAINST ('+apple +(>banana <orange)' IN BOOLEAN MODE);

返回同时包含apple和banana或者同时包含apple和orange的记录。但是同时包含apple和banana的记录的权重高于同时包含apple和orange的记录。

6. MySQL不支持中文的全文检索

默认MySQL不支持中文全文检索,怎么办?大致方法有下面几个:

A. 扩展MySQL,添加中文全文检索支持,难度较大

B. 为中文内容表提供一个对应的英文索引表(即将FULLTEXT索引列按照一定的规则转化成英文索引表中的每一条记录,比如全部进行base64编码,内容表和英文索引表的id相同),检索时先将检索词也用相同规则转换成英文,然后再使用。如果还要支持按拼音全文检索,那么还需要在索引表中增加对应的拼音内容(就需要中文转拼音算法了)。当然如果还需要支持中英文交互搜索,比如搜索William时也需要返回威廉,反之亦然,那么还需要将威廉对应的英文翻译也存到索引表中去。

参考网上的链接,具体做法包括先对中文内容进行分词,然后中文转换为四位区位码存到索引表中。检索时,包含中文的检索词也要先分词,再转换为四位区位码,然后在索引表中进行全文检索。

7. 核对条目

A. 只有存储引擎类型为MyISAM类型的表,并且MySQL版本为4.X或者以上才能使用MySQL内置的全文检索支持

B. MySQL全文检索默认不支持中文,且对英文检索时忽略大小写

C. MySQL全文检索时,默认检索长度为4,即关键词的长度必须大于5才能被捕获

D. MySQL全文检索时,所有FULLTEXT索引列必须使用相同的字符集

E. MySQL全文检索返回结果集时还会考虑权重

F. MySQL全文检索还支持灵活的布尔全文检索模式

G. 更多内容参考MySQL5官方手册

 

基于mysql全文索引的深入理解的更多相关文章

  1. 基于mysql的全文索引

    支持引擎:mysql的MyISAM存储引擎和Innodb存储引擎(5.6及其以上)支持. 适用类型:char.varchar和text. 新建方法:ALTER TABLE article  ADD F ...

  2. 基于 Mysql 实现一个简易版搜索引擎

    前言 前段时间,因为项目需求,需要根据关键词搜索聊天记录,这不就是一个搜索引擎的功能吗? 于是我第一时间想到的就是 ElasticSearch 分布式搜索引擎,但是由于一些原因,公司的服务器资源比较紧 ...

  3. Mysql Explain 解读(基于MySQL 5.6.36)

    Mysql Explain 解读(基于MySQL 5.6.36) 1.语法 explain < table_name > #例子 explain select * from t3 wher ...

  4. 一个基于mysql构建的队列表

    通常大家都会使用redis作为应用的任务队列表,redis的List结构,在一段进行任务的插入,在另一端进行任务的提取. 任务的插入 $redis->lPush("key:task:l ...

  5. paip.mysql 全文索引查询空白解决

    paip.mysql 全文索引查询空白解决   或者  Incorrect key file for table: \'%s\'. Try to repair it    作者Attilax  艾龙, ...

  6. MySQL全文索引应用简明教程

    本文从以下几个方面介绍下MySQL全文索引的基础知识: MySQL全文索引的几个注意事项 全文索引的语法 几种搜索类型的简介 几种搜索类型的实例 全文索引的几个注意事项 搜索必须在类型为fulltex ...

  7. 在Jena框架下基于MySQL数据库实现本体的存取操作

    在Jena框架下基于MySQL数据库实现本体的存取操作 转自:http://blog.csdn.net/jtz_mpp/article/details/6224311 最近在做一个基于本体的管理系统. ...

  8. 关于MySql全文索引

    从 Mysql 4.0 开始就支持全文索引功能,但是 Mysql 默认的最小索引长度是 4.如果是英文默认值是比较合理的,但是中文绝大部分词都是2个字符,这就导致小于4个字的词都不能被索引,全文索引功 ...

  9. 基于MySQL协议的数据库中间层项目Atlas - 360团队

    一.简介 Atlas是由 Qihoo 360公司Web平台部基础架构团队开发维护的一个基于MySQL协议的数据中间层项目.它在MySQL官方推出的MySQL-Proxy 0.8.2版本的基础上,修改了 ...

随机推荐

  1. 设置多个ip ,实现ip欺骗

    网关和DNS填写: 使用IP欺骗功能必须得本地有多个可用IP,通常普通的PC机只有一个物理网卡,这就需要我们手工设置多IP绑定同一网卡:         a.开始菜单 -> 控制面板 -> ...

  2. pycharm fiddler requests.exceptions.SSLError

    一.SSL问题1.不启用fiddler,直接发https请求,不会有SSL问题(也就是说不想看到SSL问题,关掉fiddler就行) 2.启动fiddler抓包,会出现这个错误:requests.ex ...

  3. 最简单的TCP、UDP案例及各函数的详细解释

    TCP: server #include "stdafx.h" #include<iostream> #define BUF_SZIE 64 #include &quo ...

  4. 【BZOJ】1975 [Sdoi2010]魔法猪学院(A*)

    题目 传送门:QWQ 分析 k短路,Astar.估价函数是终点向外跑的最短路. 显然不是正解qwq. 代码 // By noble_ // Astar algorithm // #include &l ...

  5. kudu架构(转)

    特点:   High availability(高可用性).Tablet server 和 Master 使用 Raft Consensus Algorithm 来保证节点的高可用,确保只要有一半以上 ...

  6. python2-python3字符串

    https://www.cnblogs.com/yangmingxianshen/p/7990102.html

  7. rssh RSA(非对称密钥)

    rssh ,非对称密钥,分为密钥和公钥 ,密钥在对面机器,需要进入的文件中,公钥是放在本地机器上 import paramiko private_key = paramiko.RSAKey.from_ ...

  8. AS3 巧用事件api简化鼠标拖动流程

     拖动,按照一般人的定义,拖动就是鼠标按下的时候移动鼠标,这里面有三个过程,分别是按下.移动鼠标和弹起.以stage为例,大家的实现步骤通常如下:(PS:此处不讨论startDrag和stopDrag ...

  9. 基于OpenGL编写一个简易的2D渲染框架-13 使用例子

    这是重构渲染器的最后一部分了,将会给出一个 demo,测试模板测试.裁剪测试.半透明排序等等: 上图是本次 demo 的效果图,中间的绿色图形展现的是模板测试. 模板测试 void init(Pass ...

  10. 两个关于URL解析的例子

    例一: /* 解析URL查寻串中的name=value参数对 将name=value对存储在对象属性中,并返回对象 alert(getQuery().name) */ function getQuer ...