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

InfluxQL 的基本结构和SQL很像:
sql SELECT <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 许可协议。转载请注明出处!