当前位置: 首页 > news >正文

五分钟掌握 TDengine 数据文件的工作原理

小 T 导读:今天我们来探讨一下——TDengine中的时序数据到底是如何存储的?

在上一期的文章《五分钟掌握 TDengine 时序数据的保留策略》中,我们知道了TDengine是如何按照时间段对数据进行分区来管理数据的。

接下来,我们和大家一起从产品使用者的视角继续向前探索——TDengine中的时序数据到底是如何存储的?

在那篇文章里,在我们第一次写入数据并重启数据库服务后,在vnode xx路径下看到了这三个文件。

图片

这哥仨,其实就是TDengine中广义上的数据文件,也可以说它们是一个数据文件组。

从后缀上看,仿佛.data这个文件就是数据文件组中的数据文件。而其他二位都是为它保驾护航的“辅助”。但是这个感觉是不够准确的,因为.last文件同样也会存储数据。而.head文件则是存储数据块的索引的文件。

在了解它们之前,首先我们要知道两个参数:

1.minRows:数据块中记录的最小条数,单位为条,默认值为100。

2.maxRows:数据块中记录的最大条数,单位为条,默认值为4096。

数据块,是每个.data数据文件里存储数据的单位,每一个数据块都只能存储一个表的数据。所以上面的参数描述的意思就是——形成一个数据块默认的最小行数是100行,最多就是4096行。

那么,对于一张表来说,小于100行的话数据会去哪儿呢?大于4096行的话数据又去哪儿了呢?

答案是,.last文件正是表行数不足100时数据存放的位置;而大于4096行的表会生成一个新的数据块。最终在.data文件中,数据块的分布方式如下:

图片

当然,这样讲会比较抽象,我们继续用实例说明:

我们假设创建库时使用的参数为 maxrows=1000,minrows=100。某库中有两张表A和B,我们向其中分别插入1000行和99行数据。然后,我们重启taosd服务,以上数据就会从内存中落盘到存储上。这个时候.data文件中会生成1个数据块,它就是表A的数据块1,里面拥有1000条数据。而表B的99条数据因为不足minrows所以就进入了.last文件。

接下来,继续向它们分别插入1000行和99行,然后重启taosd服务落盘。这个时候表A总共拥有2000条数据,新写入的1000行数据会被写入进表A的数据块2。而表B的数据量现在已经有了198行,大于了100行。于是它们也会被写入.data文件里面,成为表B的数据块1。

值得注意的是,当.last文件小于32k的时候,所有数据都只会追加进来。但是当.last文件大于32k的时候,每次落盘.last文件都是重写生成的了——这个的32k限制是为了防止数据的移动过于频繁。

所以,我们在做测试的时候会发现:为什么当该表行数从99到100行以上时,.data文件的大小已经增加可.last文件却没有变小。只有当.last文件大于32k的时候,才能看到符合我们心理预期的效果——.last文件把数据移到.data文件,.last文件变小,.data文件变大。

以上场景只针对两个表,但其实放大到100个表,1000个表都是一样的逻辑。尽管每个vnode内存里存储的大量数据分属于不同的表,但是每次落盘只要这些表的行数保证大于minrows,它们都会落入到.data文件的数据块中。不满足上述条件的表数据被写入.last文件后,继续等待新数据的写入,直到该表满足了行数minrows的大小后,.last文件中该表的数据会被读入到内存,之后一起写入到.data文件中。

最后总结一下:

.data类文件存储的是真正的时序数据,为多个数据块构成。一个数据块只属于一张表,且数据块的顺序只与落盘的先后顺序有关。

.last文件与.data文件一样,也是存储时序数据的,只不过.last文件存储的块中的数据条数小于minRows。

本篇文章重点讲述的是.last与.data文件的关系。

关于.head文件,我们会在后面的文章中讲解。在此之前,我们只要知道它是用来方便查询数据的索引文件就可以了。.head文件的用途是什么?它会影响到哪些重要的功能?minrows和maxrows的变化会给性能带来多大的影响呢?以上这类问题都会涉及到很广泛的性能问题,我们将会在今后的日子慢慢讨论。

如果不了解TDengine的体系架构,对于用户来说很可能是事倍功半的。现在,涛思数据的每一期内容推送都是在为大家未来可以事半功倍而做的内容沉淀。

关于 TDengine

TDengine  是一款专为物联网、工业互联网等场景设计并优化的大数据平台,其核心模块是高性能、集群开源、云原生、极简的时序数据库。

http://www.lryc.cn/news/592382.html

相关文章:

  • 【Unity】IEnumeratorCoroutine
  • 【面试题】大厂高压面经实录丨第二期
  • 解锁 Java 并发编程的奥秘:《Java 并发编程之美》中的技术亮点与难题攻克
  • 构建直播平台大体的流程
  • Netty封装Websocket并实现动态路由
  • 在git中同时配置gitcode和github访问权限
  • 微信小程序 wx.request() 的封装
  • 【图像处理基石】什么是CCM?
  • 解决 Selenium 页面跳转过快导致的内容获取问题:从原理到实践
  • 填坑 | React Context原理
  • 29、鸿蒙Harmony Next开发:深浅色适配和应用主题换肤
  • 私有服务器AI智能体搭建配置选择记录
  • 苍穹外卖项目日记(day12)
  • 再探Java多线程Ⅱ --- (创建方式+等待唤醒+Lock锁)
  • 【论文蒸馏】Recent Advances in Speech Language Models: A Survey
  • 《设计模式之禅》笔记摘录 - 8.命令模式
  • 企业如何让内部视频仅限公司官网或指定域名播放?
  • 2025年SEVC SCI2区,利用增强粒子群算法(MR-MPSO)优化MapReduce效率和降低复杂性,深度解析+性能实测
  • 某邮生活旋转验证码逆向
  • 5W8-3D牢游戏超级大集合[2012年6月] 地址 + 解压密码
  • Python绘制数据(二)
  • C语言实战:超级玛丽游戏
  • 工业数据集成中间件工具OPC Router详细介绍
  • 大模型格式
  • sky-take-out项目Mybatis的使用
  • AE电源MDX 5K 10K 15K 20K 25K 30K手侧操作使用说明
  • 【Linux】环境基础与开发工具的使用
  • 数据结构--JDK17新增语法和顺序表
  • blender如何队列渲染多个工程文件的动画?
  • 集训Demo4