🔥博客主页: 【小扳_-CSDN博客】**
❤感谢大家点赞👍收藏⭐评论✍**
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": "我是小扳手了" }
输出结果:
** 由于在分词库上加上了 "小扳手" 这个词条,那么在分词的时候,就会查询到词库有对应的词**
条,那么就不会将 "小扳手" 这个词条进行拆分了。
版权归原作者 小扳 所有, 如有侵权,请联系我们删除。