干货 | Elasticsearch多表关联设计指南

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
检索分析服务 Elasticsearch 版,2核4GB开发者规格 1个月
简介: Elasticsearch多表关联问题是讨论最多的问题之一,如:博客和评论的关系,用户和爱好的关系。多表关联通常指:1对多,或者多对多。本文以星球问题会出发点,引申出ES多表关联认知,分析了4种关联关系的适用场景、优点、缺点,希望对你有所启发,为你的多表关联方案选型、实战提供帮助。

image.png

链接

1、抛出问题

1.1 星球典型问题

image.png

1.2 社区典型问题

image.png

1.3 QQ群典型问题

关系型数据库中的多表之间的关联查询,ES中有什么好的解决方案?

如果我把关联关系的表迁移到ES中放到一个type下,文档结构除了对象之间的嵌套还有什么好的解决方案?


2、基础认知

2.1 关系型数据库

关系数据库是专门为关系设计的,有如下特点:


可以通过主键唯一地标识每个实体(如Mysql中的行)。

实体 规范化 。唯一实体的数据只存储一次,而相关实体只存储它的主键。只能在一个具体位置修改这个实体的数据。

实体可以进行关联查询,可以跨实体搜索。

支持ACID特性,即:单个实体的变化是 原子的 , 一致的 , 隔离的 , 和 持久的 。

大多数关系数据库支持跨多个实体的 ACID 事务。

关系型数据库的缺陷:


第一:全文检索有限的支持能力。 这点,postgresql已部分支持,但相对有限。

第二:多表关联查询的耗时很长,甚至不可用。之前系统开发中使用过Mysql8个表做关联查询,一次查询等待十分钟+,基本不可用。

2.2 Elasticsearch

Elasticsearch ,和大多数 NoSQL 数据库类似,是扁平化的。索引是独立文档的集合体。 文档是否匹配搜索请求取决于它是否包含所有的所需信息和关联程度。


Elasticsearch 中单个文档的数据变更是满足ACID的, 而涉及多个文档时则不支持事务。当一个事务部分失败时,无法回滚索引数据到前一个状态。


扁平化有以下优势:


索引过程是快速和无锁的。

搜索过程是快速和无锁的。

因为每个文档相互都是独立的,大规模数据可以在多个节点上进行分布。

2.3 Mysql VS Elasticsearch

mysql才擅长关系管理,而ES擅长的是检索。


Medcl也曾强调:“如果可能,尽量在设计时使用扁平的文档模型。” Elasticsearch的关联存储、检索、聚合操作势必会有非常大的性能开销。

image.png

3 Elasticsearch关联关系如何存储

关联关系仍然非常重要。某些时候,我们需要缩小扁平化和现实世界关系模型的差异。

以下四种常用的方法,用来在 Elasticsearch 中进行关联数据的管理:


3.1 应用端关联

这是普遍使用的技术,即在应用接口层面来处理关联关系。

针对星球问题实践,


存储层面:独立两个索引存储。

实际业务层面分两次请求:

第一次查询返回:Top5中文姓名和成绩;

根据第一次查询的结果,第二次查询返回:Top5中文姓名和英文姓名;


将第一次查询结果和第二次查询结果组合后,返回给用户。

即:实际业务层面是进行了两次查询,统一返回给用户。用户是无感知的。


适用场景:数据量少的业务场景。

优点:数据量少时,用户体验好。

缺点:数据量大,两次查询耗时肯定会比较长,影响用户体验。


引申场景:关系型数据库和ES 结合,各取所长。将关系型数据库全量同步到 ES 存储,不做冗余存储。

如前所述:ES 擅长的是检索,而 MySQL 才擅长关系管理。所以可以考虑二者结合,使用 ES 多索引建立相同的别名,针对别名检索到对应 ID 后再回 MySQL 查询,业务层面通过关联 ID join 出需要的数据。


3.2 宽表冗余存储

对应于官方文档中的“Data denormalization”,官方直接翻译为:“非规范化你的数据”,总感觉规范化是什么鬼,不好理解。

通俗解释就是:冗余存储,对每个文档保持一定数量的冗余数据可以在需要访问时避免进行关联。


这点通过logstash 同步关联数据到ES时,通常会建议:先通过视图对Mysql数据做好多表关联,然后同步视图数据到ES。此处的视图就是宽表。


针对星球问题实践:姓名、英文名、成绩两张表合为一张表存储。


适用场景:一对多或者多对多关联。


优点:速度快。因为每个文档都包含了所需的所有信息,当这些信息需要在查询进行匹配时,并不需要进行昂贵的关联操作。


缺点:索引更新或删除数据,应用程序不得不处理宽表的冗余数据;

由于冗余存储,导致某些搜索和聚合操作可能无法按照预期工作。


3.3 嵌套文档(Nested)存储

Nested类型是ES Mapping定义的集合类型之一,它是比object类型更NB的支持独立检索的类型。

举例:有一个文档描述了一个帖子和一个包含帖子上所有评论的内部对象评论。可以借助 Nested 实现。


实践注意1:当使用嵌套文档时,使用通用的查询方式是无法访问到的,必须使用合适的查询方式(nested query、nested filter、nested facet等),很多场景下,使用嵌套文档的复杂度在于索引阶段对关联关系的组织拼装。


推荐实践:https://blog.csdn.net/laoyang360/article/details/82950393


实践注意2:


index.mapping.nested_fields.limit 缺省值是50。即:一个索引中最大允许拥有50个nested类型的数据。

index.mapping.nested_objects.limit 缺省值是10000。即:1个文档中所有nested类型json对象数据的总量是10000。

1

2

适用场景:1 对少量,子文档偶尔更新、查询频繁的场景。

如果需要索引对象数组并保持数组中每个对象的独立性,则应使用嵌套 Nested 数据类型而不是对象 Oject 数据类型。


优点:nested文档可以将父子关系的两部分数据(举例:博客+评论)关联起来,可以基于nested类型做任何的查询。

缺点:查询相对较慢,更新子文档需要更新整篇文档。


3.4 父子文档存储

注意:6.X之前的版本的父子文档存储在相同索引的不同type中。而6.X之上的版本,单索引下已不存在多type的概念。父子文档Join的都是基于相同索引相同type实现的。


Join类型是ES Mapping定义的类型之一,用于在同一索引的文档中创建父/子关系。 关系部分定义文档中的一组可能关系,每个关系是父名称和子名称。


实践参考:https://blog.csdn.net/laoyang360/article/details/79774481


适用场景:子文档数据量要明显多于父文档的数据量,存在1 对多量的关系;子文档更新频繁的场景。


举例:1 个产品和供应商之间是1对N的关联关系。

当使用父子文档时,使用has_child 或者has_parent做父子关联查询。


优点:父子文档可独立更新。

缺点:维护Join关系需要占据部分内存,查询较Nested更耗资源。


4 小结

image.png

在Elasticsearch开发实战中对于多表关联的设计要突破关系型数据库设计的思维定式。

不建议在es做join操作,parent-child能实现部分功能,但是它的开销比较大,如果可能,尽量在设计时使用扁平的文档模型。

尽量将业务转化为没有关联关系的文档形式,在文档建模处多下功夫,以提升检索效率。

Nested&Join父子文选型必须考虑性能问题。 nested 类型检索使得检索效率慢几倍,父子Join 类型检索会使得检索效率慢几百倍。

以上内容,实际官方文档都有明确的描述。我把内容加上自己的理解,作了精炼和解读。

再次强调:第一手资料的重要性。但本着“再显而易见的道理,也有N多人不知道”的原则,一定要读英文官方文档,加深认知理解。


Elasticsearch多表关联你是如何做的呢?欢迎留言写下您的思考。


参考:

[1] https://www.elastic.co/guide/en/elasticsearch/guide/current/relations.html

[2] rockybean 教程

相关实践学习
使用阿里云Elasticsearch体验信息检索加速
通过创建登录阿里云Elasticsearch集群,使用DataWorks将MySQL数据同步至Elasticsearch,体验多条件检索效果,简单展示数据同步和信息检索加速的过程和操作。
ElasticSearch 入门精讲
ElasticSearch是一个开源的、基于Lucene的、分布式、高扩展、高实时的搜索与数据分析引擎。根据DB-Engines的排名显示,Elasticsearch是最受欢迎的企业搜索引擎,其次是Apache Solr(也是基于Lucene)。 ElasticSearch的实现原理主要分为以下几个步骤: 用户将数据提交到Elastic Search 数据库中 通过分词控制器去将对应的语句分词,将其权重和分词结果一并存入数据 当用户搜索数据时候,再根据权重将结果排名、打分 将返回结果呈现给用户 Elasticsearch可以用于搜索各种文档。它提供可扩展的搜索,具有接近实时的搜索,并支持多租户。
相关文章
|
Java 关系型数据库 存储
干货 | Elasticsearch多表关联设计指南
本文以星球问题会出发点,引申出ES多表关联认知,分析了4种关联关系的适用场景、优点、缺点。
4075 1
干货 | Elasticsearch多表关联设计指南
|
2月前
|
存储 安全 数据管理
如何在 Rocky Linux 8 上安装和配置 Elasticsearch
本文详细介绍了在 Rocky Linux 8 上安装和配置 Elasticsearch 的步骤,包括添加仓库、安装 Elasticsearch、配置文件修改、设置内存和文件描述符、启动和验证 Elasticsearch,以及常见问题的解决方法。通过这些步骤,你可以快速搭建起这个强大的分布式搜索和分析引擎。
68 5
|
3月前
|
存储 JSON Java
elasticsearch学习一:了解 ES,版本之间的对应。安装elasticsearch,kibana,head插件、elasticsearch-ik分词器。
这篇文章是关于Elasticsearch的学习指南,包括了解Elasticsearch、版本对应、安装运行Elasticsearch和Kibana、安装head插件和elasticsearch-ik分词器的步骤。
283 0
elasticsearch学习一:了解 ES,版本之间的对应。安装elasticsearch,kibana,head插件、elasticsearch-ik分词器。
|
4月前
|
NoSQL 关系型数据库 Redis
mall在linux环境下的部署(基于Docker容器),Docker安装mysql、redis、nginx、rabbitmq、elasticsearch、logstash、kibana、mongo
mall在linux环境下的部署(基于Docker容器),docker安装mysql、redis、nginx、rabbitmq、elasticsearch、logstash、kibana、mongodb、minio详细教程,拉取镜像、运行容器
mall在linux环境下的部署(基于Docker容器),Docker安装mysql、redis、nginx、rabbitmq、elasticsearch、logstash、kibana、mongo
|
5月前
|
数据可视化 Docker 容器
一文教会你如何通过Docker安装elasticsearch和kibana 【详细过程+图解】
这篇文章提供了通过Docker安装Elasticsearch和Kibana的详细过程和图解,包括下载镜像、创建和启动容器、处理可能遇到的启动失败情况(如权限不足和配置文件错误)、测试Elasticsearch和Kibana的连接,以及解决空间不足的问题。文章还特别指出了配置文件中空格的重要性以及环境变量中字母大小写的问题。
一文教会你如何通过Docker安装elasticsearch和kibana 【详细过程+图解】
|
5月前
|
JSON 自然语言处理 数据库
Elasticsearch从入门到项目部署 安装 分词器 索引库操作
这篇文章详细介绍了Elasticsearch的基本概念、倒排索引原理、安装部署、IK分词器的使用,以及如何在Elasticsearch中进行索引库的CRUD操作,旨在帮助读者从入门到项目部署全面掌握Elasticsearch的使用。
|
5月前
|
Ubuntu Oracle Java
如何在 Ubuntu VPS 上安装 Elasticsearch
如何在 Ubuntu VPS 上安装 Elasticsearch
65 0
|
5月前
|
存储 Ubuntu Oracle
在Ubuntu 14.04上安装和配置Elasticsearch的方法
在Ubuntu 14.04上安装和配置Elasticsearch的方法
53 0
|
5月前
|
存储 安全 Java
在CentOS 7上安装和配置Elasticsearch的方法
在CentOS 7上安装和配置Elasticsearch的方法
366 0
|
5月前
|
自然语言处理 Docker 容器
ElasticSearch 实现分词全文检索 - ES、Kibana、IK分词器安装
ElasticSearch 实现分词全文检索 - ES、Kibana、IK分词器安装
72 0