在舆情分析的应用场景中,数据规模通常在千亿以上。使用Elasticsearch 去构建搜索引擎,做相关的分析,面临着非常多的挑战。
先介绍一下,在舆情分析场景中,要用到的是 match phrase语法,针对文章做精准的句子匹配!
在这篇文章中:
1.我会先讲一下我们面临的挑战;
2.接着我会带着问题,分析一下 match phrase语法的检索过程;
3. 偏向底层的原理。
4.根据检索原理,考虑可以做哪些优化;
5.以及针对我们面临的挑战,我的一些优化方法。

目标

探索ES在千亿规模数据的检索场景下,句子精准匹配的性能优化方案。在实时交互的场景中,应对这么多的检索,达到注重3秒内的目标。本文会先讲一下,在舆情分析场景下使用ES做检索面临的诸多挑战。接着会对ES的检索原理做一个深度的拆解。

挑战背景

  • 数据规模大,通常舆情分析,至少要在三个月的范围内做检索。加入将互联网上现有的所有的媒体数据拿到,是非常多的。例如微博、抖音、facebook、推特、等等。日均数据量假如都放在es中,可能少说也有N T(至少要在2T)。 假如在这样的数据规模中,三个月的数据就是 90 * N T 。通常我们会有一些数据是在一年范围内,甚至两年范围内做检索。那就是 365 * 2 * N T。这个规模去做实时交互,且想在个位数的秒级别中获取结果,需要非常多的计算资源。通常,一个es实例,可以高效的运行2T的数据。超过就性能会有下降。因为买不起机器,我们单台机器负载8T的数据。

  • 要用到句子的精准匹配。通常在舆情检索场景中,用的并不是es的相关性检索,而是句子的精准匹配。这就不得不去使用ES中的 match_phrase 语法。去做句子的精准匹配。熟悉es的同学,应该会知道,es最擅长的是做term查询,其次是match 搜索,然后才是 match_phrase。 这就相当于是做的 like %中国%的检索。

  • 检索条件复杂,检索的关键词多。通常要用很多的must 和must not,查询语句中包含多个操作符、子句和过滤器。也就是在一波检索中,可能要输出100+的检索词。所以这就不得不去使用 query string 搜索语法,且匹配的模式用 phrase(和match_phrase)一样的逻辑。

  • 要命中全量的数据。在问答系统中,就像百度谷歌,只需要要返回与问题最相关的答案即可,通常在舆情场景下,要命中全量的数据。因为用户通常想要这个条件命中了多少条结果。

  • 要有非常多的聚合分析。es聚合分析的性能并不高。因为它需要大量的CPU和磁盘的IO。在数据规模远超机器规模的情况下。整体的检索效果会非常的差。我有去考虑够其他类型的擅长做OLAP类型的数据库,例如CK,奈何它做句子匹配不太行。

  • 在非结构化的数据中做检索。通常是在文章中做检索,而不是在某个字段中做检索。这回让检索变得格外的难。在做聚合分析的时候,像CK这样的数据库完全用不上。

  • 实时交互。尽可能在3-5s内返回结果。以上问题,在实时交互的要求下,都变得格外严重。

总结一下:

说了这么多,就是资源不足。任何问题都可以通过加资源解决。问题是资源非常昂贵,所以我们要做的是,在有限的资源条件下,做无限的优化。

ES的 match_phrase的检索原理

先看看为什么match_phrase慢。

match_phrase 查询是 Elasticsearch 中的一种查询类型,它用于精确匹配包含一组特定词汇的文档。具体来说,match_phrase 查询会找到那些包含特定词组、并且词组中的单词以正确的顺序出现在文档中的文档。
es组织数据的方式只有一种,那就是切分词语,然后保存在倒排表中。理论上来说,性能最佳的一定是,根据一个词语,这个词语尽可能的短。然后做term查询。因为它只需要

match_phrase 查询的过程分析

  1. Query Parsing:将用户输入的查询字符串解析为相应的查询语法。在解析的过程中,Elasticsearch会根据匹配类型、搜索字段、匹配条件等信息,生成相应的查询语句。例如,对于 match phrase 查询,Elasticsearch会生成一个 MatchPhraseQuery 对象,并将查询字符串作为参数传递给该对象。将查询语句解析成内部查询对象(Query Object),并进行语法和语义检查。在这个阶段,Elasticsearch会使用查询解析器(Query Parser)将查询语句解析成查询对象。

  1. Query Optimization:对内部查询对象进行优化,以提高查询性能。这个阶段包括优化查询逻辑、合并重复查询、减少查询范围等操作。在优化阶段,Elasticsearch会使用查询优化器(Query Optimizer)对查询对象进行优化。

  1. Query Execution:执行查询操作,将查询对象转换成对倒排索引(Inverted Index)进行搜索的操作。在执行查询阶段,Elasticsearch会使用倒排索引(Inverted Index)来查找符合查询条件的文档。具体地,Elasticsearch会使用以下文件进行查询操作:

  • .tim文件和.tip文件:这两个文件保存了词项的位置信息,用于在倒排索引中定位词项所在的文档。

  • .doc文件:这个文件保存了文档ID和词项的位置信息,用于在倒排索引中定位词项所在的文档。

  • .pos文件和.pay文件:这两个文件保存了词项在文档中的位置信息和附加信息,用于在倒排索引中计算相关性得分。

  • .liv文件和.del文件:这两个文件用于表示文档是否存在和是否被标记为删除。

  • .fdt文件和.fdx文件:这两个文件用于存储文档的内容和结构信息。

  • .nvd文件和.nvm文件:这两个文件保存了词项的文档频率、逆文档频率和文档长度等信息,用于在计算相关性得分时进行加权。

  • .tvx文件和.tvd文件:这两个文件用于提供快速访问文档中字段的信息。

在查询执行阶段,Elasticsearch会使用以上文件进行查询操作,从而找到符合查询条件的文档ID。为了提高查询性能,Elasticsearch还会使用一些技术,如布尔运算优化、term lookup optimization等。

  1. Scoring:根据相关性得分对文档进行排序,得出最终的搜索结果。在计算相关性得分阶段,Elasticsearch会使用BM25算法或TF-IDF算法等机器学习模型来计算相关性得分。同时,Elasticsearch还会使用查询向量(Query Vector)和文档向量(Document Vector)等技术来计算相关性得分。在计算相关性得分时,Elasticsearch会使用.nvd文件和.nvm文件中保存的词项相关性得分信息。.nvd文件中保存的是词项的文档频率和逆文档频率信息,.nvm文件中保存的是每个文档的长度和平方和等信息。这些信息会被用于计算查询词项的相关性得分。得分高的文档会排在搜索结果的前面。计算查询结果的相关性得分(Relevance Score),并按照相关性得分进行排序。

  1. 删除文档处理:Elasticsearch 会根据.liv文件和.del文件中的信息,处理被标记为删除的文档。.liv文件用于表示哪些文档是存在的(live),哪些文档已经被标记为删除(deleted)。.del文件则是用于存储已经被标记为删除的文档的信息。在搜索时,Elasticsearch会使用.liv文件来跳过已经被标记为删除的文档,确保这些文档不会被包含在搜索结果中。

  1. 缓存处理:为了提高搜索性能,Elasticsearch会将一些查询结果缓存到内存中,以便快速响应后续的查询请求。缓存处理包括两个方面,一是根据查询语句生成查询缓存(Query Cache),二是根据文档ID生成过滤缓存(Filter Cache)。查询缓存用于缓存查询语句匹配到的文档ID,过滤缓存用于缓存文档ID的过滤结果。这些缓存会被存储到内存中或者磁盘中,以便后续查询时使用。

  1. 结果返回:最后,Elasticsearch将匹配的文档ID返回给用户,并根据需要返回文档的内容。返回的文档内容从.fdt文件中读取。.tvx和.tvd文件用于提供快速访问文档中字段的信息,以便在返回结果时能够快速获取相应的字段值。

match_phrase 查询的源码解析-在es中的源码

在 Elasticsearch 中,处理 match_phrase 查询的源码主要分布在以下几个文件中:

  1. org.elasticsearch.index.query.MatchPhraseQueryBuilder:这个类定义了 match_phrase 查询的查询语句结构。它继承自 org.elasticsearch.index.query.MatchQueryBuilder 类,实现了查询的解析、构建和执行等操作。

  1. org.elasticsearch.index.query.MatchPhraseQueryParser:这个类用于解析 match_phrase 查询语句,生成 MatchPhraseQueryBuilder 对象。它实现了 org.elasticsearch.index.query.QueryParser 接口,可以通过 Elasticsearch 的查询解析器来调用。

  1. org.elasticsearch.index.mapper.TextFieldMapper:这个类用于定义文本字段的映射规则。它实现了 org.elasticsearch.index.mapper.Mapper 接口,并且包含了诸如解析文本、分词、建立倒排索引等操作的实现。

  1. org.elasticsearch.index.search.MatchPhraseQuery:这个类是 match_phrase 查询的实现类。它继承自 org.apache.lucene.search.MultiTermQuery 类,实现了查询的匹配和评分等操作。

这些文件的源码可以在 Elasticsearch 的 Github 仓库中找到。具体来说,你可以前往以下链接找到这些文件:

  • MatchPhraseQueryBuilder:https://github.com/elastic/elasticsearch/blob/master/server/src/main/java/org/elasticsearch/index/query/MatchPhraseQueryBuilder.java

  • MatchPhraseQueryParser:https://github.com/elastic/elasticsearch/blob/master/server/src/main/java/org/elasticsearch/index/query/MatchPhraseQueryParser.java

  • TextFieldMapper:https://github.com/elastic/elasticsearch/blob/master/server/src/main/java/org/elasticsearch/index/mapper/TextFieldMapper.java

  • MatchPhraseQuery:https://github.com/elastic/elasticsearch/blob/master/server/src/main/java/org/elasticsearch/index/search/MatchPhraseQuery.java

请注意,以上文件是 Elasticsearch 7.x 版本中的源码,如果你使用的是其他版本的 Elasticsearch,可能需要到对应版本的仓库中查找相应的文件。

match_phrase 查询的源码解析-在lucene中

  1. Lucene Query Syntax:match_phrase 查询是基于 Lucene Query Syntax 的一种查询类型。Lucene Query Syntax 是一种用于构建查询表达式的语法,它支持诸如 AND、OR、NOT、*、? 等查询操作符,并且可以使用括号、引号等来调整查询的优先级和逻辑。这个语法不仅可以在 Elasticsearch 中使用,也可以在其他基于 Lucene 的搜索引擎中使用,如 Solr、Amazon CloudSearch 等。

  1. Elasticsearch REST API:Elasticsearch 提供了 REST API 接口来管理和操作 Elasticsearch 集群。你可以使用 REST API 来执行 match_phrase 查询,例如使用 HTTP POST 方法来向 /{index}/_search 请求发送一个 JSON 查询语句,其中包含 match_phrase 查询条件。Elasticsearch REST API 还提供了一些参数和选项,用于控制查询的行为和结果格式。

  1. Elasticsearch Java API:Elasticsearch Java API 是 Elasticsearch 官方提供的 Java 客户端库,它提供了一组 Java 接口和类,用于连接和操作 Elasticsearch 集群。你可以使用 Java API 来执行 match_phrase 查询,例如使用 MatchPhraseQueryBuilder 类来构建查询语句,然后使用 SearchRequest 类来执行查询,并处理返回的查询结果。

以上这些工具和库都涉及到 match_phrase 查询的使用和实现,可以帮助你更加深入地了解和应用 match_phrase 查询。你可以查阅 Elasticsearch 的官方文档和相关教程,学习如何使用和优化 match_phrase 查询。

我能想到的优化方案

构建一个不错规模的集群,这就需要合理规划集群规模。充分的资源,一定能够解决这些问题。

在挑战背景中,已经列出来的问题,从问题的本质出发,去尝试解决问题。

  • 数据剪枝。在这样的规模下,在资源有限的情况下。应该从数据剪枝的角度出发,去减少数据量,降规模。整体的方向,是使用异构来减少原数据的存储,把es只当做索引引擎,而不是取数据的地方。降低单词检索的数据范围,调整数据组织方式,例如按照时间去分区数据。降低搜索命中的数据,搜索条件应该尽可能的精简。

  • 分段请求:数据规模大,且交互方式是实时交互,用户期望在3-5秒内得到相应。从数据规格大的角度出发,只能想想如何减少数据规模。这其实就是数据剪枝的思路。 如果是为了交互,可以设计一个交互模式,将扫描全量数据的思路,变成扫描部分数据的思路。这样就可以把检索 A B C三个月的逻辑,拆分成,检索A月的数据,将结果提前返回,此时能尽可能的满足 3-5s内得到响应的需求。假如A月已经满足了用户的查看需求,那么BC就不用检索了。在乐观的情况下,检索3个月,就变成了检索一个月。这样数据规模就只有三分之一了。 这个思路下的难题是,排序,如果想基于全局的排序,应该怎么做。假如是基于时间的排序,不用担心。假如需要根据点赞量,转发量排序,就不行了。分段请求的好处:分段匹配:可以将长句子切分成多个段落,分别进行匹配,最后将结果合并。这种方式可以有效降低内存消耗,同时还可以利用多线程并发处理,提高查询性能

  • 尝试跳过打分过程,也及时去掉相关性的计算。在Elasticsearch中可以通过设置相关参数来跳过打分的过程,从而加快查询速度。具体来说,可以使用bool查询的constant_score过滤器来跳过打分过程,该过滤器将所有符合条件的文档赋予一个固定的分值,不再计算相关性得分。使用该过滤器可以在一些特定场景下提升查询性能,如过滤掉某些不符合条件的文档等。同时,也可以通过修改查询参数中的boost值来影响相关性得分,从而控制文档在查询结果中的排名。

  • 要命中全量的数据。应该用异步的方式,将count值单独返回。其实很多分析类的请求,是可以朝着异步或者离线的方向寻找出路的。大量的聚合分析,会花费大量的资源,很难在5s内得到响应。

  • 优化分词器,分词器选择:对于长句子的匹配,可以选择适合的分词器,如N-gram分词器、Edge N-gram分词器等,将长句子切分成若干短语进行匹配,从而减小内存消耗和查询时间。

  • 还需要继续整理。我始终觉得在很多个关键词匹配的过程中,倒排链的合并过程可以优化。这一块后续会研究,等有成果了,再分享出来。

  • 在缓存利用率方向,做探索,把最需要的东西放在缓存里边。

  • 底层IO的研究。最近也在研究,等有成果了,再补充分享。

ElasticSearch Query_string + match_phrase 在千亿级检索中的思考相关推荐

  1. hive建立内部表映射hbase_快手 HBase 在千亿级用户特征数据分析中的应用与实践...

    分享嘉宾:陈杨 快手 编辑整理:Hoh Xil 内容来源:BigData NoSQL 12th Meetup 出品社区:DataFun 注:欢迎转载,转载请注明出处. 快手建设 HBase 差不多有2 ...

  2. 千亿级数量下日志分析系统的技术架构选型

     
 随着数据已经逐步成为一个公司宝贵的财富,大数据团队在公司往往会承担更加重要的角色.大数据团队往往要承担数据平台维护.数据产品开发.从数据产品中挖掘业务价值等重要的职责.所以对于很多大数据工程师 ...

  3. ES千亿级搜索实战-架构优化

    不管什么数据库,在应对千亿级别以上的数据的实时检索场景,都会有一定的压力.ES是搜索引擎,优秀的设计理念能够提速,但是也会表现的力不从心.往往会出现,集群随着数据越来愈多,而变得越来越慢的问题. 通常 ...

  4. Kylin 在满帮集团千亿级用户访问行为分析中的应用

    2019 年 7 月 12 日,国内首届以 Apache Kylin 为主题的大数据领域的前沿盛会 Kylin Data Summit 在上海落幕.在本次大会的制造业分论坛上,来自满帮集团的陈雅婕的分 ...

  5. kafka集群为什么需要三个节点_每天处理千亿级日志量,Kafka是如何做到的?

    之前为大家分享了不少 Kafka 原理解析类的干货,今天咱们一起来看看 360 基于 Kafka 千亿级数据量的深度实践! 图片来自 Pexels 本文主要围绕如下内容分享: 消息队列选型 Kafka ...

  6. 量子通信产业化初试,中国筹建千亿级国家实验室

    来源:第一财经 摘要:一个涉及多地的量子信息科学国家实验室(下称"国家实验室")正在筹建,长期投资将达千亿元. 第一财经从2018年国际量子密码会议上了解到,中国正在筹建的国家实验 ...

  7. 千亿级市场赛道,阿里云视频云拿下 “三连冠”

    简介:阿里云视频云市场份额 全球权威咨询机构 IDC 发布 <中国视频云市场跟踪(2020 下半年)>报告: 阿里云连续三年 稳居视频云整体市场份额第一 整体市场份额占比达 26.21% ...

  8. 以高并发著称的 Go 如何与 MySQL 搭档应对千亿级数据?

    前两天看到字节一个老哥写的帖子,提到高阶开发者必须掌握的技能,其中他明确提出了"精通MySQL". 为啥MySQL对开发人员如此重要? 第一,不管你去面试哪家公司,数据库是必问项, ...

  9. 千亿级的数据难题,优酷工程师怎么解决?

    阿里妹导读:优酷一天的日志量会达到千亿级别,面对如此大的数据样本,2017年5月,优酷完成了从Hadoop迁移到阿里云MaxCompute,实现计算消耗和储存的消耗呈下降趋势,得到了非常大的收益.今天 ...

最新文章

  1. marlin固件烧录教程_ESP32 MicroPython教程:uPyCraft IDE入门
  2. java语言_java语言学习
  3. 瓜子二手车在 Dubbo 版本升级、多机房方案方面的思考和实践
  4. Apache JMeter 启动
  5. 同频切换的事件_LTE前台路测切换问题处理大礼包
  6. iOS 控制section不悬停 --- iOS开发系列 ---项目中成长的知识八
  7. pytorch教程之nn.Module类详解——使用Module类来自定义网络层
  8. python自学教程-python怎么快速自学?
  9. C++ 日志框架总结
  10. ADS学习记录--元器件库列表
  11. 计算机显示器工作原理与维修,VGA显卡工作原理及种故障维修方法
  12. 男女之间的暗号,看看吧,说不定你喜欢的人正暗恋着你。
  13. 前端如何修改网页的标题栏图标和名称
  14. Python编程从入门到实践(第五章练习)
  15. C语言求矩阵的逆(高斯法)
  16. 入手评测 联想小新Pro16和thinkbook15p有什么区别 选哪个
  17. Cesium 实现卫星效果
  18. 先验分布,后验分布,共轭分布的关系
  19. Oracle OLAP 与 OLTP 介绍
  20. pythonsuper继承规则,Python用super继承

热门文章

  1. 设置网页的html的font-size,CSS中的font-size属性使用教程
  2. 遇见未知的自己 张德芬
  3. tp6框架升级支持php8
  4. pymprog库应用(一)生产线平衡
  5. 常见芯片封装有哪几种
  6. 这是最全的一篇!!!浏览器输入网址后发什么了什么?
  7. linux系统进程调度算法,Linux系统中的进程调度
  8. linux 脚本授权,Linux授权命令
  9. android 11源码开机更改屏幕方向触摸方向
  10. android intent-filter作用,Android--Intent和IntentFilter详解