本文来源:《华为云DTSE》第五期开源专刊作者:向宇,华为云数据库高级研发工程师、黄飞腾,博士,openGemini存储引擎架构师

在时序数据场景中,大部分的解决方案是以时间线为粒度对时序数据进行管理,这类解决方案在时间线数量不断增长的情形下,面临着诸多困难,包括内存膨胀、读写性能下降等,华为云开源时序数据库openGemini 针对该场景,提出了全新的列存引擎(HSCE),以解决海量时间线所带来的问题。

高基数问题长期困扰时序数据库

时序数据是一种常见的数据类型,广泛应用于车联网、工业物联网、航空航天、电力、DevOps 等领域。这类场景需要衡量事物状态随时间的变化,以便进行监控、分析和预测。例如,在DevOps中,我们需要监控服务的并发请求量;在工业物联网中,我们需要监控设备运行状态。鉴于时序数据产生频繁,且数据量很大,时序业务对实时性和查询效率要求高,通常会使用时序数据库对数据进行管理。

但在实际应用场景中,我们发现随着设备(例如车辆、终端设备等)数量达到一定量级后,时序数据库的读写性能会有明显的下降,延时波动剧烈,通过升级机器规格也无明显提升。导致这一现象的原因是海量时间线带来的高基数问题

什么是时间线?

在时序数据库中,时间线是对时间序列数据的建模,一条时间线的数据指同一数据源产生的一系列数据点的集合,可以简单理解为一台设备或者一辆车就是一条时间线。举个例子,有如下6条时序数据,由标签(A、B)、指标(C)和时间戳(Timestamp)组成。

A="a1",B="b1" C=2.82 1566000000

A="a2",B="b1" C=10.72 1566000000

A="a1",B="b2" C=15.82 1566000000

A="a1",B="b2" C=23.72 1568600000

A="a2",B="b3" C=1.36 1567000000

A="a2",B="b4" C=9.77 1568000000

存在5条时间线,分别是

A="a1",B="b1"

A="a1",B="b2"

A="a2",B="b1"

A="a2",B="b3"

A="a2",B="b4"

什么是高基数问题(High Cardinality)?

在数据库中,基数是指数据库的特定列或字段中包含的唯一值的数量。时间序列数据往往包含描述该数据的元数据(习惯称为“标签 或 TAG”)。通常,主要时间序列数据或元数据会被索引,以提高查询性能,以便使用者可以快速找到与之匹配的所有值。时间序列数据集的基数通常由每个单独索引列的基数的交叉乘积定义。如果有多个索引列,每个列都有大量唯一值,那么交叉乘积的基数可能会变得非常大。这就是软件开发人员在谈论具有“高基数”的时间序列数据集时通常的意思。

比如,以智能电表为例,它会关联设备 ID、城市 ID、厂商 ID 和模型 ID 等标签。几百个城市,百万级设备,再加上不同的厂商、模型,基数轻松超过百亿级。再比如,以网络监控为例,记录访问源到目的端经过的链路,它会关联源IP、目的IP、运营商、路由设备IP等标签,上百万IP地址产生大量链路信息,基数很容易达到千亿。

高基数问题根因在于时间线的倒排索引膨胀

倒排索引是时序数据库常用的一种索引技术,主要记录TAG和时间线之间的对应关系,给定一个或多个TAG,就可以快速找到相关的时间线,从而实现数据过滤,提升数据检索效率。

以如下数据为例

A="a1",B="b1" C=2.82 1566000000

A="a2",B="b1" C=10.72 1566000000

A="a1",B="b2" C=15.82 1566000000

A="a1",B="b2" C=23.72 1568600000

A="a2",B="b3" C=1.36 1567000000

A="a2",B="b4" C=9.77 1568000000

时序数据库中倒排索引的组织方式如下图所示:

现有大部分时序数据管理解决方案,通常会将数据按照时间线(即标签值的组合)进行聚簇,时间线相同的数据再按照时间进行排序,同时构建了标签(A)+标签值(如a1)到时间线的倒排索引,这种存储方式在时间线数量相对有限的情形下,可以提供极致的写入与查询性能,但是在处理高基数场景时,例如图中的A和B两个标签列下各有数百万不同值,那么总体时间线数量巨大,由于倒排索引与时间线数量相关,索引项激增,会导致内存膨胀、读写性能下降等问题。

高基数问题的解决方案剖析

高基数问题的核心在于优化索引结构,以提高索引的检索效率并减少内存占用。目前,稀疏索引被认为是一种高效的解决方案。ClickHouse数据库提供了一个实际的应用案例,用于我们研究这一问题。

Clickhouse在时序场景下存在局限性

以ClickHouse为例,分析其稀疏索引结构。

ClickHouse的稀疏索引不是为每一行数据创建一个索引条目,而是为一组数据行Granular(称为颗粒)构建一个索引条目。上图显示了官方如何将表中的887万行(列值)组织成1083个颗粒,每个颗粒对应主索引的一个条目,主索引被用来选择颗粒,就可以在主索引的支持下执行查询。

primary.idx 作为主键(稀疏)索引,可以用以加速查询,mrk2 文件作用类似主键索引,用于定位特定 column(bin文件) 对应的主键行所在的位置。

虽然ClickHouse的稀疏索引特别适用于处理大规模数据集,但ClickHouse数据库可能并不总是最适合时序数据的场景。例如,时序数据通常需要对时间序列进行特定的优化,如时间序列索引、窗口函数和时间序列聚合,这些可能在ClickHouse中不如专门的时序数据库那样得到优化。此外,时序数据的写入模式可能与ClickHouse的优化方向不完全一致,特别是在需要高吞吐量写入时。

openGemini结合了AP数据库优势与时序数据库特性,更加平衡高效

尽管如此,ClickHouse的稀疏索引技术仍然值得借鉴。通过将这种技术应用于时序数据库,可以更有效地管理时间线数据,减少内存空间的使用,同时保持快速的查询性能。因此,在openGemini在解决高基数问题时,考虑结合AP数据库的优势和专门的时序数据库特性,提供一个更加平衡和高效的解决方案。

openGemini 列存引擎解决该问题的核心思路主要包括:

  • 调整数据排序与索引方式:不再维护与时间线的关系,而是通过设置排序键对数据进行排序,在此基础上,将数据按列存储,并构建稀疏的聚簇索引,以支持数据的过滤查询。

  • 量化操作降低高基数列的基数:针对高基数列进行量化,以降低基数,这样可以进一步提高数据的局部有序性,提升索引的查询过滤效果。

  • 兼容 Apache Arrow Flight 协议:Apache Arrow Flight 是一种列式数据传输协议,可以实现高效的数据传输和写入。openGemini 利用该协议,消除了数据在写入流程中的转换开销,从而提升了数据写入性能。

假设有如下数据:

其中 A、C的基数较低,同时大部分查询需要对 A、C、Time 等列进行过滤,那么可以考虑将排序键设置为 A, C, Time 等,数据按照排序键排序之后变成:

排序完成之后,将数据按列存储,存储时以若干行(如 8192 行)为一个 Block 进行数据压缩并序列化,在此基础上,选取每个 Block 的第一条记录构建稀疏的聚簇索引。

可以看到,按照这种方式组织数据,位于第一个排序键的列是整体有序的,位于其他位置的排序键则是局部有序的,因此如果将低基数列放在排序键的前面,则可以使得数据的局部有序性更好,在此基础上,上述的稀疏聚簇索引就可以较好反映若干行或者一个 Block 的数据范围,进而有效支持数据过滤。

考虑到如果有多个列都包含有高基列,那么无论如何选择排序键,数据的有序性可能都不会特别理想,在这种情况下,可以考虑对其中部分高基列进行量化操作,降低该列的基数,以时间列为例,假设原始数据是以秒级进行采用生成的,那么即使仅考虑一个小时内的数据,时间列的基数都可能是数以千计,如果将时间列进行量化,使其对齐到小时粒度,那么这一个小时内的时间列基数就会降到1或者2,在这一基础上,使用量化过的时间列进行排序,无论将时间列放在排序键的哪个位置,都不会使得数据有序性劣化。同理,可以对需要排序的列进行类似的量化操作,这样就可以保证数据的整体有序性。

总体而言,openGemini 通过上述数据排序与索引方式,可以保证索引的构建不受时间线的影响, 同时数据的有序性也可以保证索引的查询过滤效果。同时在此基础上, openGemini 也通过兼容 Apache Arrow Flight 协议,一种列式数据传输协议,消除了数据在写入流程中的转换开销,极大提升了数据写入性能。

openGemini在华为云网络运维业务的实践

华为云网络运维服务的核心是基于广域网运维业务场景,提供基于运维诉求的测量数据,包括真实业务流RTT时延、丢包率、异常测量指标等,以实现对网络带宽的精准测量和实时分析。

华为云网络运维业务是一个典型的高基数场景,具有千亿级时间线规模。业务通过Agent采集通过设备的实时流量、实时流源目的地址、RTT时延等信息,以方便平台进行异常流分析、数据可视化分析等。

openGemini列存引擎(HCSE)成功解决了网络数据的高基数问题,为平台构筑了海量网流实时数据存储底座,相比原有解决方案,实现了端到端成本降低60%。数据处理吞吐量提升6+倍,数据分析性能(如Group By分组聚合分析)提升10+倍。

总结和展望

openGemini 通过引入新的数据排序与索引方式,开发了全新列存引擎,以解决海量时间线场景对于现有时序数据管理方案带来的问题。通过调整数据排序与索引方式,采用量化操作降低高基数列的基数,以及兼容 Apache Arrow Flight 协议等措施,成功解决了海量时间线数据管理中的内存膨胀、索引构建成本高等问题。这一创新提高了数据管理的效率和性能,为时序数据应用场景带来了新的解决方案。

通过全新列存引擎以及已有的时序引擎,openGemini 可以很好解决不同场景下的指标数据管理问题,未来 openGemini 还会针对日志、调用链等数据提供存储解决方案,以实现对可观测性数据的统一管理,为上层应用实现可观测性提供一个统一存储底座。


华为开发者空间是为全球开发者打造的专属开发者空间,致力于为每位开发者提供一台云主机、一套开发工具和云上存储空间。汇聚昇腾、鸿蒙、鲲鹏、GaussDB、欧拉等各项根技术的开发资源及工具,总有一款适合你! 点击链接:领取您的专属开发者云主机!

点击关注,第一时间了解华为云新鲜技术~

华为云开源时序数据库openGemini:使用列存引擎解决时序高基数问题的更多相关文章

  1. 华为云PB级数据库GaussDB(for Redis)揭秘第八期:用高斯 Redis 进行计数

    摘要:高斯Redis,计数的最佳选择! 一.背景 当我们打开手机刷微博时,就要开始和各种各样的计数器打交道了.我们注册一个帐号后,微博就会给我们记录一组数据:关注数.粉丝数.动态数-:我们刷帖时,关注 ...

  2. 华为云PB级数据库GaussDB(for Redis)揭秘第七期:高斯Redis与强一致

    摘要:在KV数据库领域,"强一致性"不仅是一个技术名词,它更是业务与运维的重要需求. 清明刚过,五一假期就要来了.大好春光,不如去婺源看油菜花吧!小云迅速打开APP刷出余票2张,赶 ...

  3. 华为云(ECS)-linux服务器中-Ubuntu图形界面安装-解决root登录受限-VNCviwer/Teamviwer远程访问教程

    安装ubuntu-desktop .更新软件库 apt-get update .升级软件 apt-get upgrade .安装桌面 apt-get install ubuntu-desktop 解决 ...

  4. 重磅!挑战Oracle,华为将开源 GaussDB 数据库

    来源:中关村在线,https://dwz.cn/nHNSOTeN 有消息称在正在进行的鲲鹏计算产业论坛上,华为宣布将开源其GaussDB数据库. GaussDB数据库是今年5月15日华为公布的分布式数 ...

  5. 日吞吐万亿,腾讯云时序数据库CTSDB解密

    一.背景 随着移动互联网.物联网.大数据等行业的高速发展,数据在持续的以指数级的速度增长,比如我们使用手机访问互网络时的行为数据,各种可穿戴设备上报的状态数据,工厂中设备传感器采集的指标数据,传统互联 ...

  6. 深度解读Facebook刚开源的beringei时序数据库——数据压缩delta of delta+充分利用内存以提高性能

    转自:https://yq.aliyun.com/topic/58?spm=5176.100239.blogcont69354.9.MLtp4T 摘要: Facebook最近开源了beringei时序 ...

  7. 华为云企业级Redis揭秘第16期:超越开源Redis的ACID"真"事务

    摘要: 开源Redis只支持伪事务,应用场景受限.高斯Redis发布企业级事务特性,支持完备ACID,为交易.库存等上层业务带来全新可能. 本文分享自华为云社区<华为云企业级Redis揭秘第16 ...

  8. 【云享专刊】开源遇上华为云,OCP架构变身“云原生框架”

    摘要:华为云DTSE团队出品云原生改造指南,助力轻松实践OCP上云. 本文分享自华为云社区<[云享专刊]开源遇上华为云,OCP架构变身"云原生框架">,作者:华为云社区 ...

  9. TimescaleDB比拼InfluxDB:如何选择合适的时序数据库?

    https://www.itcodemonkey.com/article/9339.html 时序数据已用于越来越多的应用中,包括物联网.DevOps.金融.零售.物流.石油天然气.制造业.汽车.太空 ...

  10. 0160 十分钟看懂时序数据库(I)-存储

    摘要:2017年时序数据库忽然火了起来.开年2月Facebook开源了beringei时序数据库:到了4月基于PostgreSQL打造的时序数据库TimeScaleDB也开源了,而早在2016年7月, ...

随机推荐

  1. SMU Autumn 2023 Round 1(Div.1)

    SMU Autumn 2023 Round 1(Div.1) A. Set or Decrease(枚举) 题意就是你可以进行两种操作,将\(a_i-1\)或者令\(a_i\)等于\(a_j\),然后 ...

  2. WPF自定义控件之ItemsControl鱼眼效果

    原理 先获取鼠标在控件中的坐标,在获取其每一项相对于ItemsControl的坐标,然后计算每一项离当前鼠标的距离,在根据这个距离,对其每一项进行适当的缩放 实现 创建一个类,命名为FishEyeIt ...

  3. Mac 删除 Steam 游戏图标

    Steam 将游戏安装在了 ~/Applications,打开访达,前往该目录,将相关游戏移到废纸篓.

  4. 《Effective TypeScript》条款21 - 类型扩展

    本文主要通过一些实际的代码示例,来帮助大家理解什么是类型扩展,本文主要内容如下: 什么是类型扩展 代码示例 总结 什么是类型扩展? TypeScript 需要从你指定的单一值中决定一组可能的值,这个过 ...

  5. .NET 工具库高效生成 PDF 文档

    前言 QuestPDF 是一个开源 .NET 库,用于生成 PDF 文档.使用了C# Fluent API方式可简化开发.减少错误并提高工作效率.利用它可以轻松生成 PDF 报告.发票.导出文件等. ...

  6. MySQL配置缓存查询和维护

    配置文件设置缓存 query_cache_size = 20M #缓存大小 query_cache_type = ON #开启缓存 table_cache=256 #用于限制缓存表的最大数目,如果当前 ...

  7. USB gadget驱动框架(五)

    本节主要分析虚拟串口的tty设备的注册.创建/dev/ttyGSx设备节点.tty相关接口的实现. tty的申请与注册 源码:drivers/usb/gadget/function/u_serial. ...

  8. USB 端点和管道的区别

    在USB体系架构中,经常会混用USB端点和USB管道的概念,包括本人也经常混用.但严格来说它们是两个不同的概念,具体表现在: 端点是USB设备端的概念,是真实的特理设备上的概念,其特性是通过端点描述符 ...

  9. dotnet 委托delegate的使用 定义和使用

    void Main() { // 委托 - 初级和高级的分水岭 // 1. 委托的初体验 // 委托是一个引用类型,其实是一个类型,保存方法的指针(地址) (变量名字都是地址 都是指针) // 是一个 ...

  10. 02-react中jsx的基本使用

    // 使用 createElement太繁琐 不直观 不优雅开发体验不好 代码维护不行 // jsx 不是 js 而是 js的扩展语法 // jsx 是react的核心内容 // react项目中已经 ...