性能超越 Clickhouse | 物联网场景中的毫秒级查询案例
1 物联网应用场景简介
物联网(Internet of Things,简称 IoT)是指通过各种信息传感、通信和 IT 技术来实时连接、采集、监管海量的传感设备,从而实现对现实世界的精确感知和快速响应,继而实现自动化、智能化管理。在查询 IoT 设备状态的场景下,吞吐量和时延是两个重要的性能指标。
在工业物联网中,常见有以下几种设备时序数据的查询需求:
- 案例1:查询某个设备最近的记录
- 案例2:查询某个租户所有设备的最近一条记录
- 案例3:查询某个设备最近5分钟的统计信息
- 案例4:查询某个设备最近一天的秒级数据
本教程通过一个工业物联网的案例,来演示 DolphinDB 的序列查询性能,并对比测试了 DolphinDB TSDB 引擎、OLAP 引擎,以及 ClickHouse MergeTree 引擎在上述查询案例上的时延指标。总体来说,DolphinDB TSDB 引擎的性能(时延)对比 DolphinDB OLAP 引擎和 ClickHouse MergeTree 引擎有显著优势。
2 案例数据准备
2.1 数据集说明
本教程参考了某工业物联网 SaaS 平台服务商的数据集,模拟并使用一份高度仿真的数据。该SaaS服务商的主要业务是监控各个地区的噪声情况。表结构如下:
序号 | 字段名称 | 字段类型 | 注释 |
---|---|---|---|
1 | tenantId | INT | 租户ID |
2 | deviceId | INT | 设备ID |
3 | soundPressureLevel | DOUBLE | 声音分贝 |
4 | soundPowerLevel | DOUBLE | 声音功率值 |
5 | ts | TIMESTAMP | 数据采集时间戳 |
6 | date | DATE | 日期 |
一行数据包含租户 ID、设备 ID、声压、噪声功率、采集时间戳和日期共计 6 列数据。每行记录占用 36 字节。该案例数据包含100 个租户,每个租户管理 100 个噪声监控设备,记录了从 2022-01-01 至 2022-01-12,12亿的噪声数据,共计 40G。
2.2 库表设计及数据模拟
使用 DolphinDB TSDB 引擎,创建一个名为 NoiseDB 的数据库,存储噪声数据。TSDB 引擎是 DolphinDB 自 2.00 版本起,专门为物联网场景设计研发的数据存储引擎,具备优秀的写入和序列查询性能。
在噪声监控的 SaaS 服务中,较为频繁的查询场景是以租户为维度,查询某一天某个设备的状态信息。因此设计 noise 表按日期、租户 ID 进行分区,可以有效利用分区剪枝。同时使用区分度较高的设备 ID 和数据采集时间戳作为排序键(查询索引),使查询时能够快速定位对应设备的数据,提升查询性能。具体实现脚本如下。
db1 = database(,VALUE,1000..2000)
db2 = database(, VALUE, 2022.01.01..2022.12.30) // TSDB for iot
dbNoise = database("dfs://NoiseDB",COMPO,[db1,db2], engine="TSDB") create table "dfs://NoiseDB"."noise"(tenantId INT,deviceId INT,soundPressureLevel INT,soundPowerLevel DOUBLE,ts TIMESTAMP,date DATE
)
partitioned by tenantId, date
sortColumns=[`deviceId,`ts]
库表创建完成后,模拟 2022-01-01 至 2022-01-12 的数据,具体代码详见附录 DolphinDB 脚本。
可以通过 SQL 查询验证下数据集大小:
select count(*) from loadTable(database("dfs://NoiseDB"),"noise") where date between 2022.01.01:2022.01.102> 1260010000
导入完成后,每个分区下生成3个level 0 file,未满足自动合并条件(大于等于10个 levelFile),需要进行手动合并。
chunkIds = exec chunkId from getChunksMeta() where type=1
for (x in chunkIds) {triggerTSDBCompaction(x)
}
完成后将案例数据导出数据至 csv 文件,以便后续导入 OLAP 引擎、ClickHouse。在 ClickHouse 中使用OPTIMIZE TABLE noise
合并下 mergeTree。具体过程参照附录 ClickHouse 脚本。
3 SQL 查询
在 DolphinDB 中,可以使用 SQL 快速实现4个设备状态查询需求,并且代码十分简洁。
- 案例1:查询某个设备最近的100条记录:
noise = loadTable(database("dfs://NoiseDB"),"noise")
select * from noise
where date=2022.01.01 and tenantId=1055 and deviceId=10067
order by ts desc
limit 100# timer(10) select ...
Time elapsed: 24.33 ms
脚本的 where 条件语句中指定了分区列 date 和 tenantId 进行过滤,便于 DolphinDB 系统通过分区剪枝快读定位到对应的分区。同时指定了数据库的 sort key (deviceId) 作为过滤字段,利用 TSDB 的索引机制,可以快速定位到数据块,并按时间顺序取回最新的100条记录。平均一次查询耗时 2ms,未命中缓存的首次查询耗时 14ms。
- 案例2:查询某个租户所有设备最新状态
noise = loadTable(database("dfs://NoiseDB"),"noise")
select * from noise
where date=2022.01.01 and tenantId=1055
context by deviceId
csort ts desc
limit 1# timer(10) select ...
Time elapsed: 246.619 ms
该脚本在 where 条件语句中同样指定了分区列以快速定位到对应的数据分区。通过 context by 子句来根据设备 ID 将数据进行分组,每组数据通过 csort 子句按时间倒序排列(考虑到物联网存在消息乱序的情况,必须使用csort将数据按采集时间排序)。使用 limit 1 获取每个窗口内的最新的一条记录,从而获取该租户当日所有设备的最新状态。平均一次查询耗时 25ms,首次查询耗时 121ms。
- 案例3:查询某个设备5分钟内的噪声统计值
noise = loadTable(database("dfs://NoiseDB"),"noise")
selectmin(ts) as startTs,max(ts) as endTs,max(soundPressureLevel),avg(soundPressureLevel),max(soundPowerLevel) ,avg(soundPowerLevel)
from noise
where date=2022.01.01 and tenantId=1055 and deviceId=10067 and ts between 2022.01.01T00:50:15.518:2022.01.01T00:55:15.518
group by tenantId, deviceId# timer(10) select ...
Time elapsed: 22.168 ms
该脚本首先根据 where 指定的过滤条件定位并扫描数据块,取出对应时间段的数据,并按 tenantId, deviceId 进行聚合计算,以获取声音分贝、功率的统计值。平均一次查询耗时 2ms,首次查询耗时 13ms。
- 案例4:查询某个设备最近一天的明细数据
noise = loadTable(database("dfs://NoiseDB"),"noise")
select *
from noise
where date=2022.01.01 and tenantId=1055 and deviceId=10067
order by ts# timer(10) select ...
Time elapsed: 23.261 ms
该脚本首先根据 where 指定的过滤条件定位并扫描数据块,取出对应时间段的明细数据,并按采集时间排序。平均一次查询耗时 2ms,首次查询耗时 16ms。
注:首次查询指未命中数据库缓存及操作系统缓存的查询。
4 对比测试
进一步测试 DolphinDB TSDB 引擎与 OLAP 引擎,以及 ClickHouse MergeTree 引擎在上述数据集的时序查询性能。测试过程中尽可能地保持环境变量相同,以保证科学有效。具体测试脚本详见附录。
4.1 测试环境
- 测试机器配置
操作系统:CentOS 7
CPU: 2 cores
内存:10 G
磁盘:SSD
- 核心测试参数
对测试中影响性能的关键参数,保持对等一致。
软件信息 | 核心参数 | 库表设计 |
---|---|---|
DolphinDB:2.00.6 单节点 | memSize=8G TSDB引擎 / OLAP引擎 | partitioned by tenantId, datesortColumns = [deviceId,ts] |
ClickHouse:22.6.1 单节点 | max_server_memory_usage=8GMergeTree引擎 | partition by tenantId, dateorder by deviceId, ts |
测试时,DolphinDB 和 ClickHouse 均采用单节点,并分配 8G 最大内存。在引擎方面,DolphinDB TSDB 引擎,ClickHouse MergeTree 引擎的内部实现都采用了 LSM-tree。并保持库表设计完全一致。
- 时间衡量标准
由于端到端的时间,容易受到网络抖动和客户端实现性能的影响,因此本次测试的测量时间设定为从查询引擎接收到请求至计算出结果为止。
4.2 测试结果
三者的具体测试结果为下表,表中数值为平均耗时/首次查询耗时(单位 ms),平均耗时的计算逻辑为:
平均耗时 = ( 首次耗时 + 9次缓存命中耗时 )/ 10
测试用例 | 场景 | DolphinDB TSDB | DolphinDB OLAP | ClickHouse |
---|---|---|---|---|
case1 | 查询某个设备最新100 条记录 | 2 / 14 | 34 / 51 | 14 / 150 |
case2 | 查询某个租户所有设备的最新状态 | 25 /121 | 62 / 170 | 73 / 400 |
case3 | 查询某个设备 5min的噪声统计值 | 2 / 13 | 15 / 136 | 12 / 82 |
case4 | 查询某个设备最近一天的明细数据 | 2 / 16 | 24 / 220 | 22 / 200 |
可以看出,OLAP 引擎和 ClickHouse 在不同的查询场景下性能各有其优势和劣势。
而 TSDB 引擎性能均优于 ClickHouse,在相对复杂的点查场景性能差距更大。在场景4下 ,DolphinDB TSDB 引擎比 ClickHouse 的性能高 12.5 倍,首次查询高13倍。在该场景中,TSDB 引擎需要读取对应设备的10000条记录,压缩后的存储大小约为90K。存储在6个连续的Block中,读取效率非常高效。而 ClickHouse 则是 scan 了该分区下1000000条记录的数据块,因此两者的首次查询性能差距较大,而缓存后的性能差距主要取决于两者在计算性能上的差别 。
5 总结
DolphinDB TSDB 引擎在物联网场景有着卓越的点查性能,可以以毫秒级延时迅速响应设备的状态信息,其性能更优于 ClickHouse 的 MergeTree 引擎。
6 附录
- DolphinDB 脚本
- ClickHouse 脚本
相关文章:

性能超越 Clickhouse | 物联网场景中的毫秒级查询案例
1 物联网应用场景简介 物联网(Internet of Things,简称 IoT)是指通过各种信息传感、通信和 IT 技术来实时连接、采集、监管海量的传感设备,从而实现对现实世界的精确感知和快速响应,继而实现自动化、智能化管理。在查…...

05、SpringBoot 集成 RocketMQ
目录 SpringBoot集成RocketMQ消息发送三种方式1、同步消息producer-springboot创建项目添加依赖配置文件同步消息发送代码启动类Test类 comsumer-springboot创建项目添加依赖配置文件同步消息消费代码 2、异步消息生产者消费者 3、一次性消息生产者消费者 消息消费两种方式1、集…...

PR2023中如何导入字幕
PR中如何导入字幕 方法一: 点开文本,字幕,新建字幕分段(点击右上角…三个点) 键入调整内容 方法二 点开基本图形,编辑,调整,拖动位置。...
读书笔记--华为数据之道有感
通过研读华为数据之道,了解到华为作为一家非数字原生企业,其业务涵盖研发、营销、制造、供应、采购、服务等,业务相当复杂。因此华为在开展数据治理过程中明确了由谁来对数据负责,特别是对数据质量负责,明确了数据质量的衡量或度量指标,并成立了数据管理部,确定其职能定…...

汽车数据安全事件频发,用户如何保护隐私信息?
面对日益增多的汽车数据安全事件,对于广大用户来说,有没有既廉价又安全的解决方案? 频发的汽车数据安全事件 随着汽车“新四化”大潮的来临,汽车用户从电动化、网联化、智能化、共享化中切实体验到了越来越多的便利,各…...

Redis主从复制流程
前言 Redis 支持部署多节点,然后按照 1:n 的方式构建主从集群,即一个主库、n 个从库。主从库之间会自动进行数据同步,但是只有主库同时允许读写,从库只允许读。 搭建主从复制集群的目的: 从库可用于容灾备份从库可以…...

微信公众号如何变更为订阅号?
公众号迁移有什么作用?只能变更主体吗?大家都知道,微信公众号是不支持直接变更主体的;但是很多情况下,我们又不得不进行账号主体的更换;这时候,我么就可以通过账号迁移功能,将A公众号…...

竞赛选题 深度学习YOLO抽烟行为检测 - python opencv
文章目录 1 前言1 课题背景2 实现效果3 Yolov5算法3.1 简介3.2 相关技术 4 数据集处理及实验5 部分核心代码6 最后 1 前言 🔥 优质竞赛项目系列,今天要分享的是 🚩 基于深度学习YOLO抽烟行为检测 该项目较为新颖,适合作为竞赛课…...
mysql利用mysqldump方式搭建主从
背景:线上环境在主库不停服的情况下,利用mysqldump的方式搭建从库。 建议:在主库比较小的情况下(个人建议50G左右),主库不停服可以利用mysqldump搭建从库。如果主库很大,建议利用mysql热备份工…...
如何保护IP在线隐私,提高网络安全?
在数字时代,我们的在线IP隐私面临着越来越多的威胁。黑客、广告商和第三方机构都试图获取我们的个人信息和浏览习惯。因此,保护您的在线IP隐私至关重要。本文将介绍一些简单但有效的方法,帮助您保护自己的隐私。 使用防关联浏览器:…...
掌握 C++ 编译过程:面试中常见问题解析
C是一种高级编程语言,但是计算机并不能直接理解它。因此,需要将C代码翻译成计算机可以理解的机器语言。这个过程就是编译过程,是C程序从源代码到可执行文件的转换过程,包括预处理、编译、汇编和链接四个阶段 预处理 在编译器开始…...
了解Qt QScreen的geometry ,size
目的 了解qt 对于屏幕的size, geometry含义, 更能有效实现最大化, 向下还原逻辑操作 Test 目前我有两个屏 ,1920x1080, 3840*2160. 检测当前程序所在screen(1920x1080)下属性 int screenNum…...

云安全—云计算基础
0x00 前言 学习云安全,那么必然要对云计算相关的内容进行学习和了解,所以云安全会分为两个部分来进行,首先是云计算先关的内容。 0x01 云计算 广泛传播 云计算最早大范围传播是2006年,8月,在圣何塞【1】举办的SES&a…...

【ARM Coresight Debug 系列 16 -- Linux 断点 BRK 中断使用详细介绍】
文章目录 1.1 ARM BRK 指令1.2 BRK 立即数宏定义介绍1.3 断点异常处理流程1.3.1 el1_sync_handler1.3.2 el1_dbg 跟踪 1.4 debug 异常处理函数注册1.4.1 brk 处理函数的注册 1.1 ARM BRK 指令 ARMv8 架构的 BRK 指令是用于生成一个软件断点的。当处理器执行到 BRK 指令时&…...
Rust星号(*)的作用-基础篇
在Rust中,*符号具有多种不同的用途,具体取决于它的使用方式。以下是Rust中*常见的用法. 1.解引用指针 当作为一元运算符放在指针变量之前时,*用于解引用指针并访问它指向的值。在Rust中,通常更推荐使用引用而不是原始指针。引用…...

企业该如何选择数字化转型工具?
对于希望在当今快速发展的商业环境中增强运营、提高效率并保持竞争力的公司来说,选择正确的数字化转型工具是一项关键决策。以下是选择数字化转型工具的关键步骤和注意事项: 1.定义业务目标: 清楚地阐明您的业务目的和目标。了解您希望通过数…...

element ui 中 el-button重新渲染后disabled属性失效
调试发现:disabled绑定的值和显示没有保持一致,发现是disabled属性失效 解决方式: 给标签添加key 比如:key“isOldVersion” <el-form-item><el-button type"primary" style"margin-left: 100px;" click"…...
WebRTC AIMD算法用处
WebRTC使用AIMD(Additive Increase Multiplicative Decrease)算法来进行码率控制。 在WebRTC中,码率控制的目标是优化音视频传输的质量和稳定性,以适应网络状况的变化。具体而言,AIMD算法通过监测网络的拥塞情况&…...
迁移kubelet、docker和containerd工作目录
文章目录 问题背景迁移Docker停止 Docker 服务修改配置移动文件重新启动 Docker 服务 containerd停止服务修改配置移动文件重新启动服务 kubelet(遇到问题待解决)停止服务修改配置移动文件(遇到问题待解决)重新启动服务 使用的版本…...
Go 重构:尽量避免使用 else、break 和 continue
今天,我想谈谈相当简单的事情。我不会发明什么,但我在生产代码中经常看到这样的事情,所以我不能回避这个话题。 我经常要解开多个复杂的 if else 结构。多余的缩进、过多的逻辑只会加深理解。首先,这篇文章的主要目的是让代码更透…...
Objective-C常用命名规范总结
【OC】常用命名规范总结 文章目录 【OC】常用命名规范总结1.类名(Class Name)2.协议名(Protocol Name)3.方法名(Method Name)4.属性名(Property Name)5.局部变量/实例变量(Local / Instance Variables&…...

学校招生小程序源码介绍
基于ThinkPHPFastAdminUniApp开发的学校招生小程序源码,专为学校招生场景量身打造,功能实用且操作便捷。 从技术架构来看,ThinkPHP提供稳定可靠的后台服务,FastAdmin加速开发流程,UniApp则保障小程序在多端有良好的兼…...
三体问题详解
从物理学角度,三体问题之所以不稳定,是因为三个天体在万有引力作用下相互作用,形成一个非线性耦合系统。我们可以从牛顿经典力学出发,列出具体的运动方程,并说明为何这个系统本质上是混沌的,无法得到一般解…...

OPENCV形态学基础之二腐蚀
一.腐蚀的原理 (图1) 数学表达式:dst(x,y) erode(src(x,y)) min(x,y)src(xx,yy) 腐蚀也是图像形态学的基本功能之一,腐蚀跟膨胀属于反向操作,膨胀是把图像图像变大,而腐蚀就是把图像变小。腐蚀后的图像变小变暗淡。 腐蚀…...

无人机侦测与反制技术的进展与应用
国家电网无人机侦测与反制技术的进展与应用 引言 随着无人机(无人驾驶飞行器,UAV)技术的快速发展,其在商业、娱乐和军事领域的广泛应用带来了新的安全挑战。特别是对于关键基础设施如电力系统,无人机的“黑飞”&…...
OD 算法题 B卷【正整数到Excel编号之间的转换】
文章目录 正整数到Excel编号之间的转换 正整数到Excel编号之间的转换 excel的列编号是这样的:a b c … z aa ab ac… az ba bb bc…yz za zb zc …zz aaa aab aac…; 分别代表以下的编号1 2 3 … 26 27 28 29… 52 53 54 55… 676 677 678 679 … 702 703 704 705;…...

使用SSE解决获取状态不一致问题
使用SSE解决获取状态不一致问题 1. 问题描述2. SSE介绍2.1 SSE 的工作原理2.2 SSE 的事件格式规范2.3 SSE与其他技术对比2.4 SSE 的优缺点 3. 实战代码 1. 问题描述 目前做的一个功能是上传多个文件,这个上传文件是整体功能的一部分,文件在上传的过程中…...

Linux 下 DMA 内存映射浅析
序 系统 I/O 设备驱动程序通常调用其特定子系统的接口为 DMA 分配内存,但最终会调到 DMA 子系统的dma_alloc_coherent()/dma_alloc_attrs() 等接口。 关于 dma_alloc_coherent 接口详细的代码讲解、调用流程,可以参考这篇文章,我觉得写的非常…...

sshd代码修改banner
sshd服务连接之后会收到字符串: SSH-2.0-OpenSSH_9.5 容易被hacker识别此服务为sshd服务。 是否可以通过修改此banner达到让人无法识别此服务的目的呢? 不能。因为这是写的SSH的协议中的。 也就是协议规定了banner必须这么写。 SSH- 开头,…...
Monorepo架构: Nx Cloud 扩展能力与缓存加速
借助 Nx Cloud 实现项目协同与加速构建 1 ) 缓存工作原理分析 在了解了本地缓存和远程缓存之后,我们来探究缓存是如何工作的。以计算文件的哈希串为例,若后续运行任务时文件哈希串未变,系统会直接使用对应的输出和制品文件。 2 …...