时序数据库 Apache-IoTDB 源码解析之元数据索引块(六)
上一章聊到 TsFile 索引块的详细介绍,以及一个查询所经过的步骤。详情请见:
时序数据库 Apache-IoTDB 源码解析之文件索引块(五)
打一波广告,欢迎大家访问 IoTDB 仓库,求一波 Star 。欢迎关注头条号:列炮缓开局,欢迎关注OSCHINA博客
阿里云、东方国信等各家公司正在招聘IoTDB数据库开发工程师,欢迎加我微信内推:liutaohua001
这一章主要想聊聊:
- 原有索引中的不足
- 新版本中索引的设计
原有索引中的不足

现在来张图回顾一下原有的数据存储方式,在文件尾部使用DeviceMetaDataIndexMap和MeasurementSchemaMap中记录所有设备数据偏移量、传感器的相关信息等。因为使用的是Map结构访问都是O(1)的,但是需要关注的一个问题就是它是在内存中O(1)的,在磁盘上并不能找到什么好的查询方式,唯一能做的就是全部读取出来然后放到内存中。
通常情况下这不会有什么问题,但是使用在工业场景中,传感器+设备很有可能数以百万计,这会引发无论你读取的是一个传感器或者是一个设备的数据,在DeviceMetaDataIndexMap这一段数据都需要完整的从磁盘上读取回来,这好吗?这不好,还拿之前的数据举例:
| 时间戳 | 人名 | 体温 | ... | 年龄 |
|---|---|---|---|---|
| 1580950800 | 张一 | 36.5 | ... | 30 |
| 1580950800 | 张二 | 36.9 | ... | 30 |
| 1580950800 | 张三 | 36.7 | ... | 30 |
| 1580950800 | 张.. | 36.7 | ... | 30 |
| 1580950800 | 张两百万 | 36.7 | ... | 30 |
当执行一个查询select 体温 from 张三 where time = 1580950800 时,张一、张二、张三...张两百万这两百万个名字都需要从硬盘中读取并反序列化出来(通常 IoTDB 中的路径是root.T000100010002.A_JB01.JB01.JTJBGMCA6K2052561),也就是1999999个都是多余的读取。
此外,在TsDeviceMetaDataList中,也是按照chunkGroup存储,意味着,如果我仅查询一列,同样会把其它的列信息读取出来。
新版本中索引的设计
为了尽可能贴近只读投影列的思想,新版本中对于TsDeviceMetaDataList部分不再按照设备级别存储,改为按照传感器级别存储,TsFileMetaData部分不再使用map存储所有设备,改为使用多叉树并有序排列。
改动1: 使用将一个传感器的所有ChunkMetaData的存储在一起,并使用TimeseriesMetadata结构进行维护(保存某个传感器的开始的offset及数据长度),如图: 
改动2: 在完成改动1之后,我们得到了TimeSeriesMetadata-年龄,TimeSeriesMetadata-体温, ..., TimeSeriesMetadata-x,在刷盘之前将所有TimeSeriesMetadata按照传感器名字排序,那么在这里就可以进行二分查找了,如图:

改动3: 在一个复杂的设备上传感器很有可能多达数千个,例如:新能源汽车当中,每台车量可以多达4000多个信号项。假如我们需要管理10万辆车,那么依然会有10万 * 4000 = 4亿个TimeSeriesMetadata。还是太多了,假如我们进行多个传感器的值查询时,每次都进行二分,这无疑是浪费的。
所以进行一个树状的提取,假设每1024个提取一次,那么4亿个可以节省为390,625个,假如再抽取一次,那就可以减少到382个了,这样我们从硬盘上一次读取1024个,最多读取3次硬盘就可以完成查找。大意如图: 
改动4: 除了传感器之外,还要考虑的是设备级别,因为设备也是数以万计,但同上面的逻辑是一样的。再此就不进行赘述,如图: 
在代码中使用MetadataIndexNode类进行存储图中的数据,代表了当前节点属于管理设备的节点还是管理传感器的节点,是中间节点还是叶子节点。使用MetadataIndexEntry用来存储具体的信息,也就是TimeSeriesMetadata结构在硬盘上的偏移量或者子节点MetadataIndexNode在硬盘上的偏移量.
附上一个文件展示:
POSITION| CONTENT
-------- -------
0| [magic head] TsFile
6| [version number] 000002
||||||||||||||||||||| [Chunk Group] of root.sg1.d1, num of Chunks:10000
12| [Chunk] of s8289, numOfPoints:500, time range:[0,499], tsDataType:INT64,
startTime: 0 endTime: 499 count: 500 [minValue:1,maxValue:1,firstValue:1,lastValue:1,sumValue:500.0]
| 1 pages
...
350026| [Chunk] of s0, numOfPoints:500, time range:[0,499], tsDataType:INT64,
startTime: 0 endTime: 499 count: 500 [minValue:1,maxValue:1,firstValue:1,lastValue:1,sumValue:500.0]
| 1 pages
...
1418902| [Chunk Group Footer]
| [marker] 0
| [deviceID] root.sg1.d1
| [dataSize] 1418890
| [num of chunks] 10000
||||||||||||||||||||| [Chunk Group] of root.sg1.d1 ends
1418947| [marker] 2
1418948| [ChunkMetadataList] of root.sg1.d1.s0, tsDataType:INT64
| [ChunkMetaData] of s0, offset:350026
...
2247838| [TimeseriesMetadata] name:s0, offset:1418948, chunkMetaDataListDataSize:80
3116728| [MetadataIndexNode] nodeType:LEAF_MEASUREMENT, childSize:10
| [MetadataIndexEntry] name:s0, offset:2247838, endOffset:2336808
| [MetadataIndexEntry] name:s192, offset:2336808, endOffset:2425782
| [MetadataIndexEntry] name:s2841, offset:2425782, endOffset:2514757
| [MetadataIndexEntry] name:s3763, offset:2514757, endOffset:2603732
| [MetadataIndexEntry] name:s4685, offset:2603732, endOffset:2692705
| [MetadataIndexEntry] name:s5606, offset:2692705, endOffset:2781680
| [MetadataIndexEntry] name:s6528, offset:2781680, endOffset:2870655
| [MetadataIndexEntry] name:s745, offset:2870655, endOffset:2959629
| [MetadataIndexEntry] name:s8371, offset:2959629, endOffset:3048604
| [MetadataIndexEntry] name:s9293, offset:3048604, endOffset:3116728
3116906| [TsFileMetadata] deviceNums:1,chunkNums:10000,invalidChunkNums:0
| [MetadataIndexNode] nodeType:INTERNAL_MEASUREMENT,childSize:1
| [MetadataIndexEntry] name:root.sg1.d1,offset:3116728,endOffset:3116906
| [bloom filter bit vector byte array length] 7794
| [bloom filter bit vector byte array]
| [bloom filter number of bits] 62353
| [bloom filter number of hash functions] 5
3124764| [TsFileMetadataSize] 7858
3124768| [magic tail] TsFile
3124774| END of TsFile
---------------------------------- TsFile Sketch End ----------------------------------
到此已经介绍完了文件的整体结构,以及索引的改进过程。
那么一个sql是如何执行的呢,是怎样进行的查询?又是怎样高速的写入数据?
欢迎持续关注。。。。
时序数据库 Apache-IoTDB 源码解析之元数据索引块(六)的更多相关文章
- 时序数据库 Apache-IoTDB 源码解析之文件索引块(五)
上一章聊到 TsFile 的文件组成,以及数据块的详细介绍.详情请见: 时序数据库 Apache-IoTDB 源码解析之文件数据块(四) 打一波广告,欢迎大家访问IoTDB 仓库,求一波 Star. ...
- Ocelot简易教程(七)之配置文件数据库存储插件源码解析
作者:依乐祝 原文地址:https://www.cnblogs.com/yilezhu/p/9852711.html 上篇文章给大家分享了如何集成我写的一个Ocelot扩展插件把Ocelot的配置存储 ...
- identityserver4源码解析_2_元数据接口
目录 identityserver4源码解析_1_项目结构 identityserver4源码解析_2_元数据接口 identityserver4源码解析_3_认证接口 identityserver4 ...
- 时序数据库 Apache-IoTDB 源码解析之文件数据块(四)
上一章聊到行式存储.列式存储的基本概念,并介绍了 TsFile 是如何存储数据以及基本概念.详情请见: 时序数据库 Apache-IoTDB 源码解析之文件格式简介(三) 打一波广告,欢迎大家访问Io ...
- tensorflow源码解析系列文章索引
文章索引 framework解析 resource allocator tensor op node kernel graph device function shape_inference 拾遗 c ...
- Mybatis源码解析(四) —— SqlSession是如何实现数据库操作的?
Mybatis源码解析(四) -- SqlSession是如何实现数据库操作的? 如果拿一次数据库请求操作做比喻,那么前面3篇文章就是在做请求准备,真正执行操作的是本篇文章要讲述的内容.正如标题一 ...
- identityserver4源码解析_3_认证接口
目录 identityserver4源码解析_1_项目结构 identityserver4源码解析_2_元数据接口 identityserver4源码解析_3_认证接口 identityserver4 ...
- [源码解析] 从TimeoutException看Flink的心跳机制
[源码解析] 从TimeoutException看Flink的心跳机制 目录 [源码解析] 从TimeoutException看Flink的心跳机制 0x00 摘要 0x01 缘由 0x02 背景概念 ...
- [源码解析] Flink的Slot究竟是什么?(1)
[源码解析] Flink的Slot究竟是什么?(1) 目录 [源码解析] Flink的Slot究竟是什么?(1) 0x00 摘要 0x01 概述 & 问题 1.1 Fllink工作原理 1.2 ...
随机推荐
- 十行 Python 代码就提取了韦小宝的身份证信息
本文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,如有问题请及时联系我们以作处理 记得以前有个广告词叫:"学好数理化,走遍天下都不怕",感觉应该再加一句:&quo ...
- Mysql 中的MDL
本文可以结合 MySQL中的事务原理和锁机制 查看. 首先简单了解一下 mysql 的 sql 类型: 1.数据定义语言 DDL:Create.Drop.Alter 操作.用于定义库和表结构的. 2. ...
- EF并发问题,在提供程序连接上启动事务时出错。有关详细信息,请参阅内部异常。
1 Entities data=new Entities(); var list = from p in data.Record where p.CreateTime >= d &&am ...
- (九)rmdir和rm -r删除目录命令
一.命令描述与格式 rmdir用于删除空目录 命令格式 :rmdir [选项] 目录名 选项: --ignore-fail-on-non-empty :忽略任何因目录仍有数据而造成的错误 ...
- Selenium ActionChains、TouchAction方法
ActionChains和TouchAction可以用来模拟点击.双击.滑动等事件.ActionChains用于执行PC端的鼠标移动.按键.拖拽等事件:TouchActions用法与ActionCha ...
- 轻松上手CSS Grid网格布局
今天刚好要做一个好多div格子错落组成的布局,不是田字格,不是九宫格,12个格子这样子,看起来有点复杂.关键的是笔者有点懒,要写那么多div和css真是不想下手啊.多看了两眼,这布局不跟网格挺像吗?c ...
- .NET 云原生架构师训练营(模块二 基础巩固 EF Core 更新和迁移)--学习笔记
2.4.6 EF Core -- 更新 状态 自动变更检测 不查询删除和更新 并发 状态 Entity State Property State Entity State Added 添加 Uncha ...
- Linux 时间同步 02 ntpd、ntpdate的区别
Linux 时间同步 02 ntpd.ntpdate的区别 目录 Linux 时间同步 02 ntpd.ntpdate的区别 [一]这样做不安全. [二]这样做不精确. [三]这样做不够优雅. ntp ...
- 安装cmake过程g++: 错误:unrecognized command line option ‘-std=gnu++14’
问题根因 这个错误一般是gcc/g++版本太低导致的 疑问 我本地明明安装的是高版本的gcc/g++为何说是低版本的呢,有图为证: 这主要是因为你安装了多个版本的gcc/g++,但是默认(/usr/b ...
- Pytest测试框架(五):pytest + allure生成测试报告
Allure 是一款轻量级.支持多语言的开源自动化测试报告生成框架,由Java语言开发,可以集成到 Jenkins. pytest 测试框架支持Allure 报告生成. pytest也可以生成juni ...