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

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": "john@smith.com",
"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": "john@smith.com",
"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

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

 

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

  1. Elasticsearch 数据建模指南

    文章转载自:https://mp.weixin.qq.com/s/vSh6w3eL_oQvU1mxnxsArA 0.题记 我在做 Elasticsearch 相关咨询和培训过程中,发现大家普遍更关注实 ...

  2. ES 32 - Elasticsearch 数据建模的探索与实践

    目录 1 什么是数据建模? 2 如何对 ES 中的数据进行建模 2.1 字段类型的建模方案 2.2 检索.聚合及排序的建模方案 2.3 额外存储的建模方案 3 ES 数据建模实例演示 3.1 动态创建 ...

  3. Elasticsearch数据建模笔记

    数据建模 数据建模是创建数据模型的过程 数据模型是对真实世界进行抽象描述的一种工具和方法,实现对现实世界的映射 三个过程:概念模型=>逻辑模型=>数据模型 数据模型:结合具体的数据库,在满 ...

  4. ElasticSearch 数据建模

    公号:码农充电站pro 主页:https://codeshellme.github.io 通常在使用 ES 构建数据模型时,需要考虑以下几点: 字段类型 是否需要搜索与分词 是否需要聚合与排序 是否需 ...

  5. ElasticSearch——数据建模最佳实践

    如何建模 mapping 设计非常重要,需要从两个维度进行考虑: 功能:搜索.排序.聚合 性能:存储的开锁.内存的开销.搜索的性能 mapping 注意事项: 加入新字段很容易(必要时需要 updat ...

  6. 论Elasticsearch数据建模的重要性

    文章转载自: https://mp.weixin.qq.com/s?__biz=MzI2NDY1MTA3OQ==&mid=2247484159&idx=1&sn=731562a ...

  7. Elasticsearch 6.x版本全文检索学习之数据建模

    1.什么是数据建模. 答:数据建模,英文为Data Modeling,为创建数据模型的过程.数据模型Data Mdel,对现实世界进行抽象描述的一种工具和方法,通过抽象的实体及实体之间联系的形式去描述 ...

  8. Cassandra数据建模

    1.  概述 Apache Cassandra将数据存储在表中,每个表都由行和列组成.CQL(Cassandra查询语言)用于查询存储在表中的数据.Apache Cassandra数据模型基于查询并针 ...

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

    第二章 实体数据建模基础 很有可能,你才开始探索实体框架,你可能会问“我们怎么开始?”,如果你真是这样的话,那么本章就是一个很好的开始.如果不是,你已经建模,并在实体分裂和继承方面感觉良好,那么你可以 ...

随机推荐

  1. Oracle 12c新特性之——TABLE ACCESS BY INDEX ROWID BATCHED

    Oracle12c开始,我们在获取SQL语句的执行计划时,也会经常看到"TABLE ACCESS BY INDEX ROWID BATCHED"操作,那么,这个操作到底是什么意思呢 ...

  2. vscode代码保存时自动格式化成ESLint风格(支持VUE)

    一.问题 vscode的默认的代码格式化ctrl+shift+f 无法通过eslint的代码风格检查是一个非常蛋疼的问题 同样在进行vue项目开发的时候,使用eslint代码风格检查是没啥问题的,但是 ...

  3. time_wait 和 close_wait

    tcp 四次握手状态图: 使用以下命令统计 tcp 连接信息: netstat -n |awk '/^tcp/ {++S[$NF]} END {for (a in S) print a, S[a]}' ...

  4. Python3+ssl实现加密通信

    一.说明 1. python标准库ssl可实现加密通信 2. ssl库底层使用openssl,做了面向对像化改造和简化,但还是可以明显看出openssl的痕迹 3. 本文先给出python实现的soc ...

  5. 使用Redis数据库(1)(三十三)

    Spring Boot中除了对常用的关系型数据库提供了优秀的自动化支持之外,对于很多NoSQL数据库一样提供了自动化配置的支持,包括:Redis, MongoDB, Elasticsearch, So ...

  6. oracle create tablespace

    ALTER PROFILE DEFAULT LIMIT PASSWORD_LIFE_TIME UNLIMITED; sqlplus shybt/shybt@127.0.0.1:1521/orcl Cr ...

  7. asp.net mvc如何获取url的相关信息

    1.获取完整url信息(协议名+域名+虚拟目录名+文件名+参数) string url = Request.Url.ToString(); 如: //1)获取完整url(协议名+域名+虚拟目录名+文件 ...

  8. win10打文件预览功能

  9. Win10系列:VC++绘制几何图形2

    新建了Direct2D中的资源后,接下来初始化用于绘制图形的应用窗口.在解决方案资源管理器窗口中右键点击项目图标,在弹出的菜单栏中选中"添加", 并在"添加"的 ...

  10. 遍历存储所有物体添加到列表中(使用GameObject.activeSelf进行判断)

    //存储菜单列表 List<GameObject> subMenu = new List<GameObject>(); //存储所有子菜单 public void StoreS ...