MySQL 实现一个简单版搜索引擎,真是绝了!

前言

  • 只有Innodb和myisam存储引擎能用全文索引(innodb支持全文索引是从mysql5.6开始的)
  • char、varchar、text类型字段能创建全文索引(fulltext index type)
  • 全文索引的基于关键词的,如何区分不同的关键词了,就要用到分词(stopword)
  • 英文单词用空格,逗号进行分词;中文分词不方便(一个句子不知道怎样区分不同的关键词)
  • 内置分词解析器ngram支持中文,日文,韩文(将句子分成固定数字的短语)
  • 当对表写入大量数据时,写入数据后再创建全文索引的速度更快(减少了维护索引的开销)
  • 全文索引的原理的倒排索引(一种数据结构),一般利用关联数组,在辅助表中存储单词与文档中所在位置的映射

使用

用MATCH() … AGAINST 方式来进行搜索
match()表示搜索的是那个列,against表示要搜索的是那个字符串

查看默认的分词(以这些词来区分不同的关键词);也可以自定义分词,以这些词来区分不同的关键词

SELECT * FROM information_schema.INNODB_FT_DEFAULT_STOPWORD;

+-------+ 
| value | 
+-------+ 
| a     | 
| about | 
| an    | 
| are   | 
| as    | 
| at    | 
| be    | 
| by    | 
| com   | 
| de    | 
| en    | 
| for   | 
| from  |

三种类型的全文搜索方式

natural language search(自然语言搜索)

通过MATCH AGAINST 传递某个特定的字符串来进行检,默认方式

boolean search(布尔搜索)

为检索的字符串增加操作符,如“+”表示必须包含,"-“不包含,”*" 表示通配符,即使传递的字符串较小或出现在停词中,也不会被过滤掉

query expansion search(查询扩展搜索)

搜索字符串用于执行自然语言搜索,然后,搜索返回的最相关行的单词被添加到搜索字符串,并且再次进行搜索,查询将返回来自第二个搜索的行

相关参数

配置相关参数

innodb_ft_min_token_size

默认3,表示最小3个字符作为一个关键词,增大该值可减少全文索引的大小

innodb_ft_max_token_size

默认84,表示最大84个字符作为一个关键词,限制该值可减少全文索引的大小

ngram_token_size

默认2,表示2个字符作为内置分词解析器的一个关键词,如对“abcd”建立全文索引,关键词为’ab’,‘bc’,‘cd’,当使用ngram分词解析器时,innodb_ft_min_token_size和innodb_ft_max_token_size 无效

注意:这三个参数均不可动态修改,修改了这些参数,需重启MySQL服务,并重新建立全文索引。

测试innodb引擎使用全文索引

准备

1、目标

  • 查询文章中是否含有某个关键词;一系列文章出现某个关键词的次数
  • 查询文章的标题是否含有某个关键词

2、设置以下参数减少磁盘IO压力

SET GLOBAL sync_binlog=100;
SET GLOBAL innodb_flush_log_at_trx_commit=2;

3、导入1kw 数据进行测试全文索引

该数据来源网上搜索
提取码:60l7

4、某个文章表 的结构

CREATE TABLE `article` (
  `id` bigint(10) NOT NULL,
  `url` varchar(1024) CHARACTER SET latin1 NOT NULL DEFAULT '',
  `title` varchar(256) NOT NULL DEFAULT '',
  `source` varchar(32) DEFAULT '' COMMENT '真实来源',
  `keywords` varchar(32) DEFAULT NULL,
  `publish_time` timestamp NULL DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `title_idx` (`title`)
) ENGINE=InnoDB

使用myloader 多线程导入测试数据,先把测试数据进行解压

tar -zxf mydumper_dump_article.tar.gz
time myloader -u $user -p $passwd -S $socket -t 32 -d /datas/dump_article -v 3

5、导入数据后总数据量和数据文件、索引文件大小

SELECT COUNT(*) FROM `article`;
+----------+
| COUNT(*) |
+----------+
| 10000000 |
+----------+
1 row in set (7.85 sec)

SELECT     table_name,   CONCAT(FORMAT(SUM(data_length) / 1024 / 1024,2),'M') AS dbdata_size,   CONCAT(FORMAT(SUM(index_length) / 1024 / 1024,2),'M') AS dbindex_size,   CONCAT(FORMAT(SUM(data_length + index_length) / 1024 / 1024 / 1024,2),'G') AS `db_size(G)`,   AVG_ROW_LENGTH,table_rows,update_time FROM   information_schema.tables WHERE table_schema = DATABASE() and table_name='article';
+------------+-------------+--------------+------------+----------------+------------+------------------
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值