时序数据库

简介

假设你写了个 脚本去去服务器cpu占用,内存开销和带宽

这种数据和时间有相关信的数据就是时序数据,专门优化来村这类数据的数据库就是时序数据库

比如监控,证券分析,物联网数据采集

流行的时序数据库

  1. influxDB
  2. timescaleDB(底层用的是pg)
  3. QuestDB

pgsql数据库的brin索引

b+树索引占用空间巨大,brin索引虽然查询速度没有b+树快但是他的索引大小要小很多

从PostgreSQL 9.5开始,实现了一个称为块范围索引(BRIN)的新索引。BRIN索引是一组物理上相邻的块(页面),并保存每组的值的范围(最小值和最大值)。当在数据仓库系统执行聚合分析查询巨大表时,此方法非常有效。这样可以缩小搜索时的扫描范围。(比如b+树索引占用1g的情况下,brin索引可能才占用80kb)

Brin的想法就是避免扫描绝对不合适的行,这是一个很天才的想法。根据Wiki的描述,这项技术其他厂商也有类似的功能,如Oracle Exadata的存储索引,Netezza的Zone Maps,还有infobright的data packs、MonetDB和Apache Hive with ORC/Parquet。

下面是具体的结构,左边的table是有很多个page页面组成的。而第一个block范围是1-128个page。我们的大哦对日期的最小值是1992-01-02,而最大值是1992-01-28。而第二个范围Range 2的最小值和最大值是1992-01-27和1992-02-08。而第三个范围 Range 3的最小值和最大值是1992-02-08和1992-02-16。表上总共这些page页面对应右边只需要有三行信息,这三行存储在Brin索引当中。因此Brin索引要比传统的B-Tree索引小很多。

brin优点

  • 顺序扫描会很快,它是索引顺序扫描的一种改进,如果键值的顺序和顺序存储中块的组织顺序相同,则针对大表的统计性能会大幅提升
  • 创建索引非常快
  • 索引占用的空间很小

influxdb

简介

influxDB是一个用GO语言编写的时序数据库与传统关系型数据库相比它对时序数据场景有专门的优化,当前用它完成指标的实时检测

时序数据库通常被用在监控的场景,比如运维IOT(物联网)领域。这类数据库目的在存储实时数据并实时处理他们

比如我们可以写一个程序将服务器上的CPU每隔10秒中像数据库写入一条数据。接着,我们写一个查询语句,查询过去30秒的cpu平均使用情况。数据积累起来是十分惊人的。数学型数据库底层基本上都是LSM(日志结构合并树)的数据结构

写入性能

关系型数据库也是支持时间戳,也能够基于时间戳进行查询。但是我们的使用场景出发,需要考虑数据库的写入性能。通常,关系型数据库会采用B+树数据结构,数据在写入时,有可能会触发页裂变,从而产生对磁盘的随机读写,降低写入速度。

lsm树

LSM树由两个或以上的存储结构组成,比如在论文中为了方便说明使用了最简单的两个存储结构。一个存储结构常驻内存中,称为C0 tree,具体可以是任何方便健值查找的数据结构,比如红黑树、map之类,甚至可以是跳表。另外一个存储结构常驻在硬盘中,称为C1 tree,具体结构类似B树。C1所有节点都是100%满的,节点的大小为磁盘块大小。

插入步骤

大体思路是:插入一条新纪录时,首先在日志文件中插入操作日志,以便后面恢复使用,日志是以append形式插入,所以速度非常快;将新记录的索引插入到C0中,这里在内存中完成,不涉及磁盘IO操作。当C0大小达到某一个阈值或每隔一段时间将C0中记录滚动合并到磁盘C1中,对于多个存储结构的情况,C1体谅越大就向C2合并以此类推,一直往上合并Ck。

合并过程中会使用两个块:emptying block和filling block。

从C1中读取未合并叶子节点,放置内存中的emptying block中。从小到大找C0中的节点,与emptying block进行合并排序,合并结果保存到filling block中,并将C0对应的节点删除。不断执行第2步操作,合并排序结果不断填入filling block中,当其满了则将其追加到磁盘的新位置上,注意是追加而不是改变原来的节点。合并期间如故宫emptying block使用完了则再从C1中读取未合并的叶子节点。C0和C1所有叶子节点都按以上合并完成后即完成一次合并。

但实际项目中其实有很多优化策略,而且有很多针对LSM树优化的paper。比如使用布隆过滤器快速判断key是否存在,还有做一些额外的索引以帮助更快找到记录等等。

特性

时序数据库通常有这样的操作,将最近需要用到的数据放到内存里面

大部分时序数据库不允许修改历史数据,不支持事物,不能删除数据,更新大多数时候也不行

根据之前的介绍,我们首先可以知道时序数据库一般用在监控的场景,大体上,数据应用可以分为4步走

  1. 数据采集
  2. 存储
  3. 查询
  4. 报警

这样一看,只需给一个数据库其实只能完成数据的存储和查询功能,上游的采集和下游的报警都需要自己来实现。因此InfluxDB1.X退出了TICK生态来退出start全套解决方案。

TICK四个字母分别对应4个组件

  1. telegraf:数据采集组件,收集&发送数据到InfluxDB
  2. InfluxDB:存储数据发送数据到Chronograf
  3. Chronograf:总的用户界面,起到总的管理功能
  4. Kapacitor:后台报警

3与4在2.x之后再influxdb中集成了,易用性2.x>1.x

1.7,1.8 使用的是inflexQL

influxDB2.x用的是Flux语言,influx集群版本是收费的,单台节点是免费的,国内也有开元的influxDB

数据量大:拿监控数据来举例,如果我们采集的监控数据的时间间隔是1s,那一个监控项每天会产生86400个数据点,若有10000个监控项,则一天就会产生864000000个数据点。在物联网场景下,这个数字会更大。整个数据的规模,是TB甚至是PB级的。
冷热分明:时序数据有非常典型的冷热特征,越是历史的数据,被查询和分析的概率越低。
具有时效性:时序数据具有时效性,数据通常会有一个保存周期,超过这个保存周期的数据可以认为是失效的,可以被回收。一方面是因为越是历史的数据,可利用的价值越低;另一方面是为了节省存储成本,低价值的数据可以被清理。

influxDB启动后,会向外提供一套HTTPAPI。外部程序也仅能通过HTTP API与InfluxDB。我们后面要降到的influx命令行。

所以各种客户端同InfluxDB交互时,都离不开APItoken。因为HTTP是一种支持官方且简单的协议,方便用户二次开发

Last modification:November 17, 2023
如果觉得我的文章对你有用,请随意赞赏