ES中多表关联如何解决

整个文档,摘录来自"铭毅天下"的博客。原始的地址如下:

Elasticsearh多表关联设计

引入问题

多表关联通常是指:1对多,或者多对多关系在ES中的呈现。

比如:博客和评论的关系,用户和爱好的关系,主表和子表的关系。

es_mulit_table_join1.png

基础认知

关系型数据库

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

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

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

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

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

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

关系型数据库的缺陷:

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

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

Elasticsearch

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

ES中单个文档的数据变更是满足ACID的,但是如果涉及多个文档时的删除,修改时,则不支持事务。当一个事务中的部分文档更新失败的时候,是无法将所有涉及到的事务内的文档更新操作都回滚到之前状态的。

扁平化有如下的优势:

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

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

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

Mysql VS Elasticsearch

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

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

es_mulit_table_join2.png

ES场景中如何解决这种关联关系

关联关系仍然非常重要。某些时候,我们需要缩小扁平化和现实世界关系模型的差异。有如下的四种常用的方法,用来在ES中进行关联数据的管理。

应用端关联

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

针对上面的问题,来如下实践:

1\. 存储层面:独立两个索引存储
2\. 实际业务层面分两次请求:
第一次查询返回:Top5中文姓名和成绩;
根据第一次查询的结果中,取出中文姓名。
到第二个表中进行查询,返回对应的Top5中文姓名和英文姓名。
最后将第一次查询结果和第二次查询结果组合后,返回给用户。
即:实际业务层面是进行两次查询,统一返回给用户。用户是无感知的。

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

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

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

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

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

宽表冗余存储

对每个文档保持一定数量的冗余数据可以在需要访问时避免进行关联。

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

针对最开始提出的问题:姓名、英文名、成绩两张表合为一张表存储。

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

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

缺点:索引更新或删除数据,应用程序不得不处理宽表的冗余数据;由于冗余数据,导致某些搜索和聚合操作可能无法按照预期工作。

嵌套文档nested存储

Nested类型是ES mapping定义的集合类型之一,它解决了原有object类型扁平化的字段属性,导致查询错误的问题,是支持独立检索的类型。

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

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

实践注意2:

index.mapping.nested_fields.limit 缺省值为50
即:一个索引中最大允许拥有50个nested类型的数据。
index.mapping.mested_object.limit 缺省值是10000。
即:1个文档中所有nested类型json对象数据的总量是10000。

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

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

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

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

父子文档存储

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

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

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

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

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

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

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

小结

Nested Object和父子关系的这两种的区别如下:

对比 Nested Object Parent/Child
优点 文档存储在一起,因此读取性能高 父子文档可以独立更新,互不影响
缺点 更新父或子文档时需要更新整个文档 为了维护Join的关系,需要占用部分内存读取性能较差
场景 子文档偶尔更新,查询频繁 子文档更新频繁

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

注意2:不建议在ES做Join操作,父子能实现部分功能,但是它的开销比较大,如果有可能,尽量在设计时使用扁平的文档模型。

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

注意4:Nested&Join父子类型,在选项时必须考虑性能问题。nested类型检索使得检索效率慢几倍,父子Join类型检索会使得检索效率慢几百倍。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,921评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,635评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,393评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,836评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,833评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,685评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,043评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,694评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,671评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,670评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,779评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,424评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,027评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,984评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,214评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,108评论 2 351
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,517评论 2 343