TimescaleDB时序数据库初识
注:本文翻译自https://legacy-docs.timescale.com/v1.7/introduction
TimescaleDB是一个开源时间序列数据库,针对快速摄取和复杂查询进行了优化。它说的是“完整的SQL”,因此像传统的关系数据库一样易于使用,并且以以前为NoSQL数据库保留的方式进行扩展。
与这两种选择(关系型与NoSQL)所需要的权衡相比,TimescaleDB为时间序列数据提供了两种方法的最佳选择:
易于使用
- 完整的SQL接口,支持PostgreSQL本地支持的所有SQL(包括二级索引,非基于时间的聚合,子查询,join,窗口函数)。
- 连接到任何使用PostgreSQL的客户端或工具,无需更改。
- 面向时间的特性、API函数和优化。
- 对数据保留策略的强大支持。
可伸缩性
- 透明的时间/空间分区,支持向上扩展(单节点)和向外扩展(即将推出)。
- 高数据写速率(包括批处理提交、内存索引、事务支持、数据回填支持)。
- 在单个节点上适当大小的块(二维数据分区),以确保即使在大数据大小时也能快速摄取。
- 跨块和服务器的并行操作。
可靠性
- 从PostgreSQL设计而来,打包为extension。
- 经过20多年PostgreSQL研究的可靠基础(包括流复制,备份)。
- 灵活的管理选项(与现有PostgreSQL生态系统和工具兼容)。
什么是时间序列数据?
时间序列数据是总体上表示系统、流程或行为如何随时间变化的数据。
以时间为中心:数据记录总是有一个时间戳。
仅追加:数据几乎完全是仅追加的(insert)。
最近的:新数据通常是关于最近的时间间隔,我们很少更新或回填关于旧时间间隔的缺失数据。
然而,数据的频率或规律性并不那么重要;它可以每毫秒或每小时收集一次。它也可以定期或不定期收集(例如,当某些事件发生时,而不是在预定义的时间)。
与其他数据(如标准关系“业务”数据)相比,时间序列数据(以及支持它们的数据库)之间的一个关键区别是,对数据的更改是插入,而不是覆盖。
时序数据应用场景
监控计算机系统:虚拟机、服务器、容器指标(CPU、空闲内存、网络/磁盘IOPs)、服务和应用程序指标(请求速率、请求延迟)。
金融交易系统:经典证券、新型加密货币、支付、交易事件。
物联网:来自工业机器和设备、可穿戴设备、车辆、物理容器、托盘、智能家居消费设备等传感器的数据。
事件应用:用户/客户交互数据,如点击流、页面浏览量、登录、注册等。
商业智能:跟踪关键指标和业务的整体健康状况。
环境监测:温度、湿度、压力、pH值、花粉计数、空气流量、一氧化碳(CO)、二氧化氮(NO2)、颗粒物(PM10)。
数据模型
作为一个支持完整SQL的关系数据库,TimescaleDB支持灵活的数据模型,可以针对不同的用例进行优化。这使得TimescaleDB与大多数其他时间序列数据库有些不同,后者通常使用“窄表”模型。
具体来说,TimescaleDB既支持宽表模型,也支持窄表模型。在这里,我们将使用一个物联网(IoT)示例讨论这两种模型的不同性能权衡和影响。
想象一下,一个由1000个物联网设备组成的分布式组,旨在以不同的间隔收集环境数据。这些数据可以包括:
Identifiers: device_id, timestamp
Metadata: location_id, dev_type, firmware_version, customer_id
Device metrics: cpu_1m_avg, free_mem, used_mem, net_rssi, net_loss, battery
Sensor metrics: temperature, humidity, pressure, CO, NO2, PM10
例如,您的传入数据可能看起来像这样:
timestamp | device_id | cpu_1m_avg | free_mem | temperature | location_id | dev_type |
---|---|---|---|---|---|---|
2017-01-01 01:02:00 | abc123 | 80 | 500MB | 72 | 335 | field |
2017-01-01 01:02:23 | def456 | 90 | 400MB | 64 | 335 | roof |
2017-01-01 01:02:30 | ghi789 | 120 | 0MB | 56 | 77 | roof |
2017-01-01 01:03:12 | abc123 | 80 | 500MB | 72 | 335 | field |
2017-01-01 01:03:35 | def456 | 95 | 350MB | 64 | 335 | roof |
2017-01-01 01:03:42 | ghi789 | 100 | 100MB | 56 | 77 | roof |
现在,让我们看看对这些数据建模的各种方法。
窄表模型
大多数时间序列数据库将以下列方式表示这些数据:
将每个指标表示为一个单独的实体(例如,将cpu_1m_avg和free_mem表示为两个不同的东西)
为该指标存储一系列“时间”、“值”对
将元数据值表示为与该度量/标记集组合相关联的“标记集”
在此模型中,每个度量/标记集组合被认为是包含时间/值对序列的单个“时间序列”。
使用我们上面的例子,这种方法会产生9个不同的“时间序列”,每一个都由一组唯一的标签定义。
1. {name: cpu_1m_avg, device_id: abc123, location_id: 335, dev_type: field}
2. {name: cpu_1m_avg, device_id: def456, location_id: 335, dev_type: roof}
3. {name: cpu_1m_avg, device_id: ghi789, location_id: 77, dev_type: roof}
4. {name: free_mem, device_id: abc123, location_id: 335, dev_type: field}
5. {name: free_mem, device_id: def456, location_id: 335, dev_type: roof}
6. {name: free_mem, device_id: ghi789, location_id: 77, dev_type: roof}
7. {name: temperature, device_id: abc123, location_id: 335, dev_type: field}
8. {name: temperature, device_id: def456, location_id: 335, dev_type: roof}
9. {name: temperature, device_id: ghi789, location_id: 77, dev_type: roof}
这样的时间序列的数量以每个标签的基数的交叉积为尺度,即(# names) × (# device id) × (# location id) ×(设备类型)。一些时间序列数据库随着基数的增加而挣扎,最终限制了可以存储在单个数据库中的设备类型和设备的数量。
TimescaleDB支持窄模型,并且不像其他时间序列数据库那样受到基数限制。如果您独立地收集每个指标,则狭窄的模型是有意义的。它允许您在添加新标记时添加新指标,而不需要正式的模式更改。
但是,如果使用相同的时间戳收集许多指标,那么窄模型的性能就不那么好了,因为它需要为每个指标编写时间戳。这最终导致更高的存储和摄取需求。此外,关联不同指标的查询也更复杂,因为要关联的每个额外指标都需要另一个JOIN。如果您通常同时查询多个指标,那么将它们存储在一个宽表格式中既快又容易,我们将在下一节中介绍这一点。
宽表模型
TimescaleDB很容易支持宽表模型。在这个模型中,跨多个指标的查询更容易,因为它们不需要join。此外,摄取速度更快,因为只需要为多个指标编写一个时间戳。
一个典型的宽表模型将匹配一个典型的数据流,其中在给定的时间戳中收集多个指标:
timestamp | device_id | cpu_1m_avg | free_mem | temperature | location_id | dev_type |
---|---|---|---|---|---|---|
2017-01-01 01:02:00 | abc123 | 80 | 500MB | 72 | 335 | field |
2017-01-01 01:02:23 | def456 | 90 | 400MB | 64 | 335 | roof |
2017-01-01 01:02:30 | ghi789 | 120 | 0MB | 56 | 77 | roof |
2017-01-01 01:03:12 | abc123 | 80 | 500MB | 72 | 335 | field |
2017-01-01 01:03:35 | def456 | 95 | 350MB | 64 | 335 | roof |
2017-01-01 01:03:42 | ghi789 | 100 | 100MB | 56 | 77 | roof |
在这里,每一行都是一个新的读数,具有给定时间的一组测量值和元数据。这使我们能够保留数据中的关系,并提出比以前更有趣或探索性的问题。
当然,这不是一种新格式:这是在关系数据库中常见的格式。
关系数据的JOIN操作
TimescaleDB的数据模型与关系数据库还有另一个相似之处:它支持join。具体来说,可以在辅助表中存储额外的元数据,然后在查询时使用该数据。
在我们的示例中,可以有一个单独的位置表,将location_id映射到该位置的其他元数据。例如:
location_id | name | latitude | longitude | zip_code | region |
---|---|---|---|---|---|
42 | Grand Central Terminal | 40.7527° N | 73.9772° W | 10017 | NYC |
77 | Lobby 7 | 42.3593° N | 71.0935° W | 02139 | Massachusetts |
然后在查询时,通过连接我们的两个表,可以问这样的问题:zip_code 10017中设备的平均free_mem是多少?
如果没有连接,就需要对数据进行非规范化,并将所有元数据存储在每个测量行中。这会导致数据膨胀,并使数据管理变得更加困难。
通过连接,可以独立存储元数据,并且更容易更新映射。
例如,如果我们想要更新location_id 77的“区域”(例如,从“Massachusetts”到“Boston”),我们可以进行此更改,而无需返回并覆盖历史数据。
架构及概念
TimescaleDB是作为PostgreSQL上的扩展实现的,这意味着它在整个PostgreSQL实例中运行。扩展模型允许数据库利用PostgreSQL的许多属性,如可靠性、安全性以及与广泛的第三方工具的连接性。同时,TimescaleDB通过在PostgreSQL的查询规划器、数据模型和执行引擎中添加钩子,充分利用了扩展的高度定制性。
从用户的角度来看,TimescaleDB公开了看似单一的表(称为hypertables),它实际上是保存数据的许多单独表(称为chunks)的抽象或虚拟视图。
chunks是通过将hypertables的数据划分为一个或多个维度来创建的:所有hypertables都按时间间隔进行分区,还可以按设备ID、位置、用户ID等键进行分区。我们有时把这称为“时间和空间”的划分。
Hypertables
与数据交互的主要点是一个超表,它是跨所有空间和时间间隔的单个连续表的抽象,因此可以通过标准SQL查询它。
实际上,与TimescaleDB的所有用户交互都是使用超级表。创建表和索引、修改表、插入数据、选择数据等都可以(也应该)在超级表上执行。[跳转到基本的SQL操作]
超级表由具有列名和类型的标准模式定义,其中至少有一个列指定时间值,一个(可选)列指定额外的分区键。
单个TimescaleDB部署可以存储多个超级表,每个超级表具有不同的模式。
在TimescaleDB中创建超级表需要两个简单的SQL命令:
CREATE TABLE(使用标准SQL语法),然后是SELECT create_hypertable()。
在超级表上自动创建关于时间和分区键的索引,但是也可以创建额外的索引(TimescaleDB支持所有的PostgreSQL索引类型)。
Chunks
在内部,TimescaleDB自动将每个超表分割成块,每个块对应于特定的时间间隔和分区键空间的一个区域(使用散列)。这些分区是不相交的(不重叠的),这有助于查询规划器最小化它在解析查询时必须接触的块集。
每个块都是使用标准数据库表实现的。(在PostgreSQL内部,块实际上是“父”超表的“子表”。)
块的大小合适,确保表索引的所有b树都可以在插入期间驻留在内存中。这避免了在修改这些树中的任意位置时产生震荡。
此外,通过避免过大的块,我们可以在根据自动保留策略删除已删除的数据时避免昂贵的“真空”操作。运行时可以通过简单地删除块(内部表)来执行此类操作,而不是删除单个行。
本地压缩
压缩由TimescaleDB的内置作业调度器框架提供支持。我们利用它来跨超表异步地将单个块从未压缩的基于行的形式转换为压缩的列形式:一旦块足够老,该块将以事务方式从行形式转换为列形式。
使用本机压缩,即使TimescaleDB中的单个超表将以行和列两种形式存储数据,用户也不需要担心这一点:在查询数据时,他们将继续看到标准的基于行的模式。这类似于在解压的列数据上构建视图。
TimescaleDB通过(1)透明地将以标准行格式存储的数据附加到从列格式解压缩的数据中,以及(2)在查询时透明地从选定的行解压缩各个列来实现此功能。
在查询期间,未压缩的块将被正常处理,而来自压缩块的数据将首先被解压缩并在查询时转换为标准行格式,然后再添加或合并到其他数据中。这种方法与您期望从TimescaleDB获得的一切兼容,例如关系连接和分析查询,以及避免处理块的主动约束排除。
单节点vs集群
TimescaleDB在单节点部署和集群部署(开发中)上执行广泛的分区。虽然分区传统上只用于跨多台机器的扩展,但它也允许我们在单台机器上扩展到高写速率(和改进的并行查询)。
TimescaleDB的当前开源版本仅支持单节点部署。值得注意的是,TimescaleDB的单节点版本已经在普通机器上对超过100亿行超级表进行了基准测试,而插入性能没有任何损失。
单节点分区的优势
在单台机器上扩展数据库性能的一个常见问题是内存和磁盘之间的成本/性能权衡。最终,我们的整个数据集将无法装入内存,我们需要将数据和索引写入磁盘。
一旦数据足够大,我们无法在内存中容纳索引的所有页面(例如,b树),那么更新树的随机部分可能涉及从磁盘交换数据。像PostgreSQL这样的数据库为每个表索引保留一个b树(或其他数据结构),以便有效地找到该索引中的值。因此,当您索引更多的列时,问题会变得更加复杂。
但是,由于TimescaleDB创建的每个块本身都存储为一个单独的数据库表,因此它的所有索引只能在这些小得多的表上构建,而不是在一个表示整个数据集的表上构建。因此,如果我们适当地调整这些块的大小,我们可以将最新的表(及其b树)完全放入内存中,并避免这种交换到磁盘的问题,同时保持对多个索引的支持。
相关文章:

TimescaleDB时序数据库初识
注:本文翻译自https://legacy-docs.timescale.com/v1.7/introduction TimescaleDB是一个开源时间序列数据库,针对快速摄取和复杂查询进行了优化。它说的是“完整的SQL”,因此像传统的关系数据库一样易于使用,并且以以前为NoSQL数…...

Numpy-聚合函数
NumPy 提供了很多统计函数,用于从数组中查找最小元素,最大元素,百分位标准差和方差等。 函数名说明np.sum()求和np.prod()所有元素相乘np.mean()平均值np.std()标准差np.var()方差np.median()中位数np.power()幂运算np.sqrt()开方np.min()最小…...

企业博客资讯如何高效运营起来?
运营一个高效的企业博客资讯需要综合考虑多个因素,包括内容策划、发布频率、优化推广、互动反馈等。下面将从这些方面介绍如何高效运营企业博客资讯。 如何高效运营企业博客资讯 内容策划 首先,需要制定一个明确的内容策略。确定博客的定位和目标受众…...

跟我学c++中级篇——模板的继承
一、继承 面向对象编程有三个特点:封装、继承和多态。其中继承在其中起着承上启下的作用。一般来说,继承现在和组合的应用比较难区分,出于各种场景和目的,往往各有千秋。但目前主流的观点,一般是如果没有特殊情况&…...

需求分析案例:消息配置中心
本文介绍了一个很常见的消息推送需求,在系统需要短信、微信、邮件之类的消息推送时,边界如何划分和如何设计技术方案。 1、需求 一个系统,一般会区分多个业务模块,并拆分成不同的业务系统,例如一个商城的架构如下&am…...

自动化测试——环境
一、搭建环境 1、安装Slenium pip install selenium 2、安装浏览器驱动-》查询浏览器版本-》下载对应版本驱动-》在path路径中配置(浏览器更新需要重新下载) pip install webdriver -helper(自动化)python3.9以上 pip install 安…...

短视频矩阵营销系统技术开发者开发笔记分享
一、开发短视频seo抖音矩阵系统需要遵循以下步骤: 1. 确定系统需求:根据客户的需求,确定系统的功能和特点,例如用户注册登录、视频上传、视频浏览、评论点赞等。 2. 设计系统架构:根据系统需求,设计系统的…...

vue2和vue3引用ueditor的区别
官方文档入口 UEditor Docs vue2使用方式 UE.vue组件 <template><div><script id"editor" type"text/plain"></script><Upload v-if"isupload" :config"{total:9}" :isupload"isupload" ret…...

【每日运维】RockyLinux8非容器化安装Mysql、Redis、RabitMQ单机环境
系统版本:RockyLinux 8.6 安装方式:非容器化单机部署 安装版本:mysql 8.0.32 redis 6.2.11 rabbitmq 3.11.11 elasticsearch 6.7.1 前置条件:时间同步、关闭selinux、主机名、主机解析host 环境说明:PC电脑VMware Work…...

第一次后端复习整理(JVM、Redis、反射)
1. JVM 文章仅为自身笔记 详情查看一篇文章掌握整个JVM,JVM超详细解析!!! 1.1 什么是JVM jvm是Java虚拟机 1.2 Java文件的编译过程 程序员编写代码形成.java文件经过javac编译成.class文件再通过JVM的类加载器进入运行时数据…...

python的web学习(一)-初识django
文章目录 软件创建项目默认项目文件说明App的概念(应用)apps.py编写URL和视图函数对应关系【urls.py】编写视图函数【views.py】启动服务 软件 python下载 django下载 创建项目 django-admin startproject 文件名默认项目文件说明 项目名 manage.py(项目管理,启…...

JavaWeb+jsp+Tomcat的叮当书城项目
点击以下链接获取源码: https://download.csdn.net/download/qq_64505944/88123111?spm1001.2014.3001.5503 技术:ssm jsp JDK1.8 MySQL5.7 Tomcat8.3 源码数据库课程设计 功能:管理员与普通用户和超级管理员三个角色,管理员可…...

【嵌入式Linux系统开发】——系统移植概述
目录 🍉🍉一、什么是嵌入式系统 🍉🍉二、嵌入式系统操作 🍉🍉三、嵌入式Linux的特点 🍉🍉四、嵌入式系统的组成 1、硬件和软件 2、硬件层 3、中间层 4、软件层 5、 功能层与执…...

升讯威在线客服系统是如何实现对 IE8 完全完美支持的(怎样从 WebSocket 降级到 Http)【干货】
简介 升讯威在线客服与营销系统是基于 .net core / WPF 开发的一款在线客服软件,宗旨是: 开放、开源、共享。努力打造 .net 社区的一款优秀开源产品。 完整私有化包下载地址 💾 https://kf.shengxunwei.com/freesite.zip 当前版本信息 发布…...

用VMware给运行在VMware上的CentOS7生成一个以SSH方式连接VMware上的CentOS7的运行在Windows上的命令行窗口
2023年7月27日,周四早上 目录 一个发现生成方法如果上面的方法连接失败,就采取这个方法 一个发现 今天早上无意间发现VMware可以生成一个以SSH方式连接着CentOS7的Windows命令行窗口, 这样做可以带来一定的便利性 : 方便复制、…...

C语言基础-3
1、函数 函数是C语言代码的基本组成部分,它是一个小的模块,整个程序由很多个功能独立的模块(函数)组成。这就是程序设计的基本分化方法。 main:C语言中所谓的主函数,主函数就是一种特别的函数。特别之处在于…...

Python 编程规范进阶(1) | 命名规范
养成良好的开发、编程习惯 跟着google开源项目走 https://github.com/google/styleguide 近期Target: 命名规范; Pythonic 积累 按照需求写需要的API; 写前先动脑子,比如画流程图,测试接口; Google 推荐的P…...

算法----二叉搜索树中第K小的元素
题目 二叉搜索树中第K小的元素 给定一个二叉搜索树的根节点 root ,和一个整数 k ,请你设计一个算法查找其中第 k 个最小元素(从 1 开始计数)。 示例 1: 输入:root [3,1,4,null,2], k 1 输出ÿ…...

阿里Java开发手册~安全规约
1. 【强制】隶属于用户个人的页面或者功能必须进行权限控制校验。 说明: 防止没有做水平权限校验就可随意访问、修改、删除别人的数据,比如查看他人的私信 内容、修改他人的订单。 2. 【强制】用户敏感数据禁止直接展示,必须对展示数据进…...

消息中间件RabbitMQ——学习笔记
❤ 作者主页:欢迎来到我的技术博客😎 ❀ 个人介绍:大家好,本人热衷于Java后端开发,欢迎来交流学习哦!( ̄▽ ̄)~* 🍊 如果文章对您有帮助,记得关注、点赞、收藏、…...

爬虫005_python类型转换_其他类型转换为整型_转换为Float类型_转换为字符串_转换为布尔值---python工作笔记023
首先来看,字符串转换成int 很简单 float转换成int 会把小数点后面的内容丢掉 boolean转换为int true是1 false 是0 然后字符串转换为int,要注意 不能有特殊字符比如1.23 中有点 就报错 上面字符串12ab,有ab也报错 看上面...

SpringBoot复习:(5)使用PropertySource注解
一、自定义的一个配置文件 age33 nameliu二、实体类 package com.example.demo.domain;public class Student {private String name;private int age;public String getName() {return name;}public void setName(String name) {this.name name;}public int getAge() {retur…...

webrtc 支持H265(三) 总结
文章目录 web端的解码及渲染的实现应用场景单向视频流的场景datachannel通道的稳定性解码性能 双向视频流的场景有音频流的场景 web端的解码及渲染的实现 在前面的文章中介绍了ZLMediaKit的修改方法,在web端的播放器可以参照这个实现,基于wasm H265播放…...

Windows使用Notepad++编辑Linux服务器的文件
🚀 Windows使用Notepad编辑Linux服务器的文件 🚀 🌲 算法刷题专栏 | 面试必备算法 | 面试高频算法 🍀 🌲 越难的东西,越要努力坚持,因为它具有很高的价值,算法就是这样✨ 🌲 作者简介…...

升级你的数据采集引擎 使用多线程与代理池提升HTTP代理爬虫性能
在信息爆炸的时代,海量数据的采集和分析成为了企业发展和决策的关键。本文将分享如何通过多线程和代理池的应用,助您升级数据采集引擎,提高数据获取效率和稳定性。 HTTP代理爬虫作为数据采集的重要工具,其性能直接影响着数据采集…...

flask实现一个登录界面
flask实现一个登录界面 基础的Flask项目结构 forms.py:定义登录表单和表单字段的文件。templates/login.html:用于渲染登录表单的 HTML 模板文件。routes.py:定义应用的路由和视图函数的文件。__init__.py:创建并初始化 Flask 应…...

redis的四种模式优缺点
redis简介 Redis是一个完全开源的内存数据结构存储工具,它支持多种数据结构,以及多种功能。Redis还提供了持久化功能,可以将数据存储到磁盘上,以便在重启后恢复数据。由于其高性能、可靠性和灵活性,Redis被广泛应用于…...

maven本地仓库地址修改+maven国内镜像设置+maven运行所需pos.xml文件配置基本写法
1,maven本地仓库地址修改 maven在使用过程中,本地项目仓库其空间占用会越来越大,但是其默认仓库位置往往是以C盘为主,C盘作为系统盘常常会遇到所在盘空间占满的情况,所以我们将其改至其他硬盘空间位置为适合做法&#…...

Jenkins集成SonarQube保姆级教程
Jenkins是自动化部署平台,一个粗眉大眼的糙汉子! SonarQube是代码扫描平台,一个眉目清秀的小女子! 有一天,上天交给我一个任务,去撮合撮合他们! 我抬头看了看天, 不,…...

Git的安装以及本地仓库的创建和配置
文章目录 1.Git简介2.安装Git2.1在Centos上安装git2.2 在ubuntu上安装git 3.创建本地仓库4.配置本地仓库 1.Git简介 Git是一个分布式版本控制系统,用于跟踪和管理文件的更改。它可以记录和存储代码的所有历史版本,并可以方便地进行分支管理、合并代码和协…...