NoSQL 数据建模错误会降低性能

数据建模错误是破坏性能的最简单方法之一。当您使用 NoSQL 时,特别容易搞砸,(讽刺的是)NoSQL 往往用于对性能最敏感的工作负载。NoSQL 数据建模最初可能看起来非常简单:只需对数据进行建模以适应应用程序的访问模式。但实际上,说起来容易做起来难。

修复数据建模并不有趣,但它通常是一种不可避免的罪恶。如果您的数据建模从根本上来说效率低下,那么一旦扩展到某个临界点(根据您的特定工作负载和部署而变化),您的性能就会受到影响。即使您在最强大的基础设施上采用最快的数据库,除非您的数据建模正确,否则您将无法充分发挥其潜力。

本文探讨了破坏 NoSQL 数据库性能的三种最常见方法,以及有关如何避免或解决这些问题的提示。

不处理大分区

当团队扩展其分布式数据库时,通常会出现大型分区。大型分区是指变得太大以至于开始在集群副本中引入性能问题的分区。

我们经常听到的问题之一(至少每月一次)是“什么构成了大分区?” 这得看情况。需要考虑的一些事项:

  • 延迟预期:分区越大,检索所需的时间就越长。考虑页面大小以及完全扫描分区所需的客户端-服务器往返次数。

  • 平均有效负载大小:较大的有效负载通常会导致较高的延迟。它们需要更多的服务器端处理时间来进行序列化和反序列化,并且还会产生更高的网络数据传输开销。

  • 工作负载需求:某些工作负载自然需要比其他工作负载更大的负载。例如,我曾与一家 Web3 区块链公司合作,该公司将多个交易存储为单个密钥下的 BLOB,并且每个密钥的大小很容易超过 1 MB。

  • 如何从这些分区中读取:例如,时间序列用例通常具有时间戳集群组件。在这种情况下,从特定时间窗口读取将检索到的数据比扫描整个分区要少得多。

下表说明了大分区在不同负载大小(例如 1、2 和 4 KB)下的影响。

正如您所看到的,在相同的行数下,您的有效负载越高,您的分区就越大。但是,如果您的用例经常需要扫描整个分区,那么请注意数据库有限制以防止无限制的内存消耗。例如,ScyllaDB 每 1MB 就切断页面,以防止系统可能耗尽内存。其他数据库(甚至是关系数据库)也有类似的保护机制,以防止无限的错误查询导致数据库资源匮乏。要使用 ScyllaDB 检索 4KB 的负载大小和 10K 行,您需要检索至少 40 个页面才能使用单个查询扫描分区。乍一看这似乎没什么大不了的。但是,随着时间的推移进行扩展,它可能会影响整体客户端尾部延迟。

另一个考虑因素:对于 ScyllaDB 和 Cassandra 等数据库,写入数据库的数据存储在提交日志中和称为“memtable”的内存数据结构下。

提交日志是一种预写日志,除非服务器崩溃或服务中断,否则永远不会真正读取它。由于内存表存在于内存中,因此它最终会变满。为了释放内存空间,数据库将内存表刷新到磁盘。该过程会产生 SSTable(排序字符串表),这就是数据持久化的方式。

这一切与大分区有什么关系?嗯,SSTables 有特定的组件,需要在数据库启动时保存在内存中。这可确保读取始终高效,并最大限度地减少查找数据时存储磁盘 I/O 的浪费。当您拥有非常大的分区时(例如,我们最近有一个用户在 ScyllaDB 中拥有 2.5 TB 的分区),这些 SSTable 组件会带来沉重的内存压力,从而缩小数据库的缓存空间并进一步限制延迟。

如何通过数据建模解决大型分区问题?基本上,是时候重新考虑你的主键了。主键决定数据如何在集群中分布,从而提高性能和资源利用率。一个好的分区键应该具有高基数和大致均匀的分布。例如,用户名、用户 ID 或传感器 ID 等高基数属性可能是一个很好的分区键。像“州”这样的州将是一个糟糕的选择,因为加利福尼亚州和德克萨斯州等州可能比怀俄明州和佛蒙特州等人口较少的州拥有更多的数据。

或者考虑这个例子。下表可用于具有多个传感器的分布式空气质量监测系统:

CREATE TABLE air_quality_data (   sensor_id text,   time timestamp,   co_ppm int,   PRIMARY KEY (sensor_id, time));

由于时间 是我们表的聚类键,因此很容易想象每个传感器的分区可能会变得非常大,特别是如果每几毫秒收集一次数据。这张看似无辜的桌子最终可能会变得无法使用。在此示例中,仅需要大约 50 天。

标准解决方案是修改数据模型以减少每个分区键的集群键数量。在这种情况下,我们来看看更新后的`air_quality_data`表:

CREATE TABLE air_quality_data (   sensor_id text,   date text,   time timestamp,   co_ppm int,   PRIMARY KEY ((sensor_id, date), time));

更改后,一个分区保存一天收集的值,这使得它不太可能溢出。这种技术称为分桶,因为它允许我们控制分区中存储的数据量。

热点介绍

热点可能是大分区的副作用。如果您有一个大分区(存储大部分数据集),那么您的应用程序访问模式很可能会比其他分区更频繁地访问该分区。既然如此,它也成为热点。

只要有问题的数据访问模式导致集群中的数据访问方式不平衡,就会出现热点。罪魁祸首之一是应用程序未能对客户端施加任何限制,并允许租户潜在地向给定的密钥发送垃圾邮件。例如,考虑一下消息应用程序中的机器人经常在频道中发送垃圾邮件。不稳定的客户端配置也可能以重试风暴的形式引入热点。也就是说,客户端尝试查询特定数据,在数据库超时之前超时,并在数据库仍在处理前一个查询时重试查询。

监控仪表板应该可以让您轻松找到集群中的热点。例如,此仪表板显示分片 20 因读取而不堪重负。

再举一个例子,下图显示了三个利用率较高的分片,这与为相关键空间配置的三个分片的复制因子相关。

在这里,由于垃圾邮件,分片七引入了更高的负载。

如何解决热点问题?首先,在受影响的节点之一上使用供应商实用程序来对采样期间最常点击的键进行采样。您还可以使用跟踪(例如概率跟踪)来分析哪些查询正在命中哪些分片,然后从那里采取行动。

如果您发现热点,请考虑:

  • 检查您的应用程序访问模式。您可能会发现需要更改数据建模,例如前面提到的分桶技术。如果需要排序,可以使用单调递增组件,例如 Snowflake。或者,也许最好应用并发限制器并限制潜在的不良行为者。

  • 指定每个分区的速率限制,之后数据库将拒绝命中同一分区的任何查询。

  • 确保客户端超时 高于服务器端超时,以防止客户端在服务器有机会处理查询之前重试查询(“重试风暴”)。

滥用集合

团队并不总是使用集合,但当他们使用集合时,他们经常会错误地使用它们。集合用于存储/反规范化相对少量的数据。它们本质上存储在单个单元中,这会使序列化/反序列化变得极其昂贵。

使用集合时,您可以定义相关字段是冻结还是非冻结。冻结集合只能作为一个整体来写;您不能从中添加或删除元素。可以附加非冻结集合,而这正是人们最常误用的集合类型。更糟糕的是,您甚至可以拥有嵌套集合,例如一个地图包含另一个地图,其中包含一个列表,等等。

例如,误用的集合会比大分区更快地引入性能问题。如果您关心性能,集合根本不能太大。例如,如果我们创建一个简单的键:值表,其中键是` sensor_id`,值是随时间记录的样本集合,那么一旦开始提取数据,我们的性能将不是最佳的。

         CREATE TABLE IF NOT EXISTS {table} (               sensor_id uuid PRIMARY KEY,               events map<timestamp, FROZEN<map<text, int>>>,            )

以下监视快照显示了当您尝试一次将多个项目追加到集合时会发生什么情况。

您可以看到,虽然吞吐量下降,但 p99 延迟却增加。为什么会出现这种情况?

  • 集合单元作为排序向量存储在内存中。

  • 添加元素需要合并两个集合(旧的和新的)。

  • 添加元素的成本与整个集合的大小成正比。

  • 树(而不是向量)会提高性能,但是......

  • 树会降低小集合的效率!

返回同一示例,解决方案是将时间戳移动到聚类键并将映射转换为 FROZEN 集合(因为您不再需要向其中附加数据)。这些非常简单的更改将极大地提高用例的性能。

    CREATE TABLE IF NOT EXISTS {table} (               sensor_id uuid,        record_time timestamp,               events FROZEN<map<text, int>>,     PRIMARY KEY(sensor_id, record_time)            )

作者:Felipe Mendes

更多技术干货请关注公号【云原生数据库

squids.cn,云数据库RDS,迁移工具DBMotion,云备份DBTwin等数据库生态工具。

irds.cn,多数据库管理平台(私有云)。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/204034.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

BatchOutput PDF for Mac(PDF 批量处理软件)

BatchOutput PDF是一款适用于 Mac 的 PDF 批量处理软件。它可以帮助用户将多个 PDF 文件进行异步处理&#xff0c;提高工作效率。 BatchOutput PDF 可以自动化执行许多任务&#xff0c;包括 PDF 文件的打印、转换、分割、压缩、加密、重命名等&#xff0c;而且它还可以将自定义…

基于python 医院预约挂号系统-计算机毕业设计源码24802

摘 要 随着互联网时代的到来&#xff0c;同时计算机网络技术高速发展&#xff0c;网络管理运用也变得越来越广泛。因此&#xff0c;建立一个基于django 医院预约挂号系统 &#xff0c;会使&#xff1b;医院预约挂号系统的管理工作系统化、规范化&#xff0c;也会提高平台形象&a…

汽美汽修店服务预约会员管理系统小程序效果如何

很多家庭中都有一辆或多辆汽车&#xff0c;无论燃油车还是新能源电车等&#xff0c;其市场中的数量及人均拥有量都很大&#xff0c;除了汽车销售业外&#xff0c;汽车美容修理店则生意也很多&#xff0c;可以看到城市中的不少街道中都有大大小小的汽车服务门店。 而在市场中&a…

关于制造业数字化转型,大咖们有这些建议……

随着数字经济与实体经济深度融合&#xff0c;越来越多传统制造业企业走上数字化转型之路&#xff0c;实现生产、研发、管理、组织、商业模式等多层面的创新。为发挥鼎捷41年在制造业数字化转型的行业积淀&#xff0c;赋能更多制造业企业突破发展瓶颈&#xff0c;鼎捷携手来自工…

VC++调试QT源码

环境&#xff1a;vs2017 qt 5.14.2 1&#xff1a;首先我们需要选择我们的源码路径 右键解决方案-》属性-》通用属性-》调试源文件-》在窗口内添加QT下载时的源码**.src文件夹**&#xff0c;这里最好把源码 D:\software\QT\path\5.14.2\Src 源文件里面的Src文件做一个备份出来…

028 - STM32学习笔记 - ADC(二) 独立模式单通道中断采集

028 - STM32学习笔记 - 结构体学习&#xff08;二&#xff09; 上节对ADC基础知识进行了学习&#xff0c;这节在了解一下ADC相关的结构体。 一、ADC初始化结构体 在标准库函数中基本上对于外设都有一个初始化结构体xx_InitTypeDef&#xff08;其中xx为外设名&#xff0c;例如…

重生奇迹mu武器镶嵌顺序

一、武器的镶嵌顺序&#xff1a; 雷冰火30%概率出现技能11 从上到下的镶嵌顺寻按照雷、冰、火镶嵌&#xff0c;就有30%的概率出现技能攻击力加11的幸运荧光属性。 从上到下的镶嵌顺寻按照火、冰、雷镶嵌&#xff0c;就有30%的概率出现攻击力加11的幸运荧光属性。 例如&…

设计模式 【Adapter 模式】

Adapter 模式 1.什么是 Adapter 模式 用来填补现有的程序和所需的程序之间差异的设计模式就是 Adapter 模式。 Adapter 模式有两种&#xff1a; ● 类适配器模式&#xff0c;即使用继承的适配器 ● 对象适配器模式&#xff0c;即使用委托的适配器 2.使用继承的适配器示例…

Java Swing管理系统万能模板 课程设计素材

JavaSwing管理系统万能模板 视频教程&#xff1a; 【课程设计】2小时学会JavaSwing课程设计-万能模板-图书管理系统-[你的课程我设计] 万能模板是用Java Swing开发的&#xff0c;包含管理系统常用的多角色登录、数据查询、添加、修改、删除。常用的管理系统都可以使用万能模板…

轻松搭建Nextcloud私有云盘并实现公网访问本地资源

文章目录 摘要1. 环境搭建2. 测试局域网访问3. 内网穿透3.1 ubuntu本地安装cpolar3.2 创建隧道3.3 测试公网访问 4 配置固定http公网地址4.1 保留一个二级子域名4.1 配置固定二级子域名4.3 测试访问公网固定二级子域名 摘要 Nextcloud,它是ownCloud的一个分支,是一个文件共享服…

埃拉托色尼筛法

def is_prime(n):if n % 2 0 and n ! 2:return Falsefor i in range(3, int(math.sqrt(n) 1)):if n % i 0:return Falsereturn n ! 1def eratosthenes(n):primes []is_prime [True] * (n 1)for i in range(2, n1):if is_prime[i]:primes.append(i)# 用当前素数i去筛掉所有…

AT24C02数据读取异常问题(0xFF)

文章目录 问题描述解决方法总结 2023/11/29 问题描述 使用AT24C02模块&#xff0c;写入数据后立刻读取&#xff0c;读取到的数据出现异常&#xff0c;异常值为0xFF。 例如我们在主函数里&#xff0c;首先调用AT_Write函数往模块的0地址写入一个数据&#xff0c;接着多次调用AT…

【开源】基于Vue+SpringBoot的创意工坊双创管理系统

项目编号&#xff1a; S 049 &#xff0c;文末获取源码。 \color{red}{项目编号&#xff1a;S049&#xff0c;文末获取源码。} 项目编号&#xff1a;S049&#xff0c;文末获取源码。 目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 管理员端2.2 Web 端2.3 移动端 三、…

Python教程:装饰器的10个示例用法

Python装饰器是一种高级语法&#xff0c;它允许我们增强函数或方法的功能&#xff0c;而无需修改其原始代码。装饰器本质上是一个函数&#xff0c;它接收一个函数作为参数&#xff0c;并返回一个新的函数。这个新的函数可以包装原有函数&#xff0c;添加一些新的功能。 在Pyth…

重载、重写、重定义的辨析

C重载、重写、重定义 重载、重写、重定义对比一、重载&#xff08;overload&#xff09;二、重写 / 覆盖&#xff08;override&#xff09;三、重定义 / 隐藏&#xff08;redefining&#xff09; * 为什么在虚函数中不能使用 static 关键字&#xff1f;动态绑定&#xff08;Dyn…

上海震坤行:水泥行业数字化采购的趋势、策略与实践

上海震坤行&#xff1a;水泥行业数字化采购的趋势、策略与实践 在中国水泥协会发布的《2023年上半年水泥行业经济运行及下半年展望》中提到了水泥行业的发展现状——2023年上半年&#xff0c;在全球经济增长放缓、国内经济延续恢复态势、但市场需求不足的宏观环境下&#xff0…

直播间搭建设备

直播间搭建对设备的要求因直播类型和直播内容而异&#xff0c;但以下是一些常见的直播设备要求: 1.摄像头∶高清、稳定、画面流畅的摄像头是直播的必备设备。对于大部分直播来说&#xff0c;选择一个质量较好的网络摄像头或手机摄像头即可。但对于需要更高清晰度或专业级别的直…

论文学习-Bert 和GPT 有什么区别?

Foundation Models, Transformers, BERT and GPT 总结一下&#xff1a; Bert 是学习向量表征&#xff0c;让句子中某个词的Embedding关联到句子中其他重要词。最终学习下来&#xff0c;就是词向量的表征。这也是为什么Bert很容易用到下游任务&#xff0c;在做下游任务的时候&a…

C++ Primer 第十六章 模板与泛型编程 重点解读

文章目录 1 定义模板1.1 类模板成员函数的实例化&#xff1a;1.2 在类代码内简化模板类名的使用&#xff1a;1.3 令模板自己的类型参数成为友元&#xff08;C11&#xff09;1.4 模板类型别名1.4.1 typedef1.4.2 为模板定义类型别名(C11) 1.5 函数模板与类模板的区别1.6 使用类的…

SpringMVC多种类型数据响应

SpringMVC多种类型数据响应入门 1.概念 RequestMapping 作用&#xff1a;用于建立请求URL和处理请求方法之间的对应关系 位置&#xff1a; 类上&#xff0c;请求URL的第一级访问目录。此处不写的话&#xff0c;就相当于应用的根目录 方法上&#xff0c;请求URL的第二级访问目…