🔥博客主页: 【小扳_-CSDN博客】
❤感谢大家点赞👍收藏⭐评论✍
文章目录
1.0 Elasticsearch 基本概述
1.1 Elasticsearch 安装
1.2 Kibana 安装
2.0 Elasticsearch 倒排索引
2.1 正向索引
2.2 倒排索引
2.3 正向和倒排
3.0 Elasticsearch 基础概念
3.1 文档和字段
3.2 索引和映射
3.3 Mysql 和 Elasticsearch
4.0 IK 分词器
4.1 使用 IK 分词器
4.2 拓展词典
1.0 Elasticsearch 基本概述
数据库模糊查询随着表数据量的增多,查询性能的下降会非常明显,而搜索引擎的性能则不
会随着数据增多而下降太多。目前仅 10 万不到的数据量差距就如此明显,如果数据量达到百万、
千万、甚至上亿级别,这个性能差距会非常夸张。
其次,功能单一数据库的模糊搜索功能单一,匹配条件非常苛刻,必须恰好包含用户搜索的
关键字。而在搜索引擎中,用户输入出现个别错字,或者用拼音搜索、同义词搜索都能正确匹配到
数据。
综上,在面临海量数据的搜索,或者有一些复杂搜索需求的时候,推荐使用专门的搜索引擎
来实现搜索功能。
目前全球的搜索引擎技术排名如下:
Elasticsearch 是一款非常强大的开源搜索引擎,支持的功能非常多。
Elasticsearch 的官方网站如下:
Elasticsearch:官方分布式搜索和分析引擎 | Elastic
Elasticsearch 是由 elastic 公司开发的一套搜索引擎技术,它是 elastic 技术栈中的一部分。
完整的技术栈包括:
1)Elasticsearch:用于数据存储、计算和搜索
2)Logstash/Beats:用于数据收集
3)Kibana:用于数据可视化
整套技术栈被称为 ELK,经常用来做日志收集、系统监控和状态分析等等,而整套技术栈的
核心就是用来存储、搜索、计算的 Elasticsearch 。
1.1 Elasticsearch 安装
通过下面的 Docker 命令即可安装单机版本的 Elasticsearch :
docker run -d \--name es \-e "ES_JAVA_OPTS=-Xms512m -Xmx512m" \-e "discovery.type=single-node" \-v es-data:/usr/share/elasticsearch/data \-v es-plugins:/usr/share/elasticsearch/plugins \--privileged \--network net \-p 9200:9200 \-p 9300:9300 \elasticsearch:7.12.1
这里采用的是 elasticsearch 的 7.12.1 版本,由于 8 以上版本的 JavaAPI 变化很大,在企业
中应用并不广泛,企业中应用较多的还是 8 以下的版本。
安装完成后,访问 9200 端口,即可看到响应的 Elasticsearch 服务的基本信息:
1.2 Kibana 安装
Kibana 是 elastic 公司提供的用于操作 Elasticsearch 的可视化控制台。它的功能非常强
大,包括:
1)对 Elasticsearch 数据的搜索、展示。
2)对 Elasticsearch 数据的统计、聚合,并形成图形化报表、图形。
3)对 Elasticsearch 的集群状态监控。
4)它还提供了一个开发控制台(DevTools),在其中对 Elasticsearch 的 Restful 的 API
接口提供了语法提示。
通过下面的 Docker 命令,即可部署 Kibana:
docker run -d \ --name kibana \ -e ELASTICSEARCH_HOSTS=http://es:9200 \ --network=net \ -p 5601:5601 \ kibana:7.12.1
安装完成后,直接访问 5601 端口,即可看到控制台页面:
点击 Explore on my own:
继续点击 Dev tools:
输入 "GET /" 之后点击开始按钮:
右边出现的内容与直接访问 Elasticsearch 的效果是一样的。
2.0 Elasticsearch 倒排索引
Elasticsearch 之所以有如此高性能的搜索表现,正是得益于底层的倒排索引技术。那么什么
是倒排索引呢?
倒排索引的概念是基于 MySQL 这样的正向索引而言的。
2.1 正向索引
例如有一张名为 tb_goods 的表:
其中的 id 字段已经创建了索引,由于索引底层采用了 B+ 树结构,因此根据 id 搜索的速度会
非常快。但是其他字段例如 title,只在叶子节点上存在。
因此要根据 title 搜索的时候只能遍历树中的每一个叶子节点,判断 title 数据是否符合要求。
比如用户的 SQL 语句为:
select * from tb_goods where title like '%手机%';
此时,即使给 title 加上了索引,按照这种模糊查询的方法,索引会失效,最终会进行全表查
询,效率相对来说是很差的。
搜索的大概流程如图:
综上,根据 id 精确匹配时,可以走索引,查询效率较高。而当搜索条件为模糊匹配时,由于
索引无法生效,导致从索引查询退化为全表扫描,效率很差。
因此,正向索引适合于根据索引字段的精确搜索,不适合基于部分词条的模糊匹配。
而倒排索引恰好解决的就是根据部分词条模糊匹配的问题。
2.2 倒排索引
倒排索引中有两个非常重要的概念:
1)文档(Document):用来搜索的数据,其中的每一条数据就是一个文档。例如一个网
页、一个商品信息。
2)词条(Term):对文档数据或用户搜索数据,利用某种算法分词,得到的具备含义的词
语就是词条。例如:我是中国人,就可以分为:我、是、中国人、中国、国人这样的几个词条。
创建倒排索引是对正向索引的一种特殊处理和应用,流程如下:
1)将每一个文档的数据利用分词算法根据语义拆分,得到一个个词条。
2)创建表,每行数据包括词条、词条所在文档 id、位置等信息。
3)因为词条唯一性,可以给词条创建正向索引。
倒排索引的搜索流程如下(以搜索"华为手机"为例),如图:
具体流程:
首先,在新增数据的时候,已经将文档进行分词建立了分词表,不同的词条都是唯一的,每
一个词条都有对应的 ID 也就是文档的 ID 。
再接着用户来搜索 “华为手机” 的时候,也会进行分词处理,变成一个个词条,比如说:“华
为”,“手机” 。拆分开来之后,就会根据词条到词条表中进行搜索,因为根据词条搜索的过程中,
肯定不是全表扫描的查询方式,而是有索引的方式来搜索,也就是根据词条搜索的效率不低。
得到对应的 ID 之后,再继续根据 ID 索引来查询文档得到数据,这些数据肯定是有多条的,
因为拆分出来的词条都多条,再匹配过程中会有多余的数据。
虽然要先查询倒排索引,再查询倒排索引,但是无论是词条、还是文档 id 都建立了索引,查
询速度非常快!无需全表扫描。
2.3 正向和倒排
那么为什么一个叫做正向索引,一个叫做倒排索引呢?
1)正向索引是最传统的,根据 id 索引的方式。但根据词条查询时,必须先逐条获取每个文
档,然后判断文档中是否包含所需要的词条,是根据文档找词条的过程。
2)而倒排索引则相反,是先找到用户要搜索的词条,根据词条得到保护词条的文档的 id,然
后根据 id 获取文档。是根据词条找文档的过程。
那么两者方式的优缺点是什么呢?
1)正向索引:
优点:
可以给多个字段创建索引。
根据索引字段搜索、排序速度非常快。
缺点:
根据非索引字段,或者索引字段中的部分词条查找时,只能全表扫描。
2)倒排索引:
优点:
根据词条搜索、模糊搜索时,速度非常快。
缺点:
只能给词条创建索引,而不是字段。
无法根据字段做排序。
3.0 Elasticsearch 基础概念
Elasticsearch 中有很多独有的概念,与 mysql 中略有差别,但也有相似之处。
3.1 文档和字段
Elasticsearch 是面向文档(Document)存储的,可以是数据库中的一条商品数据,一个订
单信息。文档数据会被序列化为 json 格式后存储在 Elasticsearch 中:
3.2 索引和映射
将类型相同的文档集中在一起管理,称为索引(Index)。
可以把索引当做是数据库中的表。
数据库的表会有约束信息,用来定义表的结构、字段的名称、类型等信息。因此,索引库中
就有映射(mapping),是索引中文档的字段约束信息,类似表的结构约束。
3.3 Mysql 和 Elasticsearch
mysql 与 Elasticsearch 的概念做一下对比:
两者各自有自己的擅长之处:
1)Mysql:擅长事务类型操作,可以确保数据的安全和一致性。
2)Elasticsearch:擅长海量数据的搜索、分析、计算。
因此在企业中,往往是两者结合使用:
1)对安全性要求较高的写操作,使用 mysql 实现。
2)对查询性能要求较高的搜索需求,使用 Elasticsearch 实现。
3)两者再基于某种方式,实现数据的同步,保证一致性。
关于数据同步:可以考虑采用 MQ 异步通知实现。
4.0 IK 分词器
Elasticsearch 的关键就是倒排索引,而倒排索引依赖于对文档内容的分词,而分词则需要高
效、精准的分词算法,IK 分词器就是这样一个中文分词算法。
方法一:
运行一个命令即可:
docker exec -it es ./bin/elasticsearch-plugin install https://github.com/medcl/elasticsearch-analysis-ik/releases/download/v7.12.1/elasticsearch-analysis-ik-7.12.1.zip
然后重启 es 容器:
docker restart es
方法二:
需要把 IK 分词器上传至 elasticsearch 的插件挂载到了 /var/lib/docker/volumes/es-
plugins/_data 这个目录。
IK 分词器:
接着:
最后,重启 es 容器:
4.1 使用 IK 分词器
IK 分词器包含两种模式:
1)ik_smart:智能语义切分。
2)ik_max_word:最细粒度切分。
在 Kibana 的 DevTools 上来测试分词器,首先测试 Elasticsearch 官方提供的标准分词器:
POST /_analyze {"analyzer": "standard","text": "我是小扳手" }
输出结果:
可以看到,标准分词器智能 1 字 1 词条,无法正确对中文做分词。
再测试 IK 分词器:
POST /_analyze {"analyzer": "ik_smart","text": "我是小扳手了" }
输出结果:
可见使用了 IK 分词器之后,不再一词一分了,而是根据了具体的语义来拆分成一个个词条。
IK 分词器另一个分词器也是同样如此:
POST /_analyze {"analyzer": "ik_max_word","text": "我是小扳手了" }
输出结果:
4.2 拓展词典
随着互联网的发展,“造词运动”也越发的频繁。出现了很多新的词语,在原有的词汇列表中
并不存在。要想正确分词,IK 分词器的词库也需要不断的更新,IK 分词器提供了扩展词汇的功
能。
1)打开 IK 分词器 config 目录:
2)在 IKAnalyzer.cfg.xml 配置文件内容添加:
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd"> <properties><comment>IK Analyzer 扩展配置</comment><!--用户可以在这里配置自己的扩展字典 *** 添加扩展词典--><entry key="ext_dict">ext.dic</entry> </properties>
3)在 IK 分词器的 config 目录新建一个 ext.dic,可以参考 config 目录下复制一个配置文件进行
修改:
首先创建 ext.dic 文件:
接着在该文件中添加词条:
再接着重启 elasticsearch:
再继续分词,查看最终分词结果:
POST /_analyze {"analyzer": "ik_smart","text": "我是小扳手了" }
输出结果:
由于在分词库上加上了 "小扳手" 这个词条,那么在分词的时候,就会查询到词库有对应的词
条,那么就不会将 "小扳手" 这个词条进行拆分了。