ES相关面试题

题目:

  1. 全文搜索对应的是什么功能,怎么构建索引,查询的时候怎么查

  2. 怎么构建倒排索引,使用MySQL可以实现倒排索引的功能吗

前情提要:

我的项目中的商城项目中存在使用ElasticSearch的情况,所以特地弄了此篇来应对提问,以及还有一个爬虫项目中也使用到了

question One

全文搜索对应的是什么功能,怎么构建索引,查询的时候怎么查?

全文搜索对应的是商品的搜索功能,以及厂家的搜索功能
构建索引这方面其实使用的是ElasticSearch的倒排索引

其中主要涉及的是mappings的构建吧,印象中较为深刻的是构建的时候,首先我们是基于MySQL的数据结构进行构建,其中选取需要在搜索时,商品方面使用到的信息例如说商品的名称,商品的标签,价格等等,而厂家方面使用到的有厂家名字,以及厂家的描述

其中mappings的创建中,需要注意的是keyword,以及text等
区别在于如果是keyword,那么只能精准匹配(不会进行分词),如果是text则会进行分词,在上述的情况上商品名称我使用的是text,而标签使用的是keyword,而对应的厂家名称使用的是多字段将字段同时定义为 keywordtext 类型,以便支持精确匹配和部分匹配
然后值得一提的是,倒排索引嘛,肯定是需要分词的,而我们中文不能像英文那么直接根据空格进行分词,所以我们ES在使用的时候需要额外使用插件IK分词器,然后其他的倒是没太多需要注意的了
在对应的mappings的创建中注意动静分离,只在ES中存储要检索的、修改不频繁的字段

然后就是同步上会有一些额外的考虑,例如说如何保持数据一致?
这里我是在几种方案中做出了选择:

  1. 定时任务(例如说一分钟内进行一次,那么可能会导致说给db增加 负担而且相较于cannal,相当于中间加了一层,而且多涉及了两次IO)
  2. 双写(双写可能会导致数据的增添会延长响应时间,然后双写在使用上还有一个问题就是如果mysql写入成功,而es写入失败的情况,到时候无论是采用重试机制还是说结合定时任务来再次同步或者使用日志告警等机制,都可能处理上会更加麻烦)
  3. 使用Logstash进行数据同步(查询了一些网上的情况,发现是一般需要配合kafka和beats采集器,觉得会让这个项目过于庞大,所以否决了)
  4. 使用Canal进行监听 BinLog来实时同步(最终采用的是Binlog的机制)

然后最后值得一提的是ES几乎提供了许多我们搜索上需要的功能:无论是搜索高亮还是搜索建议上

查询的时候,几乎就是编写他对应的语句喽,其中如果学习的话,编写sql语句也能执行,不过没有原生支持的性能好(具体不太清楚,好像是在官方文档看到的),然后就是其中语句编写的麻烦,我总共试过两个版本一个8开头的版本(在当时应该是仅此最新版的版本)(相对而言踩得坑非常多),另一个是使用7.9,其中maven依赖上都变化了很多,但是之后发现他们的api其实是有共性的甚至可以说他们的api就是基于语句的嵌套来编写的, 之后就容易很多了

Question two

怎么构建倒排索引,使用MySQL可以实现倒排索引的功能吗?

倒排索引(Inverted Index)是一种索引数据结构,常用于全文检索系统和搜索引擎中。它将文档中的内容和文档本身进行关联,便于快速查找包含特定词汇的文档。

倒排索引的基本概念

  1. 文档(Document):要被搜索的基本单位,比如一篇文章、一页网页等。
  2. 词汇表(Vocabulary):文档集合中所有唯一词汇的列表。
  3. 倒排列表(Posting List):每个词汇对应的文档ID列表,表示哪些文档中包含这个词汇。

倒排索引的结构

假设有以下三个文档:

  • Doc1: "The quick brown fox"
  • Doc2: "The quick blue fox"
  • Doc3: "The lazy dog"

倒排索引可能会是这样:

Term Posting List
The Doc1, Doc2, Doc3
quick Doc1, Doc2
brown Doc1
fox Doc1, Doc2
blue Doc2
lazy Doc3
dog Doc3

倒排索引的构建步骤

  1. 词项提取:从每个文档中提取词汇。(例如说中文中需要涉及的IK分词器)
  2. 词项标准化:将词项进行标准化处理,如大小写转换、词干提取等。
  3. 创建词汇表:构建所有词项的词汇表。
  4. 创建倒排列表:将词项与包含该词项的文档ID进行关联。

倒排索引的优点

  • 查询效率高:可以快速定位包含查询词的所有文档。
  • 空间利用率高:相较于其他索引方法,倒排索引的存储需求较少。

使用场景

  • 搜索引擎:如Google、Elasticsearch等。
  • 全文检索系统:用于大规模文本数据的快速搜索和分析。
  • 数据库系统:用于文本字段的高效检索。
使用MySQL可以实现倒排索引的功能吗?

MySQL有个同样能实现相关全文搜索功能的索引,也就是全文索引

其中底层不少就用到了倒排索引的功能,我们也可以自己实现,毕竟MySQL底层应该也是同样的对于中文的分词同样会有问题

MySQL 中的全文索引(Full-Text Index)用于对文本数据进行高效的全文搜索。全文索引允许你在表的一个或多个文本列上创建索引,从而加快包含大量文本数据的列的搜索速度。它主要用于在大文本字段中查找特定的单词或短语,而不是简单的前缀匹配或完整匹配。

全文索引的作用
  1. 高效全文搜索:全文索引使得对大文本数据的搜索更加高效,尤其是在搜索单词或短语时。使用全文索引的搜索速度比对大文本字段进行 LIKE 搜索要快得多。
  2. 自然语言搜索:支持自然语言搜索,允许按相关性对结果进行排序。
  3. 布尔模式搜索:支持布尔模式搜索,可以使用布尔运算符(如 AND, OR, NOT)来构造复杂的查询。
底层数据结构

在 MySQL 中,全文索引的底层数据结构依赖于存储引擎:

MyISAM 存储引擎

MyISAM 使用倒排索引(Inverted Index)来实现全文搜索。倒排索引类似于一个字典,词汇映射到文档 ID 列表,允许快速查找包含特定词汇的所有文档。

InnoDB 存储引擎

InnoDB 的全文索引实现更加复杂,因为 InnoDB 的底层数据结构是 B+ 树,而不是 MyISAM 的倒排索引。为了支持全文搜索,InnoDB 使用了一种特殊的数据结构和处理方法。

  • 分词:首先将文本数据分成词项(terms)。
  • 倒排索引表:创建一个内部的倒排索引表,将词项映射到文档 ID 列表中。
  • 辅助表:使用辅助表存储元数据和其他必要的信息,以支持高效的全文搜索。

具体实现上,InnoDB 可能会使用一种类似于倒排索引的数据结构来存储词项和文档 ID 的关系,同时利用 InnoDB 本身的事务和并发处理能力,确保全文索引的性能和可靠性。

全文索引与 B+ 树的区别
  • B+ 树:主要用于存储和索引有序数据,适合范围查询和排序。每个节点包含一个有序的键值列表,叶节点存储数据的实际指针。
  • 倒排索引:主要用于文本搜索,适合查找包含特定词汇的文档。倒排索引包含词汇到文档 ID 的映射,允许快速查找包含特定词汇的所有文档。
InnoDB 中的全文索引

为了支持全文索引,InnoDB 做了以下调整:

  1. 分词处理:在插入或更新时,对文本进行分词,将其拆分为单独的词项。
  2. 倒排索引:为每个词项创建一个倒排索引,存储词项和文档 ID 的映射。
  3. 辅助数据结构:使用辅助表和数据结构,存储必要的元数据和统计信息,以支持高效查询和排序。

自己的题目:既然Mysql有倒排索引为什么你还要使用ES呢?

题目来源

盒马 暑期实习 Java 一面凉经_牛客网 (nowcoder.com)

posted @ 2024-07-10 13:39  海山了-  阅读(36)  评论(0编辑  收藏  举报