在关系数据模型中,我们为域中的每个对象建模关系/表。 对于Cassandra,情况并非如此。本文将详细介绍在Cassandra中进行数据建模时需要考虑的所有方面。 以下是Cassandra数据建模的粗略概述。


从上图可以看出, 概念数据建模和应用程序查询是构建模型时要考虑的输入。 对于任何建模(无论是关系数据库还是Cassandra),概念数据建模都是相同的,因为它更多地是关于从实体,关系及其属性方面获取所需系统功能的知识(因此而得名-ER模型)。

考虑以下有关病理实验室门户的示例。 通过此病理实验室门户,实验室可以向同意进行建议的所有测试的门户进行注册。 此外,它还允许患者(用户)在门户网站上注册,以通过他/她选择的实验室预订测试约会。 这是概念模型的相关部分,将在Cassandra中进行数据建模:


Cassandra中的数据建模是查询驱动的。 因此,下一步是确定需要支持的应用程序级查询。 对于所举的示例,以下是我们感兴趣的查询列表:

  • 问题1:通过指定的注册号获取实验室详细信息?
  • 问题2:按预订顺序获取给定实验室要处理的所有待处理订单?
  • 问题3:通过用户的电子邮件ID /电话号码查看用户的详细信息?
  • 问题4:获取指定时间段内用户的所有挂单?

映射规则:列出应用程序查询后,将应用以下规则将概念模型转换为逻辑模型。

  • 规则1:列出我们将在其上执行基于相等性的查询的属性。 例如:按注册编号查找实验室。
  • 规则2:列出在上一步中列出的查询中必须使用的基于范围的属性。
  • 规则3:应用程序感兴趣的结果是否有排序? 例如:返回用户按其姓名升序/降序排序?

从概念模型和查询中,我们可以看到仅在第一季度使用了实体“实验室”。 由于Q1基于等式,因此只能从映射规则中应用规则1。 因此,“实验室”表可以设计如下:

create table lab_detail(registration_number text, name text, address text, primary key(registration_number));

实体“用户”已在第三季度使用。 该查询指定通过电子邮件ID或电话号码获取用户详细信息。 在关系数据库中,我们可以使用电子邮件ID /电话号码之一作为标识符创建单个用户表。 如果表中的数据很大,则可以在非标识符列上创建索引以加快数据检索速度。 但是在Cassandra中,这是以不同的方式建模的。 我们可以使用2个表来解决这个问题:

create table users_by_email(email text primary key, phone_number text, first_name text, last_name text, address text);
create table users_by_phone(phone_number text primary key, email text, first_name text, last_name text, address text);

当我们要基于不属于主键的列查询表时,可以使用二级索引 。 但是在表上创建二级索引时必须小心。 不建议在许多情况下使用它们:

  1. 在高/低基数列上创建索引时,这无济于事。 如果我们根据用户标题(Mr / Mrs / Ms)进行索引,则最终将在索引中形成大量分区。
  2. 同样,如果我们在电子邮件ID上创建索引,因为大多数电子邮件ID是唯一的,在这种情况下,最好创建一个单独的表。
  3. 同样,我们不应该在大量更新的列上创建索引。 如果生成的墓碑比压缩过程可以处理的高得多,这些索引可能会产生错误。

如我们所见,二级索引不适合我们的用户表,最好创建一个满足应用程序目的的其他表。 请注意, 数据复制在Cassandra数据建模中非常普遍。 但是出于性能原因,我们应该限制我们愿意复制多少数据。 现在,创建不同表的问题在于,需要注意可能的数据一致性异常。

  • 如果更新在一个表中成功而在另一个表中失败,该怎么办?
  • 如何使两个表中的数据保持一致,以便在两个表中为用户查询数据都能获得相同的结果?

尽管Cassandra不支持参照完整性,但是有一些方法可以解决这些问题- 批次和轻量交易 (LWT) 。 请注意,与关系数据库一样,Cassandra中的批处理未用于提高性能。 此处的批处理用于实现操作的原子性,而异步查询用于提高性能。 批处理操作的不正确使用可能由于协调器节点上的更大压力而导致性能下降。 更多关于此这里 。 当需要在写入之前执行读取时,LWT可用于实现数据完整性(要写入的数据取决于已读取的数据)。 但是,据说LWT查询比常规查询慢很多倍。 使用LWT时,需要特别小心,因为它们的伸缩性不好。

实现此目的的另一种方法是使用实例化视图 。 它们解决了应用程序维护多个引用相同数据的表同步的问题。 为了保持数据与基本表一致,Cassandra代替了应用程序维护这些表,而是负责更新视图。 结果,为了保持这种一致性,写操作将受到很小的性能损失。 但是,一旦创建了物化视图,我们就可以像对待其他任何表一样对待它。 既然我们已经了解了视图,那么我们可以重新考虑先前的users_by_phone设计:

create table users_by_email(email text primary key, phone_number text, first_name text, last_name text, address text);
create materialized view users_by_phone as
select * from users_by_email where phone_number is not null and email is not

null and primary key(phone_number, email);

注意,“不为空”约束必须应用于主键中的每一列。 因此,到目前为止,我们已经在应用程序工作流程中解决了Q1和Q3。 现在剩下第二和第四季度了:

  • 问题2:按预订顺序获取给定实验室要处理的所有待处理订单?
  • 问题4:获取指定期间内用户的所有挂单?

在一种情况下,必须由用户获取订单详细信息,而在另一种情况下,必须由实验室获取订单详细信息。 在关系数据库中,我们将订单,用户和实验室建模为不同的关系。 使用读取数据的JOIN查询可以在这些关系上实现Q2和Q4。 由于无法进行读取级别连接,因此必须在Cassandra中以不同的方式进行建模。 必须完成数据非规范化才能实现此用例。 作为非规范化的一部分,数据将被复制。 但是,如前所述,Cassandra的经验法则之一就是不要将数据复制视为一件坏事。 与时间相比,我们基本上会在空间上进行权衡。 由于以下原因, Cassandra宁愿在写入时联接而不是在读取时联接。

  • 可以通过向群集添加更多节点来扩大数据复制的规模,而联接则无法处理大量数据。
  • 同样,数据复制允许具有恒定的查询时间,而分布式联接对协调器节点施加了巨大压力。 因此,它建议写时连接而不是读时连接。 由于实验室和用户完全是两个不同的实体,因此可以使用两个不同的表对这些查询进行建模。

Cassandra的一般建议是尽可能避免客户端加入。 因此,我们使用逻辑模型中的表(orders_for_user)和视图(orders_for_lab)从概念模型中对“订单”实体进行建模,就像之前所做的那样。 创建支持Q4的表时,必须考虑映射规则#1(基于平等的属性:user_id)和#2(基于范围的属性:booking_time)。 将列order_id和test_id作为主键的一部分添加,以支持该行的唯一性。

create table orders_for_user(user_id text, order_id text, lab_id text, test_id text, booking_time timestamp, amount_paid double, primary key(user_id, booking_time, order_id, test_id));

同样,可以根据映射规则#1(基于平等的属性:lab_id)和#3(属性的聚类顺序:booking_time)对视图进行建模

create materialized view orders_for_lab as
select * from orders_for_user where lab_id is not null and order_id is not

null and test_id is not null and user_id is not null primary key(lab_id,
booking_time, test_id, order_id, user_id) with clustering order by(booking_time asc, order_id asc, test_id asc, user_id asc);

最后要考虑的一点是,建模数据时不要让分区大小变得太大。 可以将新字段添加到分区键以解决此不平衡问题。 例如:如果某些实验室与其他实验室相比订单过多,则会通过将更多的负载分配给集群中的几个节点来在其中创建不平衡的分区。 为了解决这个问题,我们可以添加一个bucket-id列,将每个实验室1000个订单分组到一个分区中。 通过这种方式,负载在群集的所有节点之间平均分配。

翻译自: https://www.javacodegeeks.com/2019/05/data-modeling-cassandra.html

Cassandra中的数据建模相关推荐

  1. cassandra数据备份_Cassandra中的数据建模

    cassandra数据备份 在关系数据模型中,我们为域中的每个对象建模关系/表. 对于Cassandra,情况并非如此.本文将详细介绍在Cassandra中进行数据建模时需要考虑的所有方面. 以下是C ...

  2. 快用云科阎志涛:现代数据栈中的数据建模

    嘉宾 | 阎志涛   整理 | 黄引红 出品 | CSDN云原生 现代数据栈作为与数据分析相关的技术栈,具有云原生的特性,它与传统的数据平台相比较,降低了数据使用的技术门槛,也能满足用户日益扩大的数据 ...

  3. 浅谈数据仓库建设中的数据建模方法

    http://www.ibm.com/developerworks/cn/data/library/techarticles/dm-0803zhousb/ 所谓水无定势,兵无常法.不同的行业,有不同行 ...

  4. 数据仓库建设中的数据建模方法(转)

    简介: 本文的主要内容不是介绍现有的比较流行的主要行业的一些数据模型,而是将笔者在数据仓库建设项目中的一些经验,在这里分享给大家.希望帮助大家在数据仓库项目建设中总结出一套能够合乎目前业界规范的,满足 ...

  5. 数据建模_浅谈数据仓库建设中的数据建模方法

    所谓水无定势,兵无常法.不同的行业,有不同行业的特点,因此,从业务角度看,其相应的数据模型是千差万别的.目前业界较为主流的是数据仓库厂商主要是 IBM 和 NCR,这两家公司的除了能够提供较为强大的数 ...

  6. python数据入库_python爬虫(中)--数据建模与保存(入库)

    前言 前面,讲的是提取出来的数据保存进一个extracted_data,再保存进extracted_data_,变成一个list包含list的情况,当然你只提取一项,那就没有必要这么做了,可是我的项目 ...

  7. Scrapy框架items数据建模、翻页请求、requests对象请求、meta参数的使用

    1. 数据建模 通常在做项目的过程中,在items.py中进行数据建模 1.1 为什么建模 定义item即提前规划好哪些字段需要抓,防止手误,因为定义好之后,在运行过程中,系统会自动检查 配合注释一起 ...

  8. Elasticsearch之数据建模

    数据建模 英文为 Data Modeling, 为创建数据模型的过程 数据模型(Data Model) - 对现实世界进行抽象描述的一种工具和方法 - 通过抽象的实体及实体之间联系的形式去描述业务规则 ...

  9. 5模型数据起别名_DMBOK 06|数据建模与设计

    数记达摩院 提供高效能数据知识体系学习解决方案 您好,欢迎来到数记达摩院,我是王兵.今天我们来一起学习,DMBOK数据管理知识体系 第五章 数据建模与设计. 开始之前,我们先回顾一下上节课讲述的内容. ...

最新文章

  1. 数值优化(Numerical Optimization)学习系列-文件夹
  2. acm第二节2020.4.2-4.4补
  3. QT的QStringList类的使用
  4. (四)RabbitMQ消息队列-服务详细配置与日常监控管理
  5. NLP(新闻文本分类)——数据读取与数据分析
  6. 春考本科2018招计算机的学校,山东2018春季高考本科普通批一志愿院校投档情况统计表...
  7. 京东商城选择地址信息
  8. Linux命令之top命令
  9. java雪崩_缓存穿透和雪崩
  10. 牛客算法周周练11A - 切题之路(阅读理解)
  11. np.arry()的用法
  12. legacy引导gpt分区_传统Legacy引导和MBR硬盘格式无损更换UEFI和GPT的操作
  13. phpcms视频库KU6改为优酷简单上传
  14. C/C++百题打卡[3/100]——约瑟夫问题
  15. USB2.0 HUB芯片 GM8220S完美替代创维GL850G
  16. (PMP)第9章-----项目资源管理
  17. 正益王国春:从技术领导者到生态协同者的跨越
  18. 日照python培训_日照市学习it课程
  19. ZBar 二维码扫描,
  20. arcgis api for4.x 绘制圆,及坐标转换问题

热门文章

  1. [USACO]Sprinklers 2: Return of the Alfalfa P(网格DP)
  2. 牛客网暑期ACM多校训练营(第五场)
  3. ssh免密登陆失败原因总结(Linux)
  4. 你知道面试官是如何刷人的吗
  5. java 中 image 和 byte[] 相互转换
  6. Oracle入门(十二G)之序列
  7. 字符串拼接+和concat的区别
  8. 建立Vue脚手架的必要性
  9. 2015蓝桥杯省赛---java---A---1(熊怪吃核桃)
  10. Android 对话框,确定取消