3. SQL 基础回顾:查询与聚合
在将 SQL 与 Grafana 结合进行趋势分析之前,必须牢固掌握 SQL 查询的核心语法。本章将系统回顾 SELECT、WHERE、ORDER BY、LIMIT 以及常用聚合函数,这些是构建任何时间序列查询的基石。
3.1 SELECT 语句与字段投影
SELECT 语句用于从数据库表中检索数据。其基本语法决定了返回哪些列(字段)以及如何对它们进行变换。
核心语法结构:
SELECT column1, column2, ...
FROM table_name;
使用 * 通配符可选择所有列,但在生产环境中应明确指定列名以提高查询性能和可读性。
Grafana 实践提示: 在 Grafana 的查询编辑器中,始终明确列出你需要的字段(如
timestamp、value、host),避免使用 SELECT *,这可以减少数据传输量并避免因表结构变更导致的仪表盘故障。
3.2 WHERE 条件过滤
WHERE 子句用于在数据返回前过滤行记录。它支持比较运算符(=, >, <)、逻辑运算符(AND, OR, NOT)以及范围匹配(IN, BETWEEN, LIKE)。
| 运算符 | 示例 | 说明 |
|---|---|---|
= |
WHERE status = 'active' |
精确匹配 |
> / < |
WHERE cpu > 90 |
大于 / 小于 |
BETWEEN |
WHERE ts BETWEEN '2024-01-01' AND '2024-01-31' |
范围匹配(闭区间) |
IN |
WHERE region IN ('us-east', 'eu-west') |
匹配集合中的任意值 |
LIKE |
WHERE host LIKE 'web-%' |
模式匹配(% 通配符) |
性能警告: 在
WHERE 子句中对列使用函数(如 WHERE DATE(ts) = '2024-01-01')会导致索引失效。应尽量使用列原生格式进行范围比较,或利用数据库的时间函数优化。
3.3 ORDER BY 排序与 LIMIT 分页
ORDER BY 用于对结果集按一列或多列进行排序,默认升序(ASC),可指定 DESC 降序。LIMIT 用于限制返回的行数,常与 ORDER BY 配合实现“Top-N”查询。
典型用法:获取 CPU 使用率最高的前 5 条记录
SELECT timestamp, host, cpu_usage
FROM system_metrics
WHERE timestamp > now() - INTERVAL '1 hour'
ORDER BY cpu_usage DESC
LIMIT 5;
分页模式: 在需要分页展示时,某些数据库(如 PostgreSQL、MySQL)支持 LIMIT 配合 OFFSET 语法。
-- 获取第 2 页数据,每页 10 条
SELECT * FROM events
ORDER BY event_time DESC
LIMIT 10 OFFSET 10;
Grafana 应用: 在 Grafana 的“Table”面板中,你可以利用
ORDER BY 和 LIMIT 来展示“最新告警”或“最高延迟的 Top 10 服务”,无需在应用层进行二次排序。
3.4 常用聚合函数
聚合函数用于对一组值执行计算并返回单个汇总值。它们通常与 GROUP BY 子句结合使用,是趋势分析的核心工具。
| 函数 | 返回类型 | 说明 | 忽略 NULL |
|---|---|---|---|
COUNT(*) |
整数 | 统计行数(包括 NULL) | 否 |
COUNT(column) |
整数 | 统计非 NULL 值的数量 | 是 |
SUM(column) |
数值 | 计算数值列的总和 | 是 |
AVG(column) |
浮点数 | 计算数值列的平均值 | 是 |
MIN(column) |
与列类型相同 | 返回最小值 | 是 |
MAX(column) |
与列类型相同 | 返回最大值 | 是 |
3.5 综合查询示例
以下示例展示了如何将上述知识点组合成一个完整的趋势分析查询。该查询按小时统计每个服务的平均响应时间和请求总数。
SELECT
DATE_TRUNC('hour', request_time) AS hour_bucket,
service_name,
COUNT(*) AS total_requests,
AVG(response_time_ms) AS avg_response_time,
MAX(response_time_ms) AS max_response_time
FROM api_requests
WHERE request_time >= now() - INTERVAL '7 days'
AND status_code != 500
GROUP BY hour_bucket, service_name
ORDER BY hour_bucket DESC, avg_response_time DESC
LIMIT 100;
查询解析:
- DATE_TRUNC:将时间戳截断到小时级别,实现时间桶聚合。
- WHERE:过滤最近 7 天数据,并排除服务器错误(500)。
- GROUP BY:按小时和服务名分组,这是生成多维度时间序列的关键。
- ORDER BY:按时间降序,再按平均响应时间降序排列。
- LIMIT:限制返回 100 条记录,防止 Grafana 面板过载。
Grafana 集成: 在 Grafana 的“Time series”面板中,你可以直接使用上述查询作为数据源。Grafana 会自动识别
hour_bucket 列为时间字段,service_name 为维度字段,avg_response_time 和 total_requests 为指标字段,无需额外配置。
3.6 常见错误与避坑指南
| 错误模式 | 错误示例 | 正确做法 |
|---|---|---|
| SELECT 中混合聚合与非聚合列 | SELECT host, AVG(cpu) FROM metrics |
非聚合列必须出现在 GROUP BY 中 |
| WHERE 中使用聚合函数 | WHERE AVG(cpu) > 90 |
使用 HAVING 子句过滤聚合结果 |
| ORDER BY 使用别名但数据库不支持 | ORDER BY avg_cpu(某些数据库) |
使用原始表达式或确认数据库支持别名排序 |
| LIMIT 不加 ORDER BY | SELECT * FROM logs LIMIT 10 |
结果不确定,应始终配合 ORDER BY |