时序数据库——时间线数据的专业存储 / Time-Series Databases for Timeline Data
📅 创建时间:2026-05-08 🏷️ 标签:#时序数据库 #TimescaleDB #InfluxDB #TDengine #监控 #IoT 📚 前置知识:[[00-db-overview]] [[09-olap-databases]](了解 OLAP 基础) 📚 相关知识:[[06-kv-embedded]](LSM-Tree 等底层存储)
定位速览
┌─────────────────────────────────────────────────────────────┐
│ 时序数据库的独特定位 │
├─────────────────────────────────────────────────────────────┤
│ │
│ 时序数据 = 按时间排列的数据序列 │
│ │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ 监控指标:CPU、内存、网络流量(随时间变化) │ │
│ │ 传感器数据:温度、湿度、GPS 坐标 │ │
│ │ 金融数据:股票价格、交易量、汇率 │ │
│ │ 用户行为:点击流、页面浏览、API 调用 │ │
│ │ 日志:应用日志、访问日志、错误日志 │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
│ 时序数据的特征: │
│ • 写多读少(持续写入,很少查询) │
│ • 基于时间聚合(SUM、AVG、MAX、MIN 等) │
│ • 冷热分层(近期数据热,历史数据冷) │
│ • 很少更新/删除(追加为主) │
│ • 数据量大(高频率采样 = 大量数据) │
│ │
└─────────────────────────────────────────────────────────────┘第1部分:时序数据的典型查询模式
┌─────────────────────────────────────────────────────────────┐
│ 时序数据典型查询模式 │
├─────────────────────────────────────────────────────────────┤
│ │
│ 1. 最新值查询: │
│ SELECT device_id, value │
│ FROM metrics WHERE device_id = 'sensor_001' │
│ ORDER BY timestamp DESC LIMIT 1; │
│ │
│ 2. 范围查询: │
│ SELECT * FROM metrics │
│ WHERE device_id = 'sensor_001' │
│ AND timestamp BETWEEN '2026-05-01' AND '2026-05-08'; │
│ │
│ 3. 降采样(Downsampling): │
│ -- 原始数据:每秒一个点 │
│ -- 降采样后:每分钟平均值 │
│ SELECT time_bucket('1 minute', timestamp) as bucket, │
│ avg(value) as avg_value │
│ FROM metrics │
│ WHERE device_id = 'sensor_001' │
│ AND timestamp > NOW() - INTERVAL '1 hour' │
│ GROUP BY bucket │
│ ORDER BY bucket; │
│ │
│ 4. 滑动窗口统计: │
│ -- 最近 5 分钟的滚动平均 │
│ SELECT time_bucket('1 minute', timestamp) as bucket, │
│ avg(value) OVER (ORDER BY bucket │
│ ROWS BETWEEN 4 PRECEDING AND CURRENT ROW) │
│ FROM metrics; │
│ │
│ 5. 异常检测: │
│ SELECT * FROM metrics │
│ WHERE value > avg(value) OVER (PARTITION BY device_id │
│ ORDER BY timestamp ROWS BETWEEN 100 PRECEDING │
│ AND 1 PRECEDING) * 2; │
│ │
└─────────────────────────────────────────────────────────────┘第2部分:TimescaleDB——PostgreSQL 的时序扩展
2.1 超表(Hypertable)
┌─────────────────────────────────────────────────────────────┐
│ TimescaleDB 超表原理 │
├─────────────────────────────────────────────────────────────┤
│ │
│ TimescaleDB = PostgreSQL + 时序超表 │
│ │
│ 核心概念:Hypertable(超表) │
│ • 对用户来说就是一张普通表 │
│ • 底层自动按时间分区(chunk)为多个子表 │
│ │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ SELECT * FROM metrics; (超表) │ │
│ │ ↓ 底层自动路由到 chunk │ │
│ │ ┌───────────┐ ┌───────────┐ ┌───────────┐ │ │
│ │ │ chunk_1 │ │ chunk_2 │ │ chunk_3 │ │ │
│ │ │ 5月1-7日 │ │ 5月8-14日 │ │ 5月15-21日│ │ │
│ │ │ (已压缩) │ │ (已压缩) │ │ (活跃) │ │ │
│ │ └───────────┘ └───────────┘ └───────────┘ │ │
│ │ │ │
│ │ Chunk 自动按时间切分,查询时自动跳过不相关 chunk │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
│ 压缩(最关键特性): │
│ • 历史 chunk 自动压缩(压缩率 10-20x) │
│ • 压缩格式:列式 + 字典编码 + 游程编码 │
│ • 查询时自动解压缩,对用户透明 │
│ • 配置:ALTER TABLE metrics SET (timescaledb.compress, │
│ timescaledb.compress_segmentby = 'device_id'); │
│ │
│ 连续聚合(Continuous Aggregate): │
│ • 后台自动预计算降采样数据 │
│ • 近期原始数据 + 历史聚合数据混合查询 │
│ • 查询速度提升 100-1000x │
│ │
└─────────────────────────────────────────────────────────────┘2.2 TimescaleDB 实战
sql
-- ================== 创建超表 ==================
SELECT create_hypertable(
'metrics',
'timestamp',
chunk_time_interval => INTERVAL '1 day', -- 每天一个 chunk
migrate_data => true
);
-- 添加索引(按设备 ID)
CREATE INDEX ON metrics (device_id, timestamp DESC);
-- ================== 连续聚合(自动预计算) ==================
-- 每分钟聚合:自动计算(后台运行)
CREATE MATERIALIZED VIEW metrics_minutely
WITH (timescaledb.continuous) AS
SELECT time_bucket('1 minute', timestamp) AS bucket,
device_id,
AVG(value) as avg_value,
MAX(value) as max_value,
MIN(value) as min_value,
COUNT(*) as sample_count
FROM metrics
GROUP BY 1, 2
WITH NO DATA;
-- 关联连续聚合和超表(自动刷新策略)
SELECT add_continuous_aggregate_policy(
'metrics_minutely',
start_offset => INTERVAL '3 hours',
end_offset => INTERVAL '1 hour', -- 1 小时前的数据自动聚合
schedule_interval => INTERVAL '10 minutes'
);
-- ================== 数据保留策略 ==================
-- 自动删除 30 天前的原始数据(保留聚合)
SELECT add_retention_policy(
'metrics',
INTERVAL '30 days'
);
-- ================== 实战:IoT 传感器分析 ==================
-- 查询:每台设备过去 7 天的每小时平均 CPU 使用率
SELECT
device_id,
time_bucket('1 hour', timestamp) as hour,
ROUND(AVG(cpu_usage)::numeric, 2) as avg_cpu,
ROUND(MAX(cpu_usage)::numeric, 2) as max_cpu,
COUNT(*) as samples
FROM metrics
WHERE metric_name = 'cpu_usage'
AND timestamp > NOW() - INTERVAL '7 days'
GROUP BY 1, 2
ORDER BY 1, 2;
-- 查询:异常 CPU 使用(超过该设备历史均值的 2 倍)
WITH device_stats AS (
SELECT device_id,
AVG(value) as mean,
STDDEV(value) as std
FROM metrics
WHERE metric_name = 'cpu_usage'
AND timestamp > NOW() - INTERVAL '7 days'
GROUP BY device_id
)
SELECT m.device_id, m.timestamp, m.value, ds.mean, ds.std
FROM metrics m
JOIN device_stats ds ON m.device_id = ds.device_id
WHERE m.metric_name = 'cpu_usage'
AND m.value > ds.mean + 2 * ds.std;2.3 TimescaleDB + pgvector:时序 + 语义
sql
-- TimescaleDB + pgvector:AI + 时序融合
-- 场景:时序数据异常模式的语义检索
-- 1. 存储带 embedding 的时序摘要
CREATE TABLE anomaly_signatures (
id SERIAL PRIMARY KEY,
device_id TEXT,
start_time TIMESTAMPTZ,
end_time TIMESTAMPTZ,
signature_embedding VECTOR(768), -- 异常模式的 embedding
description TEXT
);
CREATE INDEX ON anomaly_signatures USING hnsw (signature_embedding);
-- 2. 查找相似的历史异常
SELECT
id,
device_id,
description,
start_time,
1 - (signature_embedding <=> query_embedding) as similarity
FROM anomaly_signatures
WHERE device_id = 'sensor_001'
AND start_time > NOW() - INTERVAL '30 days'
ORDER BY signature_embedding <=> query_embedding
LIMIT 5;第3部分:InfluxDB
┌─────────────────────────────────────────────────────────────┐
│ InfluxDB 特点 │
├─────────────────────────────────────────────────────────────┤
│ │
│ InfluxDB = 时序数据库的"原生"产品 │
│ │
│ 核心概念(Line Protocol): │
│ measurement,tag-set,field-set,timestamp │
│ │
│ weather,location=us-midwest,season=summer temperature=82 1465839830100400200
│ │
│ 优势: │
│ • 专为时序设计,TSM 引擎(类似 LSM-Tree) │
│ • Telegraf 采集生态(200+ 采集器) │
│ • InfluxQL(类 SQL)+ Flux(函数式脚本) │
│ • 连续查询(类似 TimescaleDB 的 continuous aggregate) │
│ │
│ vs TimescaleDB: │
│ • TimescaleDB = PostgreSQL 扩展(兼得 SQL + 时序) │
│ • InfluxDB = 独立时序数据库(更专但与 PG 生态不兼容) │
│ • 如果已在用 PostgreSQL → TimescaleDB │
│ • 如果需要完整时序平台(采集+存储+可视化)→ InfluxDB │
│ │
└─────────────────────────────────────────────────────────────┘第4部分:TDengine——国产超大规模时序数据库
┌─────────────────────────────────────────────────────────────┐
│ TDengine 核心特点 │
├─────────────────────────────────────────────────────────────┤
│ │
│ 涛思数据出品,GitHub Stars: 22K+,主打超大规模 │
│ │
│ 核心优势: │
│ • 超级表(Super Table):一个设备一张子表,共享 Schema │
│ • 写入性能:单节点 100 万行/秒+ │
│ • 集群版支持:100 亿行+ 表 │
│ • 存储压缩率:10-20x(列式压缩) │
│ • 连续聚合:毫秒级响应 │
│ │
│ 与其他时序 DB 的最大区别: │
│ • 存储时同时预计算(写入即索引) │
│ • 不需要独立的流计算引擎(内置 Streaming SQL) │
│ • 支持 Kafka / MQTT / OPC-UA 原生接入 │
│ │
│ 适合场景: │
│ • 电网/水务/燃气等能源行业(千万级 IoT 设备) │
│ • 车联网(亿级车辆实时数据) │
│ • 工业互联网(工厂设备监控) │
│ │
└─────────────────────────────────────────────────────────────┘第5部分:选型对比
┌─────────────────────────────────────────────────────────────┐
│ 时序数据库选型对比 │
├─────────────────────────────────────────────────────────────┤
│ │
│ │ 数据库 │ 架构 │ 最大优势 │ 适合规模│
│ ├───────────────┼─────────────┼────────────────┼─────────┤
│ │ TimescaleDB │ PG 扩展 │ SQL + 时序合一 │ 中等 │
│ │ │ (HTAP) │ │ │
│ ├───────────────┼─────────────┼────────────────┼─────────┤
│ │ InfluxDB │ 原生时序 │ Telegraf 生态 │ 中等 │
│ │ │ │ │ │
│ ├───────────────┼─────────────┼────────────────┼─────────┤
│ │ TDengine │ 原生时序 │ 超大规模 │ 超大规模│
│ │ │ + 流计算 │ 国产 │ │
│ ├───────────────┼─────────────┼────────────────┼─────────┤
│ │ QuestDB │ 原生时序 │ 极速写入 │ 中等 │
│ │ │ │ 内存映射 │ │
│ ├───────────────┼─────────────┼────────────────┼─────────┤
│ │ ClickHouse │ 列式 OLAP │ 分析能力最强 │ 大规模 │
│ │ │ │ (需额外适配) │ 分析 │
│ │
│ 选型建议: │
│ • 已有 PostgreSQL → TimescaleDB(零学习成本) │
│ • 需要完整采集+存储+可视化 → InfluxDB(TICK Stack) │
│ • 千万级 IoT 设备 → TDengine │
│ • 监控+APM → VictoriaMetrics / Thanos(Prometheus 生态) │
│ │
└─────────────────────────────────────────────────────────────┘学习状态:🟡 开始学习