数据写进去了,接下来就是把它们查出来。InfluxDB 使用 InfluxQL 作为查询语言,语法类似SQL,但专门为时间序列数据优化过。
如果你熟悉SQL,学 InfluxQL 会很快上手。如果不熟悉也没关系,我们从基础开始。
InfluxQL 基础查询语法结构示意图,展示了 SELECT 语句的组成部分、常见查询模式以及 WHERE 子句的使用方法

InfluxQL 的基本结构和SQL很像:
sqlSELECT <field_key>[,<field_key>,<tag_key>] FROM <measurement_name>[,<measurement_name>]
最简单的查询:
sql-- 查询所有字段
SELECT * FROM temperature
-- 查询特定字段
SELECT value FROM temperature
-- 查询多个字段
SELECT value, humidity FROM temperature
sql-- 按标签筛选
SELECT * FROM temperature WHERE location = 'room1'
-- 按时间筛选
SELECT * FROM temperature WHERE time >= '2023-01-01T00:00:00Z'
-- 组合条件
SELECT * FROM temperature
WHERE location = 'room1' AND time >= now() - 1h
时间是时序数据的核心,InfluxQL 提供了灵活的时间查询:
sql-- 查询最近1小时的数据
SELECT * FROM temperature WHERE time >= now() - 1h
-- 查询特定时间段
SELECT * FROM temperature
WHERE time >= '2023-01-01T00:00:00Z'
AND time <= '2023-01-01T23:59:59Z'
-- 查询最近7天
SELECT * FROM temperature WHERE time >= now() - 7d
-- 查询今天的数据
SELECT * FROM temperature WHERE time >= now() - 1d
时间单位很丰富:
InfluxQL 聚合函数和时间窗口示意图,展示了基本聚合函数的使用方法、GROUP BY TIME的工作原理以及不同时间窗口粒度的性能对比

InfluxQL 提供了丰富的聚合函数:
sql-- 计算平均值
SELECT MEAN(value) FROM temperature WHERE time >= now() - 1h
-- 计算最大值和最小值
SELECT MAX(value), MIN(value) FROM temperature WHERE time >= now() - 1h
-- 计算总和
SELECT SUM(value) FROM temperature WHERE time >= now() - 1h
-- 计算数量
SELECT COUNT(value) FROM temperature WHERE time >= now() - 1h
-- 计算标准差
SELECT STDDEV(value) FROM temperature WHERE time >= now() - 1h
GROUP BY TIME 是 InfluxQL 的核心功能,用来按时间窗口聚合数据:
sql-- 按5分钟窗口计算平均值
SELECT MEAN(value) FROM temperature
WHERE time >= now() - 1h
GROUP BY time(5m)
-- 按1小时窗口计算最大值
SELECT MAX(value) FROM temperature
WHERE time >= now() - 1d
GROUP BY time(1h)
-- 按天计算平均值
SELECT MEAN(value) FROM temperature
WHERE time >= now() - 30d
GROUP BY time(1d)
除了时间,还可以按标签分组:
sql-- 按location分组
SELECT MEAN(value) FROM temperature
WHERE time >= now() - 1h
GROUP BY location
-- 按时间和标签同时分组
SELECT MEAN(value) FROM temperature
WHERE time >= now() - 1h
GROUP BY time(5m), location
-- 多个标签分组
SELECT MEAN(value) FROM temperature
WHERE time >= now() - 1h
GROUP BY location, sensor_type
InfluxQL 高级查询功能示意图,展示了子查询、数学运算和数据填充等高级功能的使用方法和应用场景

InfluxQL 支持子查询,用来处理复杂的数据分析:
sql-- 查询高于平均温度的数据点
SELECT * FROM temperature
WHERE value > (
SELECT MEAN(value) FROM temperature WHERE time >= now() - 1h
)
-- 查询每小时最高温度的时间点
SELECT * FROM (
SELECT MAX(value) FROM temperature
WHERE time >= now() - 1d
GROUP BY time(1h)
)
可以对字段进行数学运算:
sql-- 温度单位转换(摄氏度转华氏度)
SELECT value * 9/5 + 32 AS fahrenheit FROM temperature
-- 计算温湿度指数
SELECT value + humidity * 0.1 AS comfort_index FROM temperature
-- 计算变化率
SELECT DERIVATIVE(value) FROM temperature
WHERE time >= now() - 1h
GROUP BY time(1m)
时序数据经常有缺失值,可以用FILL来处理:
sql-- 用前一个值填充
SELECT MEAN(value) FROM temperature
WHERE time >= now() - 1h
GROUP BY time(5m)
FILL(previous)
-- 用线性插值填充
SELECT MEAN(value) FROM temperature
WHERE time >= now() - 1h
GROUP BY time(5m)
FILL(linear)
-- 用固定值填充
SELECT MEAN(value) FROM temperature
WHERE time >= now() - 1h
GROUP BY time(5m)
FILL(0)
-- 不填充(默认)
SELECT MEAN(value) FROM temperature
WHERE time >= now() - 1h
GROUP BY time(5m)
FILL(null)
InfluxQL 窗口函数和移动计算示意图,展示了移动平均、导数计算和累积计算等窗口函数的工作原理和应用场景

sql-- 5点移动平均
SELECT MOVING_AVERAGE(value, 5) FROM temperature
WHERE time >= now() - 1h
-- 指数移动平均
SELECT EXPONENTIAL_MOVING_AVERAGE(value, 5) FROM temperature
WHERE time >= now() - 1h
sql-- 计算导数(变化率)
SELECT DERIVATIVE(value) FROM temperature
WHERE time >= now() - 1h
GROUP BY time(1m)
-- 计算非负导数
SELECT NON_NEGATIVE_DERIVATIVE(value) FROM cpu_usage
WHERE time >= now() - 1h
GROUP BY time(1m)
-- 计算差值
SELECT DIFFERENCE(value) FROM temperature
WHERE time >= now() - 1h
sql-- 累积和
SELECT CUMULATIVE_SUM(value) FROM rainfall
WHERE time >= now() - 1d
-- 积分计算
SELECT INTEGRAL(value) FROM power_consumption
WHERE time >= now() - 1d
GROUP BY time(1h)
sql-- 匹配特定模式的标签值
SELECT * FROM temperature WHERE location =~ /room[0-9]+/
-- 不匹配特定模式
SELECT * FROM temperature WHERE location !~ /test.*/
-- 匹配多个measurement
SELECT * FROM /temperature|humidity/ WHERE time >= now() - 1h
sql-- 模糊匹配
SELECT * FROM temperature WHERE location LIKE 'room%'
-- 不匹配
SELECT * FROM temperature WHERE location NOT LIKE 'test%'
sql-- 按时间升序(默认)
SELECT * FROM temperature ORDER BY time ASC
-- 按时间降序
SELECT * FROM temperature ORDER BY time DESC
-- 按字段值排序
SELECT * FROM temperature ORDER BY value DESC
sql-- 限制返回条数
SELECT * FROM temperature LIMIT 100
-- 跳过前N条记录
SELECT * FROM temperature LIMIT 100 OFFSET 50
-- 获取最新的10条记录
SELECT * FROM temperature ORDER BY time DESC LIMIT 10
sql-- 查询多个measurement
SELECT * FROM temperature, humidity WHERE time >= now() - 1h
-- 使用正则表达式查询多个measurement
SELECT * FROM /temperature|humidity/ WHERE time >= now() - 1h
虽然InfluxQL不支持传统的JOIN,但可以用其他方式合并数据:
sql-- 在应用层合并不同measurement的数据
-- 或者使用Flux查询语言(InfluxDB 2.0+)
sql-- 查找温度异常的时间点
SELECT * FROM temperature
WHERE value > 30 OR value < 10
-- 查找CPU使用率持续高于80%的时间段
SELECT MEAN(cpu_percent) FROM cpu_usage
WHERE time >= now() - 1h
GROUP BY time(5m)
HAVING MEAN(cpu_percent) > 80
sql-- 计算响应时间的95百分位数
SELECT PERCENTILE(response_time, 95) FROM api_requests
WHERE time >= now() - 1h
GROUP BY time(5m)
-- 查找最慢的请求
SELECT * FROM api_requests
WHERE time >= now() - 1h
ORDER BY response_time DESC
LIMIT 10
sql-- 计算同比增长率
SELECT MEAN(value) FROM sales
WHERE time >= now() - 7d
GROUP BY time(1d)
-- 计算移动平均趋势
SELECT MOVING_AVERAGE(MEAN(value), 7) FROM temperature
WHERE time >= now() - 30d
GROUP BY time(1d)
InfluxQL 查询优化技巧对比图,展示了推荐与不推荐的查询方式对比,以及各种优化策略的性能影响分析

sql-- 好的查询:利用标签索引
SELECT * FROM temperature WHERE location = 'room1' AND time >= now() - 1h
-- 避免:对字段进行范围查询
SELECT * FROM temperature WHERE value > 25 -- 这会很慢
sql-- 总是指定时间范围
SELECT * FROM temperature WHERE time >= now() - 1h
-- 避免查询全部历史数据
SELECT * FROM temperature -- 这可能很慢
sql-- 使用适当的时间窗口
SELECT MEAN(value) FROM temperature
WHERE time >= now() - 1d
GROUP BY time(1h) -- 而不是 GROUP BY time(1s)
InfluxQL 常见错误诊断与解决方案图,展示了语法错误、性能问题和数据类型问题的诊断流程以及相应的解决方案

sql-- 错误:忘记引号
SELECT * FROM temperature WHERE location = room1
-- 正确:字符串要加引号
SELECT * FROM temperature WHERE location = 'room1'
-- 错误:时间格式不对
SELECT * FROM temperature WHERE time > '2023-01-01'
-- 正确:使用完整的时间格式
SELECT * FROM temperature WHERE time > '2023-01-01T00:00:00Z'
sql-- 问题:查询范围太大
SELECT * FROM temperature WHERE time >= '2020-01-01T00:00:00Z'
-- 解决:限制时间范围
SELECT * FROM temperature WHERE time >= now() - 7d
-- 问题:没有使用标签筛选
SELECT * FROM temperature WHERE value > 25
-- 解决:先用标签筛选,再用字段筛选
SELECT * FROM temperature WHERE location = 'room1' AND value > 25
sql-- 错误:标签值用数字比较
SELECT * FROM temperature WHERE room_number > 5
-- 正确:标签值是字符串
SELECT * FROM temperature WHERE room_number = '5'
sh# 进入 InfluxDB 命令行
influx -host localhost -port 8086
# 选择数据库(InfluxDB 1.x)
USE mydb
# 执行查询
SELECT * FROM temperature WHERE time >= now() - 1h;
# 格式化输出
SELECT * FROM temperature WHERE time >= now() - 1h FORMAT json;
sh# 使用curl查询
curl -G 'http://localhost:8086/query' \
--data-urlencode "db=mydb" \
--data-urlencode "q=SELECT * FROM temperature WHERE time >= now() - 1h"
# InfluxDB 2.0 API
curl -XPOST 'http://localhost:8086/api/v2/query' \
-H 'Authorization: Token your-token' \
-H 'Content-Type: application/vnd.flux' \
-d 'from(bucket:"mybucket") |> range(start:-1h) |> filter(fn:(r) => r._measurement == "temperature")'
掌握了InfluxQL,你就能从时序数据中挖掘出有价值的信息了。下一篇我们会学习聚合函数的高级用法,让数据分析更加强大。
本文作者:柳始恭
本文链接:
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!