0


微服务篇-深入了解 Elasticsearch 基础概念、Elasticsearch 倒排索引、IK 分词器(拓展词典)

🔥博客主页: 【小扳_-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": "我是小扳手了"
}

输出结果:

** 由于在分词库上加上了 "小扳手" 这个词条,那么在分词的时候,就会查询到词库有对应的词**

条,那么就不会将 "小扳手" 这个词条进行拆分了。


本文转载自: https://blog.csdn.net/Tingfeng__/article/details/144315124
版权归原作者 小扳 所有, 如有侵权,请联系我们删除。

“微服务篇-深入了解 Elasticsearch 基础概念、Elasticsearch 倒排索引、IK 分词器(拓展词典)”的评论:

还没有评论