[转] [Elasticsearch] 数据建模 - 处理关联关系(1)

[Elasticsearch] 数据建模 - 处理关联关系(1)

标签: 建模elasticsearch搜索搜索引擎

2015-08-16 23:55 6958人阅读 评论(0) 收藏 举报

分类:

Search(43) Elasticsearch(43)

目录(?)[+]

数据建模(Modeling Your Data)

ES是一头不同寻常的野兽,尤其是当你来自SQL的世界时。它拥有很多优势:性能,可扩展性,准实时的搜索,以及对大数据的分析能力。并且,它很容易上手!只需要下载就能够开始使用它了。

但是它也不是魔法。为了更好的利用ES,你需要了解它从而让它能够满足你的需求。

在ES中,处理实体之间的关系并不像关系型存储那样明显。在关系数据库中的黄金准则 - 数据规范化,在ES中并不适用。在处理关联关系嵌套对象父子关联关系中,我们会讨论几种可行方案的优点和缺点。

紧接着在为可扩展性而设计中,我们会讨论ES提供的一些用来快速灵活实现扩展的特性。对于扩展,并没有一个可以适用于所有场景的解决方案。你需要考虑数据是如何在你的系统中流转的,从而恰当地对你的数据进行建模。针对基于时间的数据比如日志事件或者社交数据流的方案比相对静态的文档集合的方案是十分不同的。

最后,我们会讨论一样在ES中不会扩展的东西。


处理关联关系(Handling Relationships)

在真实的世界中,关联关系很重要:博客文章有评论,银行账户有交易,客户有银行账户,订单有行项目,目录也拥有文件和子目录。

在关系数据库中,处理关联关系的方式让你不会感到意外:

  • 每个实体(或者行,在关系世界中)可以通过一个主键唯一标识。
  • 实体是规范化了的。对于一个唯一的实体,它的数据仅被存储一次,而与之关联的实体则仅仅保存它的主键。改变一个实体的数据只能发生在一个地方。
  • 在查询期间,实体可以被联接(Join),它让跨实体查询成为可能。
  • 对于单个实体的修改是原子性,一致性,隔离性和持久性的。(参考ACID事务获取更多相关信息。)
  • 绝大多数的关系型数据库都支持针对多个实体的ACID事务。

但是关系型数据库也有它们的局限,除了在全文搜索领域它们拙劣的表现外。在查询期间联接实体是昂贵的 - 联接的实体越多,那么查询的代价就越大。对不同硬件上的实体执行联接操作的代价太大以至于它甚至是不切实际的。这就为在单个服务器上能够存储的数据量设下了一个限制。

ES,像多数NoSQL数据库那样,将世界看作是平的。一个索引就是一系列独立文档的扁平集合。一个单一的文档应该包括用来判断它是否符合一个搜索请求的所有信息。

虽然在ES中改变一份文档的数据是符合ACIDic的,涉及到多份文档的事务就不然了。在ES中,当事务失败后是没有办法将索引回滚到它之前的状态的。

这个扁平化的世界有它的优势:

  • 索引是迅速且不需要上锁的。
  • 搜索是迅速且不需要上锁的。
  • 大规模的数据可以被分布到多个节点上,因为每份文档之间是独立的。

但是关联关系很重要。我们需要以某种方式将扁平化的世界和真实的世界连接起来。在ES中,有4中常用的技术来管理关联数据:

通常最终的解决方案会结合这些方案的几种。


应用端联接(Application-side Joins)

我们可以通过在应用中实现联接来(部分)模拟一个关系型数据库。比如,当我们想要索引用户和他们的博客文章时。在关系型的世界中,我们可以这样做:

PUT /my_index/user/1  (1)
{
  "name":     "John Smith",
  "email":    "[email protected]",
  "dob":      "1970/10/24"
}

PUT /my_index/blogpost/2   (2)
{
  "title":    "Relationships",
  "body":     "It‘s complicated...",
  "user":     1   (3)
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

(1)(2) 索引,类型以及每份文档的ID一起构成了主键。

(3) 博文通过保存了用户的ID来联接到用户。由于索引和类型是被硬编码到了应用中的,所以这里并不需要。

通过用户ID等于1来找到对应的博文很容易:

GET /my_index/blogpost/_search
{
  "query": {
    "filtered": {
      "filter": {
        "term": { "user": 1 }
      }
    }
  }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

为了找到用户John的博文,我们可以执行两条查询:第一条查询用来得到所有名为John的用户的IDs,第二条查询通过这些IDs来得到对应文章:

GET /my_index/user/_search
{
  "query": {
    "match": {
      "name": "John"
    }
  }
}

GET /my_index/blogpost/_search
{
  "query": {
    "filtered": {
      "filter": {
        "terms": { "user": [1] }   (1)
      }
    }
  }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

(1) 传入到terms过滤器的值是第一条查询的结果。

应用端联接最大的优势在于数据是规范化了的。改变用户的名字只需要在一个地方操作:用户对应的文档。劣势在于你需要在搜索期间运行额外的查询来联接文档。

在这个例子中,只有一位用户匹配了第一条查询,但是在实际应用中可能轻易就得到了数以百万计的名为John的用户。将所有的IDs传入到第二个查询中会让该查询非常巨大,它需要执行百万计的term查询。

这种方法在第一个实体的文档数量较小并且它们很少改变时合适(这个例子中实体指的是用户)。这就使得通过缓存结果来避免频繁查询成为可能。


反规范化你的数据(Denormalizing Your Data)

让ES达到最好的搜索性能的方法是采用更直接的办法,通过在索引期间反规范化你的数据。通过在每份文档中包含冗余数据来避免联接。

如果我们需要通过作者的名字来搜索博文,可以在博文对应的文档中直接包含该作者的名字:

PUT /my_index/user/1
{
  "name":     "John Smith",
  "email":    "[email protected]",
  "dob":      "1970/10/24"
}

PUT /my_index/blogpost/2
{
  "title":    "Relationships",
  "body":     "It‘s complicated...",
  "user":     {
    "id":       1,
    "name":     "John Smith"
  }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

现在,我们可以通过一条查询来得到用户名为John的博文了:

GET /my_index/blogpost/_search
{
  "query": {
    "bool": {
      "must": [
        { "match": { "title":     "relationships" }},
        { "match": { "user.name": "John"          }}
      ]
    }
  }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

对数据的反规范化的优势在于速度。因为每份文档包含了用于判断是否匹配查询的所有数据,不需要执行代价高昂的联接操作。

时间: 2024-10-08 01:23:50

[转] [Elasticsearch] 数据建模 - 处理关联关系(1)的相关文章

[Elasticsearch] 数据建模 - 处理关联关系

数据建模(Modeling Your Data) ES是一头不同寻常的野兽,尤其是当你来自SQL的世界时.它拥有很多优势:性能,可扩展性,准实时的搜索,以及对大数据的分析能力.并且,它很容易上手!只需要下载就能够开始使用它了. 但是它也不是魔法.为了更好的利用ES,你需要了解它从而让它能够满足你的需求. 在ES中,处理实体之间的关系并不像关系型存储那样明显.在关系数据库中的黄金准则 - 数据规范化,在ES中并不适用.在处理关联关系,嵌套对象和父子关联关系中,我们会讨论几种可行方案的优点和缺点.

[转] - 浅谈数据分析和数据建模

大数据应用有几个方面,一个是效率提升,帮助企业提升数据处理效率,降低数据存储成本.另外一个是对业务作出指导,例如精准营销,反欺诈,风险管理以及业务提升.过去企业都是通过线下渠道接触客户,客户数据不全,只能利用财务数据进行业务运营分析,缺少围绕客户的个人数据,数据分析应用的领域集中在企业内部经营和财务分析. 数字时代到来之后,企业经营的各个阶段都可以被记录下来,产品销售的各个环节也被记录下来,客户的消费行为和网上行为都被采集下来.企业拥有了多维度的数据,包括产品销售数据.客户消费数据.客户行为数据

DataUML 数据建模 介绍

DataUml Design 是面向开发人员使用的一个永久免费的软件,提高软件的开发效率和代码的规范度.它主要包括三大功能,数据模型.代码生成和UML建模,数据模型功能类似于PowerDesigner软件,代码生成类似于动软的代码生成器. 1.什么是DataUml Design     DataUml Design是采用WPF开发的一款软件,该软件功能包括实体类建模.数据库设计.模型与数据库同步.数据库与模型同步.代码生成.文档生成.数据库生成 实体模型等功能.以往的软件修改模型之后还得修改数据

用户画像数据建模方法

作者:百分点技术总监郭志金 摘自:百分点(ID: baifendian_com) 从1991年Tim Berners-Lee发明了万维网(World Wide Web)开始,到20年后2011年,互联网真正走向了一个新的里程碑,进入了“大数据时代”.经历了12.13两年热炒之后,人们逐渐冷静下来,更加聚焦于如何利用大数据挖掘潜在的商业价值,如何在企业中实实在在的应用大数据技术.伴随着大数据应用的讨论.创新,个性化技术成为了一个重要落地点.相比传统的线下会员管理.问卷调查.购物篮分析,大数据第一次

MongoDB实战-面向文档的数据(找到最合适的数据建模方式)

前一段时间一直研究通过Ruby操作MongoDB数据库,在学习的过程中也分享了自己学习成长的过程,撰写了包含两篇入门操作文章和十二篇进阶文章.本篇文章开始,我们将进入MongoDB的实战操作流程,MongoDB这一非关系型数据库-是一个文档型数据库,存储的是面向文档的数据. 如何在MongoDB数据库中使用schema 设计数据库schema是在已知数据库系统特性.数据本质以及应用程序需求的情况下为数据集选择最佳表述的过程.传统的关系型数据库RDBMS中鼓励使用正规化的数据模型,从而确保数据的可

《Entity Framework 6 Recipes》翻译系列 (3) -----第二章 实体数据建模基础之创建一个简单的模型 (转)

第二章 实体数据建模基础 很有可能,你才开始探索实体框架,你可能会问“我们怎么开始?”,如果你真是这样的话,那么本章就是一个很好的开始.如果不是,你已经建模,并在实体分裂和继承方面感觉良好,那么你可以跳过本章. 本章将带你漫游使用实体框架建模的基本实例,建模是实体框架的核心特性,同时也是区别实体框架和微软早期的数据访问平台的特性.一旦建好模,你就可以面向模型编写代码,而不用面向关系数据库中的行和列. 本章以创建一个简单概念模型的实例开始,然后让实体框架创建底层的数据库,剩下的实例,将向你展示,如

《MySQL Workbench数据建模与开发》

<MySQL Workbench数据建模与开发> 基本信息 原书名:MySQL Workbench:Data Modeling & Development 原出版社: McGraw-Hill Osborne Media 作者: (美)麦克劳克林(McLaughlin, M.) 译者: 张骏温 出版社:清华大学出版社 ISBN:9787302363712 上架时间:2014-6-5 出版日期:2014 年6月 开本:16开 页码:368 版次:1-1 所属分类:计算机 > 数据库

保险业个险计价模块开发的数据建模经验分享

前段时间在开发某大型保险公司的项目,其中,涉及到个险计价的模块,之前没接触过保险业,一看他们某险种的费率表,顿时惊呆了,是一个四维的表,也就是,四种因素(性别.保险期间.交费期间.年龄)决定一个价格,还有一个影响最终保费的因素,就是保额(也就是保险金额---最大赔付金额),但这个跟价格的关系是线性的,得出标记所以这里就忽略它不谈了. 某险种的费率表如下图所示: 这是某险种的费率表,要通过四个条件得出一个价格,如某男,保险期间设为30年,交费期间为10年,假如他现在的年龄是14岁,那他的保费价格是

NoSQL数据建模技术

原文来自“NoSQL Data Modeling Techniques”,由酷壳网陈皓编译<NoSQL数据建模技术>.这篇文章看完之后,你可能会对NoSQL的数据结构会有些感觉.我的感觉是,关系型数据库想把一致性,完整性,索引,CRUD都干好,NoSQL只干某一种事,但是牺牲了很多别的东西.总体来说,我觉得NoSQL更适合做Cache. 下面是正文: NoSQL数据库经常被用作很多非功能性的地方,如,扩展性,性能和一致性的地方.这些NoSQL的特性在理论和实践中都正在被大众广泛地研究着,研究的