1.概述
InfluxDB是一种流行的开源时序数据库,专门设计用于处理时间序列数据。时序数据是按时间顺序排列的数据,通常用于表示传感器数据、应用程序指标、日志和事件等。InfluxDB具有高效存储和查询的能力,采用自适应压缩算法和特定的存储引擎,可以高效地存储大量的时序数据,并通过类似SQL的查询语言(InfluxQL)提供丰富的查询功能。它支持高并发写入,适用于处理实时数据流,并可定义数据保留策略自动删除旧数据以控制数据库大小。此外,InfluxDB拥有插件生态系统,可扩展其功能,并具备高可用性和容错性,支持数据复制和故障转移。InfluxDB是influxdata 公司提供的一款专门处理高写入和查询负载的时序数据库,除了InfluxDB外其生态还包括下图中一些组件和工具。
- InfluxDB Cloud:InfluxDB Cloud是InfluxData提供的托管服务,它为用户提供了一种简便的方式来运行和管理InfluxDB。它具有高度可扩展性、高可用性和灵活的计费模型,适用于各种规模的应用和工作负载。
- InfluxDB Enterprise:InfluxDB Enterprise是InfluxData提供的企业级解决方案,用于在私有云环境中部署和管理InfluxDB。它提供了高度可扩展的集群架构、数据复制和故障转移、安全性和监控功能等,适用于对数据隐私和安全要求较高的企业场景。
- Telegraf:Telegraf是InfluxData开发的开源数据采集代理。它可以从各种来源收集数据,并将其写入InfluxDB。Telegraf支持众多输入插件(如系统指标、日志文件、数据库等)和输出插件(包括InfluxDB、Kafka、Elasticsearch等),可用于构建端到端的数据收集和处理流程。
- Kapacitor:Kapacitor是InfluxData开发的开源数据处理引擎。它可以接收实时数据流,执行复杂的数据处理和分析操作,并支持自定义的告警和通知机制。Kapacitor与InfluxDB紧密集成,可用于实时监测、自动化任务和异常检测等场景。
- Chronograf:Chronograf是InfluxData开发的开源数据可视化和监控工具。它提供了直观的用户界面,可用于查询和可视化InfluxDB中的数据,创建仪表盘和报表,并设置警报规则和通知。Chronograf还支持数据探索和控制台调试等功能。
- Flux:Flux是InfluxData推出的用于查询和处理数据的新的函数式查询语言。与传统的InfluxQL相比,Flux提供了更强大和灵活的数据操作能力,支持更复杂的查询和数据转换操作。Flux已成为InfluxDB 2.0及以上版本的默认查询语言。
InfluxDB生态系统还有丰富的第三方工具和插件,如Grafana(数据可视化)、Prometheus(监控和告警)、Python和Go等语言的客户端库等,可以帮助用户更好地集成和使用InfluxDB。
InfluxDB数据模型
Bucket:存储时间序列数据的命名位置,包含多个 Measurement;
Measurement:时序数据的逻辑分组,表示该条记录对应的含义。在一个特定的测量中,所有点都应具备相同的标签。包含多个 tags 和 fields;
Tags:表示该条记录的一系列属性信息。键值对的值不一样,但是不经常变化。tags用来存储每个点的元数据,默认是被索引的,例如:地点;
Fields:表示该条记录的内容信息,值随时间变化的键值对,不能被索引,例如温度、股价等;
Timestamp:数据关联的时间戳。在存储和查询时,所有数据都是基于时间顺序的。
- Point:单条数据记录是由 measurement,tag keys, tag values, field key, timestamp来定义的;
- Series:一组具有相同 measurement, tag keys, tag values的点;
Series = Measurement + Tags;
一个数据源采集的一个指标随着时间的流逝,而源源不断地吐出的数据,这样形成的一条数据线;
InfluxDB特点
我们之前说,时序数据库一般用于指标监控场景。这个场景的数据有一个非常明显的特点就是冷热差别明显。通常,指标监控只会使用近期一段时间的数据,比如我只查询某个设备最近 10 分钟的记录,10 分钟前的数据我就不再用了。那么这 10 分钟前的数据,对我们来说就是冷数据,应该被压缩放到磁盘里去来节省空间。而热数据因为经常要用,数据库就应该让它留在内存里,等待查询。而市面上的时序数据库大都有类似的设计。
时序数据是描述一个实体在不同时间所处的不同状态。
就像是我们打开任务管理器,查看 CPU 的使用情况。我发现 CPU 占用率太高了,于是杀死了一个进程,但 10秒前的数据不会因为我关闭进程再发生改变了。
这是时序数据的一大特点。与之相应,时序数据库基本上是插入操作较多,而且还没有什么更新需求。
- 内置HTTP接口,使用方便
- 数据可以打标记,查让查询可以很灵活
- 类SQL的查询语句
- 安装管理很简单,并且读写数据很高效
- 能够实时查询,数据在写入时被索引后就能够被立即查出
timestamp:time存着时间戳,这个时间戳以RFC3339
格式展示了与特定数据相关联的UTC日期和时间。
field set:每组field key和field value的集合,如butterflies = 3, honeybees = 28
field key/value:在InfluxDB中不能没有field,field没有索引。
tag set:不同的每组tag key和tag value的集合,如location = 1, scientist = langstroth
tag key/value:在InfluxDB中可以没有tag,tag是索引起来的。
measurement: 是一个容器,包含了列time,field和tag。概念上类似表。
retention policy:单个measurement可以有不同的retention policy。measurement默认会有一个autogen
的保留策略,autogen中的数据永不删除且备份数replication为1(只有一份数据,在集群中起作用)。
series:series是共同retention policy,measurement和tag set的集合。如下:
2.InfluxDB逻辑架构
InfluxDB的逻辑存储架构包括数据库、测量(Measurement)、标签(Tag)和字段(Field),这些组件共同构成了数据的组织和存储方式:
- 数据库(Database):数据库是InfluxDB中的顶层概念,用于逻辑上组织和隔离数据。每个数据库都可以独立存储不同类型的数据,例如不同应用程序、传感器或设备的数据。用户可以创建和管理多个数据库,根据需求进行数据的分组和分类。
- 测量(Measurement):测量是InfluxDB中的核心概念,代表一组相关的数据点。测量通常对应于一个实体、一个测量对象或一个应用程序指标。例如,一个传感器的测量可以是温度、湿度或压力等。测量可以包含多个标签和字段。
- 标签(Tag):标签是用于标识和过滤数据的键值对。标签通常用于描述测量数据的元数据,如传感器ID、地理位置、设备类型等。标签是字符串类型的键值对,可以根据需要动态添加或修改。
- 字段(Field):字段是实际存储数据值的键值对。字段可以包含不同类型的数据,如浮点数、整数、字符串或布尔类型。字段的值是实际要存储和查询的数据。
- 数据保留时间(Retention Duration):RP定义了数据在数据库中保留的时间范围。可以根据需求指定保留的时间,例如保留最近7天、30天或更长时间的数据。过期的数据将自动从数据库中删除,以保持数据库的大小和性能控制。
3.InfluxDB存储架构
InfluxDB的存储架构是基于Time-Structured Merge Tree(TSI)的设计,数据分片、TSI存储引擎、索引结构和压缩算法的结合,使得InfluxDB能够在保证数据可靠性的同时,提供快速的数据写入和查询性能。
- WAL(Write-Ahead Log):WAL是InfluxDB中的一种持久化机制,用于确保数据的持久性和一致性。在写入数据之前,InfluxDB首先将数据写入WAL,然后再将其写入到实际的数据文件中。WAL记录了所有写入操作的日志,以防止数据丢失或损坏。在系统崩溃或故障恢复时,WAL可用于恢复未写入到数据文件的数据。
- Shard(数据分片):Shard是InfluxDB中用于水平分割和存储数据的单位。数据分片是将数据按照时间范围进行分割和存储的方式,可以提高数据写入和查询的性能。数据节点可以配置为拥有多个数据分片,每个数据分片存储一段时间范围内的数据。
- Shard Group(分片组):Shard Group是一组相邻时间范围内的数据分片的集合。分片组可以根据一定的规则和策略来确定数据分片的范围和数量。分片组的目的是将相邻时间段内的数据分配到一组数据分片中,以提高查询性能和数据的局部性。
- Cache(缓存):InfluxDB中的缓存主要用于加速数据的查询性能。缓存可以存储最常用的数据和查询结果,以便在后续的查询中快速检索。InfluxDB使用多级缓存机制,包括操作系统的文件系统缓存、InfluxDB内部的查询结果缓存和查询引擎的缓存,以提高查询的响应速度。
- 存储引擎:InfluxDB使用Time-Structured Merge Tree(TSI)作为其存储引擎。TSI通过将数据分为多个时间段,并在每个时间段内创建索引和压缩数据来提供高效的存储和查询性能。数据被存储在磁盘上的文件中,而索引则被存储在内存中,以加快查询性能。
- 索引结构:InfluxDB使用B+树索引结构来支持快速的数据查询。B+树是一种常见的平衡树结构,能够快速定位数据,支持范围查询和范围聚合操作。索引按照时间序列组织,根据时间戳和标签值来进行索引。
- 压缩算法:InfluxDB使用自适应的压缩算法来减小数据在磁盘上的存储空间。压缩算法基于数据的类型和时间范围,对数据进行有损或无损的压缩。压缩后的数据被存储在磁盘上,以节省存储空间并提高读取性能。
- 数据复制和故障转移:InfluxDB支持数据的复制和故障转移,以提供高可用性和容错性。数据复制将数据的副本存储在不同的节点上,以保证数据的冗余和可靠性。当一个节点发生故障时,复制的数据可以自动切换到其他节点,以保持数据的可用性和连续性。
InfluxDB的存储结构树是时间结构合并树(Time-Structured Merge Tree,TSM),它是由日志结构化合并树(Log-Structured Merge Tree,LSM),根据实际需求变化而来的;
LSM树,包含3部分,Memtable、Immutable和SSTable,Memtable是内存中的数据结构,用于保存最近产生的数据,并按照Key有序地组织数据,内存并不是可靠存储,若断电就会丢失数据,因此通常会使用预写式日志(Write-ahead logging,WAL)的方式来保证数据的可靠性;
分片
ShardGroup,每个ShardGroup只存储指定时间段的数据,不同的ShardGroup对应的时间段不会重合;为什么这么划分?
1InfluxDB中数据过期删除的执行力度就是ShardGroup;
2可以有效根据时间维度选择目标分区,淘汰部分数据;
Shard,真正存储数据的地方并提供读写服务,ShardGroup是逻辑概念;
存储示例
下图为InfluxDB数据存储在磁盘上的组织形式,下图示例中创建了一个名为“nuclear”的数据库用来存储时序数据,数据存储RP命名为“5_year”,数据保留策略设置为5年。
4.InfluxDB优缺点
优点
- 高效的时序数据处理:InfluxDB专门为时序数据而设计,具有高效的写入和查询性能。它采用了优化的存储引擎和查询引擎,能够处理大规模的时序数据。
- 灵活的数据模型:InfluxDB的数据模型灵活,可以根据需求组织和存储数据。它支持标签和字段的概念,使得数据的描述和过滤更加方便和高效。
- 强大的查询语言:InfluxDB提供了InfluxQL和Flux两种查询语言,可以灵活地进行数据查询、过滤、聚合和计算。这些查询语言支持常见的时序数据操作,提供了丰富的功能和灵活性。
- 扩展性和高可用性:InfluxDB支持水平扩展,可以通过添加更多的节点来增加存储容量和查询吞吐量。它还提供了高可用性机制,支持数据的冗余备份和故障转移,以确保数据的可靠性和持续可用性。
缺点
- 适用范围受限:InfluxDB专注于时序数据处理,在其他类型的数据存储和查询方面相对较弱。如果应用场景涉及非时序数据或复杂的关系查询,可能需要与其他数据库进行集成。
- 索引和存储开销:InfluxDB为了支持高效的时序数据查询,需要维护较大的索引和数据存储结构。这可能会占用较多的存储空间和内存,特别是对于大规模的数据集。
- 复杂性和学习曲线:InfluxDB拥有自己的查询语言和数据模型,学习和掌握这些概念和语法需要一定的时间和学习成本。对于不熟悉时序数据处理的用户来说,可能需要一段时间来适应和理解InfluxDB的工作方式。
- 开源版本不支持集群部署,对于大规模应用来说,使用前需要慎重考虑。但github有童鞋实现了集群版InfluxDB替代方案,感兴趣的童鞋可以在使用万单机版InfluxDB之后,去体验一把集群版
5.InfluxDB特性
- Time Series(时间序列):你可以使用与时间有关的相关函数(如最大、最小、求和等)
- Metrics(度量):你可以实时对大量数据进行计算
- Events(事件):它支持任意的事件数据
6.InfluxDB特点
为时间序列数据专门编写的自定义高性能数据存储。TSM引擎具有高性能的写入和数据压缩
Golang编写,没有其他的依赖
提供简单、高性能的写入,查询http api,Native Http API,内置http支持,使用http读写
插件支持其他数据写入协议,例如graphite、collected、OpenTSDB
支持类sql查询语句
tags可以索引序列化,提供快速有效的查询
Retention policies自动处理过期数据
Continuous queries自动聚合,提高查询效率
schemaless(无结构),可以是任意数量的列
min,max,sum,count,mean,median一系列函数,方便统计
Built-in Explorer自带管理工具
7.InfluxDB应用场景
时序数据以时间作为主要的查询纬度,通常会将连续的多个时序数据绘制成线,制作基于时间的多纬度报表,用于揭示数据背后的趋势、规律、异常,进行实时在线预测和预警,时序数据普遍存在于IT基础设施、运维监控系统和物联网中。如:监控数据统计。每毫秒记录一下电脑内存的使用情况,然后就可以根据统计的数据,利用图形化界面(InfluxDB V1一般配合Grafana)制作内存使用情况的折线图;可以理解为按时间记录一些数据(常用的监控数据、埋点统计数据等),然后制作图表做统计。
8.InfluxDB普通安装
9.InfluxDB docker安装
version: '3.8'
volumes:
influxdb:
services:
influxdb:
image: influxdb:1.8.7
ports:
- '8086:8086'
volumes:
- influxdb:/root/influxdb/data
# - $PWD/influxdb.conf:/root/influxdb/influxdb.conf
environment:
- INFLUXDB_ADMIN_USER=root
- INFLUXDB_ADMIN_PASSWORD=root
- INFLUXDB_DB=sprixin
restart: always
docker pull influxdb:1.8.7
docker run -d -p 8086:8086 --name influxdb -v /data/influxdb:/var/lib/influxdb --restart=always influxdb:1.8.7
常用操作命令
#先不启用密码验证, 创建用户和密码,启动后进入创建好用户和密码后,修改auth-enabled = true 重启容器生效,就必须要用户和密码
docker pull influxdb
docker run -d --name my-influxdb \
-p 8086:8086 \
-p 8083:8083 \
-p 2003:2003 \
-e INFLUXDB_GRAPHITE_ENABLED=true \
-v /data/influxdb/conf/influxdb.conf:/etc/influxdb/influxdb.conf \
-v /data/influxdb:/var/lib/influxdb \
-v /etc/localtime:/etc/localtime \
influxdb
#进入容器
docker exec -it my-influxdb /bin/bash
输入 influx
#创建用户和密码
create user "admin" with password 'admin' with all privileges
create user "admin" with password 'beyond_2021' with all privileges
auth admin admin 登录
show databases; 展示数据库
create database demo 创建表
#默认是不用用户密码的, 是否开启认证,默认值:false
cat /data/influxdb/conf/influxdb.conf
[meta]
dir = "/var/lib/influxdb/meta"
[data]
dir = "/var/lib/influxdb/data"
engine = "tsm1"
wal-dir = "/var/lib/influxdb/wal"
[http]
auth-enabled = false
#容器外面执行命令
curl -i -XPOST http://localhost:8086/query --data-urlencode "q=CREATE DATABASE testdb"
curl -XPOST http://localhost:8086/query --data-urlencode "q=create user "admin123" with password 'admin123' with all privileges"
./influx -database 'testdb' -execute 'auth admin123 admin123'
./influx -database 'testdb' -execute 'auth admin123 admin123'
show users; 启用用户密码后,会报错
输入 influx -username 'admin' -password 'beyond_2021'
# 保存策略
show retention policies on test 显示test数据库策略 如果没有指定策略默认是autogen
对test数据库创建一个策略,2小时之前数据删除,一个副本,设置为默认策略
create retention policy "abc" on "test" duration 2h replication 1 default
10天前数据删除 比如:h(小时),w(星期)
create retention policy "rp_10d" on "testdata" duration 10d replication 1 default
修改默认策略
alter retention policy "autogen" on "demo" duration 10d replication 1 default
alter retention policy "autogen" on "demo" duration 15d replication 1 default
修改策略
alter retention policy "rp_10d" ON "demo" duration 10d replication 1 default
插入数据不指定策略,按默认策略保存
insert into devops,host=server01 cpu=23.1,mem=0.61
指定策略保存数据
insert into "autogen" devops,host=server01 cpu=23.1,mem=0.71
查询时不指定策略,按默认策略查询
select * from "devdata"
指定策略查询数据
select * from "autogen"."devdata"
show tag keys from 表名
show field keys from 表名
10.InfluxDB相关概念
database:数据库; 用于针对不同应用进行数据隔离
measurement:数据库中的表; 类似与关系型数据库table row记录
points:表里面的一行数据; point相当于关系库中表中一条记录
influxDB中独有的一些概念:Point由时间戳(time)、数据(field)和标签(tags)组成
库 database
表 measurement
point = time(主键 可以自动生成,手动指定 必须存在)+field(普通字段 存储数据 必须存在)+ tags标签(可有可无 索引 用来加快查询速度 String)
field:不经常查询数据,可以直接存储为field
tags:索引字段,主要用来提高查询效率
在influxdb中,字段必须存在。因为字段是没有索引的。如果使用字段作为查询条件,会扫描符合查询条件的所有字段值,性能不及tag。类比一下,fields相当于sql的没有索引的列。tags是可选的,但是强烈建议你用上它,因为tag是有索引的,tags相当于sql中的有索引的列。tag value只能是string类型
11.InfluxDB基础操作
HttpAPI
操作库
-- 库操作
- show databases; 查看所有库
- create database test; 创建一个库
- drop database test; 删除一个库
- use test; 选中一个库
- clear database|db; 清除当前上下文的库
> CREATE DATABASE "NOAA_water_database"
> CREATE DATABASE "NOAA_water_database" WITH DURATION 3d REPLICATION 1 SHARD DURATION 1h NAME "liquid"
操作表
-- 表操作
- show measurements; 查看所有表
- drop measurement "test"; 删除一个表 # 注意:删除表
从单个measurement删除所有series:
DROP SERIES FROM "h2o_feet"
从单个measurement删除指定tag的series:
DROP SERIES FROM "h2o_feet" WHERE "location" = 'santa_monica'
从数据库删除有指定tag的所有measurement中的所有数据:
DROP SERIES WHERE "location" = 'santa_monica'
插入数据
-- 基本语法
- insert into <retention policy> measurement,tagKey=tagValue fieldKey=fieldValue timestamp
- 如:
insert user,name=blr,phone=110 id=20,email="11@qq.com"
从上面的输出,简单小结一下插入的语句写法:
1) insert + measurement + "," + tag=value,tag=value + + field=value,field=value
2) tag与tag之间用逗号分隔;field与field之间用逗号分隔
3) tag与field之间用空格分隔
4) tag都是string类型,不需要引导将value包裹
5) field如果是string类型,需要加引导
删除数据
删除measurement`h2o_feet`的所有相关数据:
> DELETE FROM "h2o_feet"
删除measurement`h2o_quality`并且tag`randtag`等于3的所有数据:
> DELETE FROM "h2o_quality" WHERE "randtag" = '3'
删除数据库中2016年一月一号之前的所有数据:
> DELETE WHERE time < '2016-01-01'
普通查询
0、查询所有 # 注意:tags显示再查询结果最后
- select * from test;
1、查询所有的 tag 和 field
- select * from test where person_name='blr'
- select * from test where "name"='xiaochen' # name为influxdb关键字需要加入双引号区分
2、从单个measurement查询所有的field,不插tag
- select *::field from test
3、从单个measurement查询特定的field和tag # 注意:查询时至少要带上一个field key,如果只查询tag字段的话是查不到数据的
- select person_name,age from test
4、同时查询多张表 # 注意:返回是将每张表不同记录返回
- select * from test,student
5、模糊查询
# 前缀匹配,相当于 mysql 的 like 'blr%'
- select * from test where person_name = ~/^blr/
# 后缀匹配,相当于 mysql 的 like '%blr'
- select * from test where person_name = ~/blr$/
# 前后匹配,相当于 mysql 的 like '%blr%'
- select * from test where person_name = ~/blr/
// 例一:从单个measurement查询所有的field和tag
> SELECT * FROM "h2o_feet"
// 例二:从单个measurement中查询特定tag和field
> SELECT "level description","location","water_level" FROM "h2o_feet"
// 例三:从单个measurement中选择特定的tag和field,并提供其标识符类型
> SELECT "level description"::field,"location"::tag,"water_level"::field FROM "h2o_feet"
// 例四:从单个measurement查询所有field
> SELECT *::field FROM "h2o_feet"
// 例五:从measurement中选择一个特定的field并执行基本计算
> SELECT ("water_level" * 2) + 4 from "h2o_feet"
// 例六:从多个measurement中查询数据
> SELECT * FROM "h2o_feet","h2o_pH"
// 例七:从完全限定的measurement中选择所有数据
> SELECT * FROM "NOAA_water_database"."autogen"."h2o_feet"
// 例八:从特定数据库中查询measurement的所有数据
> SELECT * FROM "NOAA_water_database".."h2o_feet"
聚合函数
0、如果我就要对tag字段进行聚合函数计算怎么办?那我们可以通过子查询来实现
- select distinct(person_name) from (select * from test);
1、count() 统计
# 查询某个field字段中的非空数量
- select count(age) from test;
2、DISTINCT() 去重
- select distinct(age) from test;
3、MEAN() 求平均值,这个平均值必须是数字类型
- select mean(age) from test;
4、MEDIAN() 求中位数,从单个字段(field)中的排序值返回中间值
# 中位数统计学中的专有名词,是按顺序排列的一组数据中居于中间位置的数,代表一个样本、种群或概率分布中的一个数值,其可将数值集合划分为相等的上下两部分
- select median(age) from test;
5、SPREAD() 返回字段的最小值和最大值之间的差值。数据类型必须是长整型或者float64
- select spread(age) from test;
6、SUM() 求和
- select sum(age) from test;
7、BOTTOM() 返回一个字段中最小的N个值。字段类型必须是长整型或float64类型
- select bottom(age,3) from test;
8、FIRST() 返回一个字段中时间最早取值
- select first(age) from test;
9、LAST() 返回一个字段中时间最晚取值
- select last(age) from test
10、MAX() 求最大值
- select max(age) from test;
分组聚合 group by
1、基于时间分组
# 查询所有数据,并对其划分为每200毫秒一组
select count(age) from test group by time(200ms)
# 查询所有数据,并对其划分为每200秒一组
select count(age) from test group by time(200s)
# 查询所有数据,并对其划分为每12分钟一组
select count(age) from test group by time(12m)
# 查询所有数据,并对其划分为每12小时一组
select count(age) from test group by time(12h)
# 查询所有数据,并对其划分为每12天一组
select count(age) from test group by time(12d)
# 查询所有数据,并对其划分为每12周一组
select count(age) from test group by time(12w)
分页查询
LIMIT 用法有2钟
1. limit 10 :查询前10条数据
2. limit size offset N :size表示每页大小,N表示第几条记录开始查询
# 查询前10条数据
select * from test limit 10
# 分页,pageSize 为每页显示大小 pageIndex 为查询的页数
pageIndex = 1
pageSize = 10
- select * from test limit pageSize offset (pageIndex - 1)*pageSize
// 例一:限制返回的点数
> SELECT "water_level","location" FROM "h2o_feet" LIMIT 3
// 例一:限制返回的series的数目
> SELECT "water_level" FROM "h2o_feet" GROUP BY * SLIMIT 1
// 例二:限制数据点数和series数并且包括一个GROUP BY time()子句
> SELECT MEAN("water_level") FROM "h2o_feet" WHERE time >= '2015-08-18T00:00:00Z' AND time <= '2015-08-18T00:42:00Z' GROUP BY *,time(12m) LIMIT 2 SLIMIT 1
name: h2o_feet
tags: location=coyote_creek
time mean
---- ----
2015-08-18T00:00:00Z 8.0625
2015-08-18T00:12:00Z 7.8245
// 例一:分页数据点
> SELECT "water_level","location" FROM "h2o_feet" LIMIT 3 OFFSET 3
// 例一:分页series
> SELECT "water_level" FROM "h2o_feet" GROUP BY * SLIMIT 1 SOFFSET 1
排序 order by
# 升序
select * from test order by time asc
# 降序
select * from test order by time desc
into 子句
// 例一:重命名数据库
> SELECT * INTO "copy_NOAA_water_database"."autogen".:MEASUREMENT FROM "NOAA_water_database"."autogen"./.*/ GROUP BY *
name: result
time written
---- -------
0 76290
因为influxdb不支持重命名数据库,所以可以这样重新导入一边数据。`group by *`的作用是将原measurement中的tag key,依旧在新的measurement当成tag key。如果不加,
in查询
# 关系型数据库可以用in关键字来查询多个值
select * from test where person_name in ('','','')
# 但是时序数据库是没有 in 查询的,虽然in是保留的关键字,但是依然有办法解决,可用模糊查询
# 同时匹配123 和 thing
select * from test where person_name = ~/^123$|^thing$/
保留策略
# 1、创建 h (小时) d (天) w (星期)
- CREATE RETENTION POLICY "保留策略名称" ON "数据库名称" DURATION "该保留策略对应的数据过期时间" REPLICATION "复制因子,开源的InfluxDB单机环境永远为1" SHARD DURATION "分片组的默认时长" DEFAULT
- create retention policy "testpolicy" on myInfluxdb duration 72h replication 1 shard duration 1h default
# 2、修改保留策略
- alter retention policy "保留策略名称" on "数据库名称" duration 1d
# 3、修改默认保留策略
- alter retention policy "保留策略名称" on "数据库名称" default
# 4、删除保留策略
- drop retention policy "保留策略名称" on "数据库名称"
创建用户
show
create user "用户名" with password '密码' with all privileges
# 注意:用户名必须双引号,密码必须单引号
# 创建指定库只读用户
create user "用户名" with password '密码'
grant read on 库名 to "用户名"
# 删除用户
drop user "用户名"
数据导入导出
# 导出
influx_inspect export -compress -datadir "/var/lib/influxdb/data" -waldir "/var/lib/influxdb/wal" -out "/home/myDB" -database myDB
# 导入
influx -import -database myDB -path=/home/myDB -precision=ns
# 数据压缩导入
influx -import -database myDB -path=/home/myDB -compress -precision=ns -username=root -password=root
# 数据未压缩导入
influx -import -database myDB -path=/home/myDB -compress -precision=ns -username=root -password=root
高级语法
连续查询(Continuous Queries下文统一简称CQ)是InfluxQL对实时数据自动周期运行的查询,然后把查询结果写入到指定的measurement中。
cq_query
需要一个函数,一个INTO
子句和一个GROUP BY time()
子句:
注意:请注意,在WHERE
子句中,cq_query
不需要时间范围。 InfluxDB在执行CQ时自动生成cq_query
的时间范围。cq_query
的WHERE
子句中的任何用户指定的时间范围将被系统忽略。
CREATE CONTINUOUS QUERY <cq_name> ON <database_name>
BEGIN
<cq_query>
END
SELECT <function[s]> INTO <destination_measurement> FROM <measurement> [WHERE <stuff>] GROUP BY time(<interval>)[,<tag_key[s]>]
例一:自动采样数据
CREATE CONTINUOUS QUERY "cq_basic" ON "transportation"
BEGIN
SELECT mean("passengers") INTO "average_passengers" FROM "bus_data" GROUP BY time(1h)
END
例二:自动采样数据到另一个保留策略里
CREATE CONTINUOUS QUERY "cq_basic_rp" ON "transportation"
BEGIN
SELECT mean("passengers") INTO "transportation"."three_weeks"."average_passengers" FROM "bus_data" GROUP BY time(1h)
END
例三:使用逆向引用自动采样数据
CREATE CONTINUOUS QUERY "cq_basic_br" ON "transportation"
BEGIN
SELECT mean(*) INTO "downsampled_transportation"."autogen".:MEASUREMENT FROM /.*/ GROUP BY time(30m),*
END
例四:自动采样数据并配置CQ的时间边界
CREATE CONTINUOUS QUERY "cq_basic_offset" ON "transportation"
BEGIN
SELECT mean("passengers") INTO "average_passengers" FROM "bus_data" GROUP BY time(1h,15m)
END
例一:配置执行间隔
CREATE CONTINUOUS QUERY "cq_advanced_every" ON "transportation"
RESAMPLE EVERY 30m
BEGIN
SELECT mean("passengers") INTO "average_passengers" FROM "bus_data" GROUP BY time(1h)
END
每30分钟运行一边CQ,覆盖区间为`now() - 1h` ~ `now()`。
例二:配置CQ的重采样时间范围
CREATE CONTINUOUS QUERY "cq_advanced_for" ON "transportation"
RESAMPLE FOR 1h
BEGIN
SELECT mean("passengers") INTO "average_passengers" FROM "bus_data" GROUP BY time(30m)
END
每30分钟执行一次,覆盖区间为`now() - 1h` ~ `now()`
例三:配置执行间隔和CQ时间范围
CREATE CONTINUOUS QUERY "cq_advanced_every_for" ON "transportation"
RESAMPLE EVERY 1h FOR 90m
BEGIN
SELECT mean("passengers") INTO "average_passengers" FROM "bus_data" GROUP BY time(30m)
END
每1小时执行一次,覆盖区间为`now() - 1h30m` ~ `now()`
12.InfluxDB集群
简介
InfluxDB CLuster是一个开源的 时间序列数据库,没有外部依赖。它对于记录指标、事件和执行分析很有用。
InfluxDB CLuster启发于InfluxDB Enterprise、InfluxDB v1.8.10 和 InfluxDB v0.11.1,旨在替代InfluxDB Enterprise。
InfluxDB CLuster易于维护,可以与上游InfluxDB 1.x保持实时更新
特性
内置 HTTP API ,无需编写任何服务端代码即可启动和运行
数据可以被标记 tag ,允许非常灵活的查询
类似 SQL 的查询语言
集群支持开箱即用,因此处理数据可以水平扩展。集群目前处于生产就绪状态
易于安装和管理,数据写入查询速度快
旨在实时应答查询。这意味着每个数据点在到来时都会被计算索引,并且在 < 100 毫秒内返回的查询中立即可用
集群架构
InfluxDB Cluster 安装由两组独立的进程组成:Data 节点和 Meta 节点。
Meta节点
元节点持有以下所有的元数据
集群中的所有节点和它们的角色
集群中存在的所有数据库和保留策略
所有分片和分片组,以及它们存在于哪些节点上
集群用户和他们的权限
所有的连续查询
Data节点
数据节点持有所有的原始时间序列数据和元数据,包括:
测量值
标签键和值
字段键和值
Meta 节点通过 TCP 协议和 Raft 共识协议相互通信,默认都使用端口 8089,此端口必须在 Meta 节点之间是可访问的。默认 Meta 节点还将公开绑定到端口 8091 的 HTTP API,influxd-ctl 命令使用该 API。
Data 节点通过绑定到端口 8088 的 TCP 协议相互通信。Data 节点通过绑定到 8091 的 HTTP API 与 Meta 节点通信。这些端口必须在 Meta 节点和 Data 节点之间是可访问的。
在集群内,所有 Meta 节点都必须与所有其它 Meta 节点通信。所有 Data 节点必须与所有其它 Data 节点和所有 Meta 节点通信。
13.性能优化
缓存大小
InfluxDB的存储引擎是TSM Tree(Time-Structured Merge Tree),基本上整体思想和LSM Tree(Log-Structured-Tree)类似,做了一些时序场景下数据存储结构上的建模优化。cache-snapshot-memory-size值需要调试
[data]
cache-snapshot-memory-size=562144000
cache-snapshot-memory-size 这个大小控制的是 LSM 中的 cache 的大小,当 cache 达到一定阈值后,cache会落盘生成tsm file,此时的tsm file的level为 level 0,两个相同level的 tsm file 会进行 compact 生成一个level + 1的 tsm file,既两个 level 0 的tsm file会生成一个 level 1的tsm file,这种设计既TSM tree的写入放大问题。
由于Influxdb是固定两个低level文件compact成一个高一级level的tsm file,所以如果cache size越小,dump成tsm file的频率越高,进而做compact的频率也越高,造成写入放大越显著,当写入的频率很高的场景下,会导致influxdb的吞吐下降非常明显。
compact频率变高后,Influxdb写入放大很重要一个原因是TSH file数据做了编码压缩磁盘占用空间,当compact时,需要对数据decode,会带来明显的性能损耗。
Influxdb为了优化这个问题,在做compact时分为optimize compact和full compact两种类型。在full compact场景下,首先会对tsm file中的block做decode,然后按照每个Block存储的point数量,将decode的Point value按照时间顺序重新encode成Block,然后写入到新的TSM file中,其中的性能损耗会非常显著。而在optimize场景下,不会读取block内部的数据,会对多个block拼接,减少性能消耗。
目前部分场景下Influxdb做compact还是会选择full compact。optimize compact虽然会提升compact速度和减少compact的资源消耗,但是会引起查询放大问题:需要从多个block中才能获取到需要返回的数据。
cache-snapshot-memory-size 值理论上是越大越好,但是需要关注你的硬件配置
cache-snapshot-memory-size 值跟当前并发写入tags数量有关系,如果你的tags数很大的情况下,一定要调大这个值,如果tags数不多,只是少数tags的数据写入频率很高,那么这个值稍低也不会对性能有太大的影响。
数据表调优
表 point = [time + tags] (series 100w tags 10w) + fields
max-series-per-databse 可调整为0,如注释所示:该参数控制每个db的最大的series数量
max-values-per-tag可调整为0,如注释所示:该参数控制每个tag的tag_value数量
查询超时时间配置
query-timeout="100"
参考资料
InfluxDB中文文档 https://jasper-zhang1.gitbooks.io/influxdb/content/