牛B,用MySQL实现搜索引擎_mysql 做搜索

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';
+------------+-------------+--------------+------------+----------------+------------+---------------------+
| table_name | dbdata_size | dbindex_size | db_size(G) | AVG_ROW_LENGTH | table_rows | update_time         |
+------------+-------------+--------------+------------+----------------+------------+---------------------+
| article    | 3,710.00M   | 1,003.00M    | 4.60G      |            414 |    9388739 | 2019-07-05 15:31:37 |
+------------+-------------+--------------+------------+----------------+------------+---------------------+

使用默认方式创建全文索引

1、该表已有关键词字段(对文章内容的简述),并以“,”作为分词符

select keywords from article limit 10;
+-------------------------------------------------+
| keywords                                        |
+-------------------------------------------------+
| NULL                                            |
| NULL                                            |
| ,婚姻,爱情                                      |
| 发型,偏分,化妆,时尚                             |
| 小A,                                            |
| ,服装搭配,女性,时尚                             |
| 漂亮,女性                                       |
| 情人节,东莞,女性                                |
| 皮肤,护肤,护肤,食品营养,美容,养生               |
| 三里屯,北京,时尚                                |
+-------------------------------------------------+

2、不建全文索引时搜索某个关键词
需要进行全表扫描

select count(*) from article where keywords like '%时尚%';
+----------+
| count(*) |
+----------+
|      163 |
+----------+
1 row in set (7.56 sec)

3、对关键词字段创建全文索引(以 , 作为分词)

my.cnf配置文件中设置innodb_ft_min_token_size,并重启MySQL服务(最小两个字符作为一个关键词,默认三个字符作为一个关键词)

[mysqld]
innodb_ft_min_token_size=2

3.1 设置自定义stopwords(即分词)

USE mysql;
CREATE TABLE my_stopwords(VALUE VARCHAR(30)) ENGINE = INNODB;
INSERT INTO my_stopwords(VALUE) VALUE (',');
SET GLOBAL innodb_ft_server_stopword_table = 'mysql/my_stopwords';
SHOW GLOBAL  VARIABLES WHERE Variable_name IN('innodb_ft_min_token_size','innodb_ft_server_stopword_table');
+---------------------------------+--------------------+
| Variable_name                   | Value              |
+---------------------------------+--------------------+
| innodb_ft_min_token_size        | 2                  |
| innodb_ft_server_stopword_table | mysql/my_stopwords |
+---------------------------------+--------------------+

3.2 创建全文索引

alter table article add fulltext index idx_full_keyword(keywords);
* [ ] Query OK, 0 rows affected, 1 warning (1 min 27.92 sec)
* [ ] Records: 0  Duplicates: 0  Warnings: 1

3.3 剩余磁盘空间需足够,原表4.6G,剩余5.7G磁盘,添加全文索引也会失败

df -h
Filesystem            Size  Used Avail Use% Mounted on
/dev/vda1             7.8G  6.3G  1.2G  85% /
tmpfs                 1.9G     0  1.9G   0% /dev/shm
/dev/mapper/vg_opt-lvol0
                       19G   12G  5.7G  68% /datas

会创建原表大小的临时文件
 8.6K Jul  5 16:19 #sql-5250_3533.frm
 4.4G Jul  5 16:20 #sql-ib117-1768830977.ibd


alter table article add fulltext index idx_full_keyword(keywords);
ERROR 1114 (HY000): The table 'article' is full

3.4 利用创建的全文索引进行查询某个关键词出现的次数
查询响应时间有了很大的提升,只需0.05s;使用where keywords like ‘%时尚%’ 需要7.56s

select count(*) from article where match(keywords) against('%时尚%');
+----------+
| count(*) |
+----------+
|      163 |
+----------+
1 row in set (0.05 sec)

3.5 如需同时完全匹配多个关键词,用布尔全文搜索

表示完全匹配 “三里屯,北京” 的记录数:

select count(*) from article where match(keywords)  against('+三里屯,北京' in boolean mode);
+----------+
| count(*) |
+----------+
|        1 |
+----------+
1 row in set (0.06 sec)

表示匹配“三里屯” 或者 “北京”的记录数
select count(*) from article where match(keywords)  against('三里屯,北京');
+----------+
| count(*) |
+----------+
|        8 |
+----------+
1 row in set (0.06 sec)

3.6 创建全文索引后,会创建一些其它文件

96K Jul 5 16:30 FTS_00000000000000a7_00000000000000c0_INDEX_1.ibd
96K Jul 5 16:30 FTS_00000000000000a7_00000000000000c0_INDEX_2.ibd
96K Jul 5 16:30 FTS_00000000000000a7_00000000000000c0_INDEX_3.ibd
96K Jul 5 16:30 FTS_00000000000000a7_00000000000000c0_INDEX_4.ibd
128K Jul 5 16:30 FTS_00000000000000a7_00000000000000c0_INDEX_5.ibd
256K Jul 5 16:30 FTS_00000000000000a7_00000000000000c0_INDEX_6.ibd
96K Jul 5 16:29 FTS_00000000000000a7_BEING_DELETED_CACHE.ibd
96K Jul 5 16:29 FTS_00000000000000a7_BEING_DELETED.ibd
96K Jul 5 16:30 FTS_00000000000000a7_CONFIG.ibd
96K Jul 5 16:29 FTS_00000000000000a7_DELETED_CACHE.ibd
96K Jul 5 16:29 FTS_00000000000000a7_DELETED.ibd

  • 前6个表示倒排索引(辅助索引表)
  • 第7,8个表示包含已删除文档的文档ID(DOC_ID),其数据当前正在从全文索引中删除
  • 第9个表示FULLTEXT索引内部状态的信息
  • 第10,11个表示包含已删除但尚未从全文索引中删除其数据的文档

使用ngram分词解析器创建全文索引

1、对title字段建立全文索引(该字段没有固定的stopwords 分词,使用ngram分词解析器)
需先在my.cnf 配置文件中设置ngram_token_size(默认为2,2个字符作为ngram 的关键词),并重启mysql服务。

这里使用默认的 2

select title from article limit 10;
+------------------------------------------------------------------------------+
| title                                                                        |
+------------------------------------------------------------------------------+
| worth IT                                                                    |
|Launchpad 江南皮革厂小show                                                  |
|Raw 幕后罕见一刻 “疯子”被抬回后台                                           |
|Raw:公子大骂老爸你就是个绿茶  公子以一打四                                  |
|四组30平米精装小户型,海量图片,附户型图                                    |
|夜店女王性感烟熏猫眼妆                                                      |
|大秀哥重摔“巨石”强森                                                        |
|少女时代 崔秀英 服饰科普 林允儿 黄美英 金泰妍 郑秀晶                        |                                              
|德阳户外踏青,花田自助烧烤                                                  |
+------------------------------------------------------------------------------+

2、对title字段创建全文索引

alter table article add fulltext index ft_index_title(title) with parser ngram;
Query OK, 0 rows affected (3 min 29.22 sec)
Records: 0  Duplicates: 0  Warnings: 0

3、会创建倒排索引(title字段越长长,创建的倒排索引越大)

[112M Jul 5 21:46 FTS\_00000000000000a7\_00000000000000cd\_INDEX\_1.ibd 28M Jul 5 21:46 FTS\_00000000000000a7\_00000000000000cd\_INDEX\_2.ibd 20M Jul 5 21:46 FTS\_00000000000000a7\_00000000000000cd\_INDEX\_3.ibd 140M Jul 5 21:46 FTS\_00000000000000a7\_00000000000000cd\_INDEX\_4.ibd 128M Jul 5 21:46 FTS\_00000000000000a7\_00000000000000cd\_INDEX\_5.ibd 668M Jul 5 21:46 FTS\_00000000000000a7\_00000000000000cd\_INDEX\_6.ibd](https://bbs.csdn.net/forums/4304bb5a486d4c3ab8389e65ecb71ac0)

4、不建立全文索引搜索title的某个关键词

select count(*) from article where title like '%户外%';
+----------+
| count(*) |
+----------+
|    22058 |
+----------+
1 row in set (8.60 sec)

select count(*) from article where title like '%后台%';
+----------+
| count(*) |
+----------+
|     1142 |
+----------+

5、使用全文索引搜索某个关键词
响应时间有很大的提升

select count(*) from article where match(title)  against('户外');
+----------+
| count(*) |
+----------+
|    22058 |
+----------+
1 row in set (0.07 sec)

select count(*) from article where title like '%后台%';
+----------+
| count(*) |
+----------+
|     1142 |
+----------+
1 row in set (8.31 sec)

6、注意当搜索的关键词字符数大于2 (ngram_token_size定义大小)会出现不一致问题

普通搜索,实际中出现该关键词的记录数为6
select count(*) from article where title like '%公子大%';
+----------+
| count(*) |
+----------+
|        6 |
+----------+
1 row in set (8.40 sec)

全文搜索,出现关键字的记录数为9443
select count(*) from article where match(title)  against('公子大');
+----------+
| count(*) |
+----------+
|     9443 |
+----------+
1 row in set (0.06 sec)

实际出现该关键字的记录数为1
select count(*) from article where title like '%花田自助%';
+----------+
| count(*) |
+----------+
|        1 |
+----------+
1 row in set (8.33 sec)

全文搜索出现该关键词的记录数为3202


# 写在最后


还有一份JAVA核心知识点整理(PDF):**JVM,JAVA集合,JAVA多线程并发,JAVA基础,Spring原理,微服务,Netty与RPC**,网络,日志,Zookeeper,Kafka,RabbitMQ,Hbase,**MongoDB,Cassandra,设计模式,负载均衡,数据库,一致性哈希,JAVA算法,数据结构,加密算法,分布式缓存**,Hadoop,Spark,Storm,YARN,机器学习,云计算...

![image](https://img-blog.csdnimg.cn/img_convert/86715077f28de537e2b2723eb50a7b45.webp?x-oss-process=image/format,png)

---+
|        1 |
+----------+
1 row in set (8.33 sec)

全文搜索出现该关键词的记录数为3202


# 写在最后


还有一份JAVA核心知识点整理(PDF):**JVM,JAVA集合,JAVA多线程并发,JAVA基础,Spring原理,微服务,Netty与RPC**,网络,日志,Zookeeper,Kafka,RabbitMQ,Hbase,**MongoDB,Cassandra,设计模式,负载均衡,数据库,一致性哈希,JAVA算法,数据结构,加密算法,分布式缓存**,Hadoop,Spark,Storm,YARN,机器学习,云计算...

[外链图片转存中...(img-VaIJGSuX-1721194295614)]

  • 3
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值