TSDB 存储引擎介绍

article/2025/9/2 20:45:12

本文介绍 DolphinDB 在2.0版本中新推出的存储引擎 TSDB。

1. OLAP 与 TSDB 适用的场景

OLAP 是 DolphinDB 在2.0版本之前的唯一存储引擎。数据表中每个分区的每一列存为一个文件。数据在表中的存储顺序与数据写入的顺序一致,数据写入有非常高的效率。

OLAP 引擎的主要局限有以下几点:

(1) 分区内不支持索引,即使只是检索几行数据,也必须加载整个分区(的相关列)。

(2) 写入过程设计简单,不支持去重;

(3) 不适合几百几千列的宽表存储。

(4) 即使修改一条记录,也必须重写整个分区。

TSDB 是 DolphinDB 基于 LSM 树自研的新的存储引擎。它很好的克服了 OLAP 引擎的局限,功能更加全面。每一个分区的数据写在一个或多个 level file 中。每一个 level file 内部的数据按照指定的列进行排序且创建块索引。

TSDB 引擎具有以下优点:

(1) 过滤条件使用分区列以及分区内排序字段的点查询非常高效。

(2) 可以在写入时对数据进行排序和去重。

(3) 适合存储几百几千列的宽表,也适合存储 array vector 和 BLOB 类型的数据。

(4) 若指定去重时保留最后一条记录(设置 keepDuplicates=LAST),则修改数据时重写数据所在 level file 即可,不需要重写整个分区。

与 OLAP 引擎相比,TSDB 引擎的不足之处在于:

(1) 写入吞吐量低。TSDB 引擎中,数据需在 cache engine 中进行排序;level file 会进行合并与压缩。

(2) 读取整个分区数据或整个分区的某几列数据时,效率低于 OLAP。

下面通过一个例子来解释 OLAP 与 TSDB 引擎适合的 query。假设数据表 t 按照股票代码与交易日进行 COMPO 分区。以下是该数据表中的4行数据:

StockIDTimestampBid
AAPL2021.08.05T09:30:001.5
MSFT2021.08.05T09:30:001.3
AAPL2021.08.05T09:31:001.6
GOOG2021.08.05T09:31:001.4
..................

OLAP 存储引擎的建库建表脚本如下:

dbTime = database("", VALUE, 2021.08.01..2021.09.01)
dbStockID = database("", HASH, [SYMBOL, 100])db = database(directory="dfs://stock",partitionType=COMPO,partitionScheme=[dbTime,dbStockId],engine="OLAP")schema = table(1:0, `Timestamp`StockID`bid, [TIMESTAMP, SYMBOL, DOUBLE])
stocks = db.createPartitionedTable(table=schema, tableName=`stocks, partitionColumns=`Timestamp`StockID)

TSDB 存储引擎的建库建表脚本如下:

dbTime = database("", VALUE, 2021.08.01..2021.09.01)
dbStockID = database("", HASH, [SYMBOL, 100])db = database(directory="dfs://stock",partitionType=COMPO,partitionScheme=[dbTime,dbStockId],engine="TSDB")schema = table(1:0, `Timestamp`StockID`bid, [TIMESTAMP, SYMBOL, DOUBLE])
stocks = db.createPartitionedTable(table=schema, tableName=`stocks, partitionColumns=`Timestamp`StockID, sortColumns=`StockID`Timestamp)

和 OLAP 的脚本相比,TSDB 的脚本在 database 初始化的时候指定存储引擎为 "TSDB",并在创建表格的时候指定 sortColumns 为 StockID 和 Timestamp

OLAP 引擎适合执行以下的 query:

select avg(Bid) from t where date=2021.08.05 group by StockID

TSDB 引擎适合执行以下的 query:

select * from table where StockID='AAPL', Timestamp > 2021.08.05T09:30:00, Timestamp < 2021.08.05T09:35:00

使用 OLAP 引擎所创建的数据库中,每个分区内部无索引,一个 query 从数据库中读取数据的最小单位是一个分区的一列。即使要查找一行数据,也必须读取该行数据所在分区的所有行,耗时一般在100毫秒以上。TSDB 引擎则在每个分区内部设置了索引,查找少量数据时无需读取分区内所有行,耗时可以低至几毫秒。TSDB 引擎在海量数据查询与分析方面的性能仅仅略慢于 OLAP 引擎。因此,若对查询少量数据有极致性能要求,推荐使用 TSDB 引擎。

2. TSDB原理简介

本节叙述中,为简便起见,我们将结合上一节中的例子。

2.1. redo log

redo log 类似于 Write-Ahead Log。数据加载到内存之后,会先持久化到 redo log 中。即便数据库在写入时宕机了,重启时,系统仍能够从 redo log 中恢复数据。

2.2. Cache Engine

确认数据写入 WAL 之后,数据会写入内存中的 cache engine。

新写入 cache engine 的数据是直接追加(append)的,且未经排序的(unsorted write buffer)。待缓存的数据量达到一个阈值之后,对其按照 StockID 排序(sorted write buffer)。sorted write buffer 是只读的,可在内存中开启压缩,以在内存中存储更多的数据,降低查询数据的时延。待产生多个 sorted write buffer,其总数据量达到一个阈值(由配置参数 TSDBCacheEngineSize 设定)之后,TSDB 会将所有 sorted write buffer 中的数据按照 Timestamp 排序后写入磁盘的数据文件(称为 level file)。

TSDB cache engine 的这种从 unsorted write buffer 到 sorted write buffer 两阶段的设计,与大多数的基于 LSMT 系统的 cache engine(或称 MemTable)有所不同。这种独特的设计是为了平衡系统的读性能与写性能。

请注意,在数据从 cache engine 写入磁盘的过程中,如果又有数据写入 cache engine,则 cache engine 会分配新的空间来存储新写入 cache engine 的数据。因此,在极端情况下,TSDB的 cache engine 最多会占用两倍的 TSDBCacheEngineSize 的空间。

2.3. Sort Columns

类似上例中 StockID 与 Timestamp 这样用于将数据进行排序的列,在 TSDB 中被称为 sort columns。sort columns 的最后一列必须为时间类型。sortColumns 除了最后一列的其他列通常为在点查中过滤条件会用到的列,其唯一值组合,称为 sort key。使用 TSDB 引擎,查询时可利用 sort key 直接定位到过滤条件所指定的数据块,然后仅读取这些数据块的数据,点查性能可大幅提升。

2.4. Level File

每个 level file 中的数据均按照 StockID 与 Timestamp 排序。每个 StockID 的记录会存储为多个一定大小(16KB)的数据块,并将每个数据块在该文件中存储的起始位置记录下来。后续写入的数据会写入另一个 level file,依此类推。

level file 最多可有4个 level。Level 0 的文件由 cache engine 写入到磁盘而产生,而更高层次的 level file 是由更低层次的 level file 合并生成的。每个 level 0 文件最大为32MB。每次从 cache engine 写入同一分区的数据量若大于 32MB,则产生多个 level 0 文件。从 level 0 到 level 1 的过程如下:当一个分区内的 level 0 文件数量超过10个或 level 0 总数据量大于某个阙值(256MB)时,所有 level 0 文件会被合并压缩为一个 level 1 的文件,以此类推。合并文件时会将数据按照 StockID 与 Timestamp 进行排序。通过不断进行数据文件的合并压缩,可以有效控制 level file 的数量,以免 level file 数量过多导致性能降低。

3. TSDB 使用技巧

本文在这一部分简单介绍 TSDB 的一些配置项和使用技巧。

3.1. 如何处理重复数据

一个分区内 sortColumns 重复的数据应当如何处理,由建表时 createPartitionedTable 函数的 keepDuplicates 参数指定。在上面这个例子中,即股票代码与时间列都一致的数据。默认的值为 ALL,即保留所有数据。若设置为 FIRST,则仅会保留重复数据中的第一条;若设置为 LAST,则仅会保留重复数据中的最新一条。

3.2. 控制 sort key 数量

为保证性能最优,建议每个分区内 sort key 最好不超过1000个。若 sort key 过多,每个 sort key 对应的数据量少,造成部分数据块内的数据量可能不足 TSDBMaxBlockSize,数据块数量也很多。当用户查询数据时,由于读取大量数据块,造成读文件耗时增加。此时,用户可通过建表函数指定 sortKeyMappingFunction,对 sort key 降维。请注意,降维操作一定程度上将影响写入性能,建议用户优先合理规划 sortColumns。

3.3. 设置 cache engine 容量

使用配置参数 TSDBCacheEngineSize 设定 cache engine 容量(以 GB 为单位)。默认值为 1GB,建议设置 1GB 或以上。

3.4. 设置 TSDB 数据块大小

使用配置参数 TSDBMaxBlockSize 设置存储时拆分的数据块(block)在压缩前的大小(以 bytes 为单位),默认值为16,384。这个参数越大,则数据的压缩率越高,但点查的性能也会有所下降。

3.5. 触发 level file 合并

level file 的数量越多,则查询的效率会越低。对不再有数据写入的分区,可使用 triggerTSDBCompaction 命令以手动触发 level 0 file 的合并,既可以提升查询性能,亦可提升压缩率。


存储引擎是数据库最核心、最复杂的组件之一。而在时序数据库的场景下,究竟该怎么设计一个存储引擎,至今仍是一个没有标准答案的开放性问题。

10月27日(本周四)19:30,DolphinDB 就邀请到了国内「知名工业互联网平台」解决方案专家陈超、「华夏基金」高级工程师李乾鹏以及「DolphinDB」研发副总监胡津铭,一同与大家探讨时序数据库极致性能背后的存储引擎。

扫描下方海报二维码,立即报名参加活动!

 


http://chatgpt.dhexx.cn/article/YvxmgJJq.shtml

相关文章

TSDB与Blockchain

各位小伙伴们我们又见面了&#xff0c;伴随着区块链技术的推广&#xff0c;很多企业也在思考是否将其应用。其实TSDB与区块链有很多共通之处&#xff0c;本期Jesse就来和大家聊聊TSDB与区块链。本文参考了Nicolas Hourcard的文章“You Don’t Need a Blockchain, You Need a Ti…

FlashDB嵌入式数据库之TSDB数据存储解析

一、驱动层&#xff1a;SFUD&#xff08;Serial Flash Universal Driver&#xff09; 是一款开源的串行 SPI Flash 通用驱动库 二、中间层&#xff1a;FAL&#xff08;FLASH ABSTRACTION LAYER)&#xff09;FLASH 抽象层 三、应用层&#xff1a;FlashDB&#xff08;FlashDB 是一…

时间序列数据库 (TSDB)

参考文档&#xff1a;时间序列数据库 TSDB_时间序列数据库 TSDB-阿里云帮助中心 什么是时序数据库 时序数据是随时间不断产生的一系列数据&#xff0c;简单来说&#xff0c;就是带时间戳的数据。数据可能来自服务器和应用程序的指标、物联网传感器的读数、网站或应用程序上的…

TSDB在高速公路大数据平台的应用

好久没有跟大家聊TSDB的应用场景了&#xff0c;Jesse也在国庆期间进行了补课&#xff0c;今天就跟大家聊聊TSDB在高速公路大数据平台的应用。本文借鉴了郝建明、袁逸涛发表在《上海船舶运输科学研究生学报》的《基于时序数据库的高速公路数据集成平台》一文&#xff0c;感谢二位…

时序数据库(TSDB)

时序数据库&#xff08;TSDB&#xff09;是一种特定类型的数据库&#xff0c;主要用来存储时序数据。随着5G技术的不断成熟&#xff0c;物联网技术将会使得万物互联。物联网时代之前只有手机、电脑可以联网&#xff0c;以后所有设备都会联网&#xff0c;这些设备每时每刻都会吐…

TSDB数据库

目录 为什么需要时序数据库&#xff1a; 时间序列数据库的特点&#xff1a; 常见的时间序列数据库&#xff1a; 时间序列数据库存储&#xff1a; 时间序列数据库问题&#xff1a; 参考资料&#xff1a; 内容是在我球的docs上直接复制过来的&#xff0c;懒得写两份&#x…

关于时许数据库的相关名词解释

1 时序数据库TSDB 英文全称为 Time Series Database&#xff0c;提供高效存取时序数据和统计分析功能的数据管理系统。 2 时序数据&#xff08;Time Series Data&#xff09; 基于稳定频率持续产生的一系列指标监测数据。例如&#xff0c;监测某城市的空气质量时&#xff0c…

物联网平台搭建的全过程介绍(六)——物联网TSDB之基本知识及读写代码介绍

目录 一、TSDB基本知识 二、物联网平台数据流通架构 三、TSDB数据结构 1、TSDB数据包的组成 2、TSDB的另外两个相关概念 四、阿里云物联网平台实例内TSDB功能介绍 1、数据写入 &#xff08;1&#xff09;需要添加的依赖 &#xff08;2&#xff09;写入数据代码 2、数据…

ES6—简介

目录 一、概述 二、扩展&#xff1a;Babel转码器 三、拓展&#xff1a;编译打包 一、概述 概念 ES6全称ECMAScript 6.0&#xff0c;是Javascript语言的下一代标准&#xff0c;2015年6月正式发布。 注意&#xff0c;ES6既是一个历史名词&#xff0c;也是一个泛指&#xff0c;…

深入浅出ES6(一):ES6是什么

深入浅出ES6&#xff08;一&#xff09;&#xff1a;ES6是什么 作者 Jason Orendorff &#xff0c;译者 刘振涛 发布于 2015年6月5日 | http://www.infoq.com/cn/articles/es6-in-depth-an-introduction 我的阅读清单 编者按&#xff1a;ECMAScript 6离我们越来越近了&#…

[ 前端开发 ] 为什么要学习ES6?

ECMAScript 6 概念 ECMAScript 6 简称 ES6 为什么要学习ES6? ES6 是 JavaScript 的下一个版本标准&#xff0c;诞生于2015年6月份。ES6 的主要目的是为了解决 ES5 的先天不足。ES6 的终极目标是为了使 JavaScript 语言可以用来编写复杂的大型应用程序&#xff0c;成为企业…

前端基础之ES6

ES6 ES6简介 ES6实际上是一个泛指&#xff0c;泛指ES2015及后续版本 为什么使用ES6&#xff1f; 每一次标准的诞生都意味着语言的完善&#xff0c;功能的加强。JavaScript语言本身也有一些令人不满意的地方。 变量提升特性增加了程序运行时的不可预测性语法过于松散&#x…

第一节:ES是什么?ES6是什么?

系列文章目录 第一节&#xff1a;ES是什么&#xff1f;ES6是什么&#xff1f; 文章目录 系列文章目录前言一、ES是什么&#xff1f;二、ES6是什么&#xff1f; 前言 学习一下ES&#xff0c;都是自己学习的总结和理解&#xff0c;大家有什么问题都可以提出&#xff0c;一起讨论…

1.什么是ES6,为什么使用它

1.什么是ES6&#xff1f; ECMAScript 6&#xff08;以下简称ES6&#xff09;是JavaScript语言的下一代标准&#xff0c;已经在2015年6月正式发布了。Mozilla公司将在这个标准的基础上&#xff0c;推出JavaScript 2.0。ES6主要是为了解决ES5的先天不足&#xff0c;比如JavaScri…

ES6是什么

ES6是什么 ECMAScript 6.0&#xff08;以下简称 ES6&#xff09;是 JavaScript 语言的下一代标准&#xff0c;已经在 2015 年 6 月正式发布了。 它的目标&#xff0c;是使得 JavaScript 语言可以用来编写复杂的大型应用程序&#xff0c;成为企业级开发语言。 现在大部分的编…

ES6是什么?通俗理解

1.了解一门语言&#xff0c;首先要搞明白它到底是什么&#xff1f; ECMA (Eurupean Compuler Manuluclurers Assuxiation)中文名为欧洲计算机制造商协会&#xff0c;这个组织的日常是评估、开发和认可电信和计算机标准。19919 年后该组织改名为ECMA国际。 ES6是门脚本语言&…

list集合转换成string字符串

集合转换成字符串 闲来无事&#xff0c;总结了几种list转换成string的方法 第一种 <jdk8新特性&#xff0c;string集合、integer集合均可随意转换成string> 个人觉得这个方法应该属于jdk8的新特性 ArrayList<String> arrayList new ArrayList<String>(){{…

python set转为list_python 怎么把set转成list

今天小就为大家分享一篇python-list,set间的转换实例&#xff0c;具有很好的参考价值&#xff0c;推荐手册&#xff1a;Python 基础入门教程 其实python中&#xff0c;set转list的非常的简单&#xff0c;直接将set的值放入list()的括号中即可&#xff0c;相反&#xff0c;list转…

Java list转set;JDK8 下list 集合转Set 集合

List 集合转Set 集合 1. List 集合和Set 集合的区别 在说如何List集合转Set 集合之前我们先回顾一下 List 集合和Set 集合的区别, 细致上说List 集合和Set 集合的区别还是有蛮多的有兴趣的同学可以去看一下源码&#xff0c;粗糙地讲List 集合和Set 集合的区别主要有那么几点 …

Java中的List与Set转换

一、List列表与Set列表的区别 List列表是有序、可以重复、线程不安全的列表,Set是无序、不能重复、线程不安全的列表。但List和Set可以通过方法来转换为线程安全的&#xff0c;加互斥锁。 Set<Long> setnew HashSet<>();// 转换为线程安全的集合Collections.sy…