物联网设备、日志采集、监控指标——这些场景的数据量动辄每秒数万条,写入压力大、查询还要实时。传统关系型数据库扛不住写入,NoSQL 又让查询变得痛苦。CrateDB 6.2.8 的发布,再次提醒我们这条赛道上有一个有意思的选项:分布式架构 + SQL 接口,专门面向机器数据。
为什么机器数据需要专门的数据库
机器数据有几个鲜明特征:
- 写入密集:传感器、日志、指标持续涌入,峰值每秒数万条是常态。
- 时间维度强:几乎所有查询都带时间范围过滤。
- 结构多变:不同设备上报的字段不一致,schema 经常需要灵活扩展。
- 查询混合:既要实时聚合看仪表盘,又要临时钻取查单条异常。
用 MySQL 写入跟不上,用 Elasticsearch 查询语法门槛高,用 MongoDB 做聚合写起来费劲。CrateDB 的思路是:底层用分布式存储和 Lucene 引擎(和 ES 同源),上层暴露标准 SQL,让开发者用熟悉的语法完成高吞吐写入和实时分析。
CrateDB 的核心能力
根据项目介绍,CrateDB 的几个关键点:
- 集群化摄取:最小集群即可每秒摄入数万条记录,数据分布到多个节点并行处理。
- 实时并行查询:数据写入后立即可查,查询在集群中并行执行,无需预先建索引或等批处理。
- NoSQL 级灵活性:支持动态列、嵌套对象、数组类型,schema 不用提前锁死。
- SQL 接口:
SELECT、JOIN、GROUP BY、窗口函数、地理空间查询都支持,对有 SQL 经验的开发者几乎没有学习曲线。
6.2.8 版本主要聚焦于稳定性修复,属于常规维护迭代。对于已经在生产环境跑 CrateDB 的团队,升级可以解决已知边界情况下的异常;对新用户来说,核心能力没有变化,选型依据仍然是上面这些特性。
实际上手:从部署到查询
下面用一个最小场景演示 CrateDB 的典型用法:采集设备温度数据,实时查询异常。
1. 用 Docker 快速拉起单节点
# 拉起 CrateDB 单节点,映射 HTTP 端口和 PostgreSQL 协议端口
docker run -d \
--name cratedb \
-p 4200:4200 \
-p 5432:5432 \
crate/crate:6.2.8
# 等几秒启动完成后,浏览器访问 http://localhost:4200 进入 Admin UI
# 或用 psql 协议连接:
psql -h localhost -p 5432 -U crate
CrateDB 同时支持 HTTP REST 和 PostgreSQL 协议,现有 PostgreSQL 客户端库可以直接对接。
2. 建表并写入数据
-- 建表:设备温度日志,带时间戳、设备 ID、温度值和动态标签
CREATE TABLE device_readings (
ts TIMESTAMP WITH TIME ZONE,
device_id TEXT,
temperature DOUBLE,
labels OBJECT(DYNAMIC), -- 动态嵌套对象,不同设备可以带不同字段
PRIMARY KEY (ts, device_id)
);
-- 批量插入模拟数据
INSERT INTO device_readings (ts, device_id, temperature, labels) VALUES
('2024-06-01T08:00:00Z', 'sensor-01', 23.5, {'location': 'floor-1', 'model': 'v2'}),
('2024-06-01T08:00:00Z', 'sensor-02', 78.2, {'location': 'floor-2', 'model': 'v1'}),
('2024-06-01T08:01:00Z', 'sensor-01', 24.1, {'location': 'floor-1', 'model': 'v2'}),
('2024-06-01T08:01:00Z', 'sensor-02', 81.0, {'location': 'floor-2', 'model': 'v1'});
OBJECT(DYNAMIC) 类型是 CrateDB 的灵活之处——不同设备可以塞进不同的标签字段,查询时直接用 labels['location'] 访问,不需要提前定义子列。
3. 实时查询:找出温度异常的设备
-- 查最近 1 小时温度超过 70°C 的设备,按设备聚合
SELECT
device_id,
COUNT(*) AS high_temp_count,
AVG(temperature) AS avg_temp,
labels['location'] AS location
FROM device_readings
WHERE ts >= NOW() - INTERVAL '1 hour'
AND temperature > 70
GROUP BY device_id, labels['location']
ORDER BY avg_temp DESC;
写入后立即可查,不需要等索引构建。这就是 CrateDB 宣称的"实时查询"在实际操作中的体现。
4. 用 Python 高速摄入
生产环境中数据通常由程序推送。以下是用 PostgreSQL 协议批量写入的示例:
import psycopg2
import time
import random
# CrateDB 兼容 PostgreSQL 协议,直接用 psycopg2
conn = psycopg2.connect(
host="localhost",
port=5432,
user="crate",
database="doc" # CrateDB 默认 schema 在 doc 数据库下
)
cur = conn.cursor()
# 模拟每秒批量摄入 1000 条设备读数
batch_size = 1000
device_ids = [f"sensor-{i:03d}" for i in range(50)]
def generate_batch():
rows = []
now = time.time()
for i in range(batch_size):
ts = time.strftime('%Y-%m-%dT%H:%M:%SZ', time.gmtime(now))
device_id = random.choice(device_ids)
temperature = random.uniform(20, 85)
location = f"floor-{random.randint(1,5)}"
rows.append((ts, device_id, temperature, {"location": location}))
return rows
# 执行批量插入
batch = generate_batch()
args_str = ",".join(
cur.mogrify("(%s,%s,%s,%s)", row).decode("utf-8")
for row in batch
)
cur.execute(f"INSERT INTO device_readings (ts, device_id, temperature, labels) VALUES {args_str}")
conn.commit()
print(f"Inserted {len(batch)} rows in one batch")
cur.close()
conn.close()
运行前确保
psycopg2已安装(pip install psycopg2-binary),且 CrateDB 容器正在运行。单节点仅供测试,生产摄入数万条/秒需要多节点集群分担写入压力。
选型考量:什么时候该看 CrateDB
CrateDB 不是万能替代,它的定位很明确:
适合的场景: - 机器数据(IoT、日志、指标、APM trace)的实时摄入和即时分析 - 数据结构半固定但有扩展需求(不同设备类型字段不同) - 团队熟悉 SQL,不想学新的查询 DSL - 需要时间序列聚合 + 地理空间过滤的混合查询
需要注意的边界: - 事务支持有限——CrateDB 不是为强一致性多表事务设计的,复杂业务逻辑还是交给 PostgreSQL - 超大规模集群(数百节点)的运维经验相对 Elasticsearch 生态更少,社区资源也更小 - 如果你的查询模式完全固定且不需要实时钻取,专用时序数据库(如 TimescaleDB、InfluxDB)可能在压缩率和存储成本上更优
升级 6.2.8 的建议: - 已在生产跑 CrateDB 的团队,关注官方 release notes 中的具体 bug 修复列表,评估是否命中你的场景 - 新用户直接用 6.2.8 部署即可,不需要先装旧版再升级
CrateDB 的价值在于把"高吞吐写入 + 灵活 schema + 实时 SQL 查询"打包成一个产品。如果你的数据是机器生成的、查询是即时且多样的,它值得花一个下午用 Docker 跑起来验证。