不同写入协议的性能差距可达 50 倍。这篇文章用 benchmark 数据帮你选对。
GreptimeDB 支持十几种写入协议,社区里被问得最多的问题就是:该用哪个?
能找到的零散数据不少,但测试条件各不相同,没法直接对比。所以我做了一个开源 benchmark 工具 greptimedb-ingestion-benchmark,把几种最常用的协议放在完全相同的条件下跑了一遍。这篇文章分享结果和选型建议。
测了哪些协议
从众多写入方式中挑了三类:
GreptimeDB gRPC 协议,通过官方 SDK 使用,有三种写入模式:
| 写入模式 | 说明 |
|---|---|
| gRPC SDK (Unary) | 每批次一次 RPC 调用,最简单 |
| gRPC Stream | 双向流复用连接,适合高频、持续高吞吐 |
| gRPC Bulk (Arrow) | Arrow Flight DoPut 列式传输,吞吐最高 |
开放标准协议:InfluxDB Line Protocol(HTTP 文本格式)和 OTLP Logs(HTTP + Protobuf)。
SQL 协议:MySQL INSERT 和 PostgreSQL INSERT。
这里 OTLP 测的是 Logs 而不是 Metrics。原因是 GreptimeDB 的 OTLP 数据模型中,Metrics 会把每个 metric name 映射为独立的表。本次 benchmark 有 5 个指标字段,Metrics 模型会拆成 5 张表,没法和其他协议公平对比。Logs 模型把所有字段写入同一张表,测试条件一致。
关于 Schemaless(自动建表):gRPC SDK、gRPC Stream、InfluxDB LP、OTLP 都支持写入时自动建表[1],新字段直接写,GreptimeDB 自动加列。SQL INSERT 和 gRPC Bulk (Arrow) 需要提前建表。SQL 是因为 INSERT INTO 依赖已有表结构,Arrow Bulk 是因为 DoPut 接口需要目标表已存在来做列映射。数据结构不固定的场景(IoT 设备字段变化、LLM 对话数据等),优先选支持 Schemaless 的协议。
测试条件
1000 万行,100 万个时间序列(1000 台主机 × 5 region × 10 datacenter × 20 service),每行 5 个 float64 指标字段,固定随机种子(seed=42)。每种协议写入独立表,5 并发 worker,SDK 全部默认配置。
测试环境:MacBook Pro 14-inch(M4 Max, 48 GB),GreptimeDB standalone 模式。这是单机测试,目的是比较协议间的相对差异,不是测绝对吞吐上限。生产环境分布式集群的绝对数值会更高,但协议间的排序一致。完整方法论见仓库 README。
结果
batch=1000,100 万 series
100 万时间序列接近真实生产环境的基数,batch=1000 是大多数场景的合理默认值。
| 协议 | 吞吐 (rows/sec) | 耗时 | P50 延迟 | P99 延迟 |
|---|---|---|---|---|
| gRPC Bulk (Arrow) | 2,010,017 | 5.0 秒 | 1.7 ms | 8.6 ms |
| gRPC Stream | 1,446,508 | 6.9 秒 | 2.6 ms | 9.7 ms |
| gRPC SDK | 1,189,277 | 8.4 秒 | 3.6 ms | 9.4 ms |
| OTLP Logs (HTTP) | 1,046,518 | 9.6 秒 | 4.6 ms | 8.1 ms |
| InfluxDB LP | 985,409 | 10.2 秒 | 4.2 ms | 10.5 ms |
| MySQL INSERT | 68,987 | 145.0 秒 | 68.0 ms | 147.3 ms |
| PostgreSQL INSERT | 36,300 | 275.5 秒 | 134.6 ms | 202.9 ms |

gRPC 三种模式在 120-200 万/秒这个区间,HTTP 协议(OTLP Logs 和 InfluxDB LP)在 100 万/秒左右,SQL 在 3.6-6.9 万/秒。最快和最慢差了将近 55 倍。
OTLP Logs 吞吐略高于 InfluxDB LP,这不是协议本身的差距。OTLP Logs 表默认 append_mode = 'true',不把 host、region 这些业务维度作为主键(这些维度存在 log_attributes JSON 列里),100 万 series 下主键维护代价对它没影响,其他协议的表则需要维护大量主键。后面"时间序列基数的影响"一节有更详细的分析。
SQL 的结果需要多说一句:本次测试的连接池大小和并发数都只有 5,这是 benchmark 统一的配置。实际使用中,通过增大连接池和并发数可以提升 SQL 写入吞吐,但这不在本次测试的覆盖范围内。这里的数据反映的是相同并发条件下各协议的相对表现。
低基数参考:batch=1000,10 万 series
时间序列较少的场景(几百台主机的监控之类),吞吐会明显更高:
| 协议 | 吞吐 (rows/sec) | P50 延迟 | P99 延迟 |
|---|---|---|---|
| gRPC Bulk (Arrow) | 2,978,357 | 1.5 ms | 5.3 ms |
| gRPC Stream | 1,890,927 | 2.5 ms | 6.9 ms |
| gRPC SDK | 1,423,277 | 3.4 ms | 6.6 ms |
| InfluxDB LP | 1,177,155 | 4.1 ms | 7.0 ms |
| OTLP Logs (HTTP) | 985,826 | 4.5 ms | 13.5 ms |
| MySQL INSERT | 73,682 | 65.2 ms | 122.9 ms |
| PostgreSQL INSERT | 43,762 | 112.4 ms | 149.8 ms |
低基数下 gRPC Bulk 可以跑到接近 300 万/秒,各协议普遍提升 20-50%。注意这组数据里 InfluxDB LP 排在 OTLP Logs 前面了,10 万 series 下索引压力小,append-only 的优势不再明显。
批次大小的影响
4 种批次大小(50 / 200 / 1000 / 2000),100 万 series:
| 协议 | batch=50 | batch=200 | batch=1000 | batch=2000 |
|---|---|---|---|---|
| gRPC Bulk (Arrow) | 1,141,828 | 1,605,752 | 2,010,017 | 2,059,978 |
| gRPC Stream | 903,437 | 1,201,400 | 1,446,508 | 1,559,845 |
| gRPC SDK | 780,298 | 1,044,454 | 1,189,277 | 1,114,197 |
| InfluxDB LP | 723,982 | 924,198 | 985,409 | 1,078,624 |
| OTLP Logs (HTTP) | 685,865 | 896,434 | 1,046,518 | 1,065,914 |
| MySQL INSERT | 65,662 | 67,240 | 68,987 | 70,324 |
| PostgreSQL INSERT | 37,962 | 33,611 | 36,300 | 40,731 |

gRPC 系列对批次大小很敏感。Bulk 从 batch=50 的 114 万提升到 batch=2000 的 206 万,接近翻倍,更大的批次意味着更少的 RPC 调用和更高效的列式编码。不过 gRPC SDK 在 batch=2000 时反而小幅回落(111 万 vs batch=1000 的 119 万),Unary 模式下过大的请求体有额外序列化开销。
InfluxDB LP 从 72 万到 108 万(+49%),HTTP 请求-响应模型限制了上限。
SQL 几乎没变化。MySQL 从 6.6 万到 7 万,瓶颈在 SQL 文本解析和同步连接模型,batch 大小影响不大。
时间序列基数的影响
10 万 vs 100 万 series,batch=1000:
| 协议 | 10 万 series | 100 万 series | 差异 |
|---|---|---|---|
| gRPC Bulk (Arrow) | 2,978,357 | 2,010,017 | -32% |
| gRPC Stream | 1,890,927 | 1,446,508 | -24% |
| gRPC SDK | 1,423,277 | 1,189,277 | -16% |
| InfluxDB LP | 1,177,155 | 985,409 | -16% |
| OTLP Logs (HTTP) | 985,826 | 1,046,518 | +6% |

更多时间序列意味着更多 Memtable 写入和主键维护开销。gRPC Bulk 绝对吞吐最高,瓶颈转移到 Memtable 时下降最明显(-32%)。针对超高基数场景,GreptimeDB 专门设计了 flat 格式,写入吞吐提升 4 倍,查询性能提升最高 10 倍。
OTLP Logs 不降反升。它的表默认 append_mode = 'true',只有 scope_name 作 Primary Key,host/region 等维度存在 log_attributes JSON 列里不参与主键。series 基数对它没意义。这是 append-only 模式的特点:写入快,后续可以按需对特定字段建索引。
为什么差距这么大
gRPC 快在编码效率。Protocol Buffers 二进制格式,体积小,解析快。三种模式的区别在于连接模型:SDK 每批次独立 RPC;Stream 用双向流复用连接,省掉连接协商开销,吞吐比 Unary 高约 20-30%;Bulk 走 Arrow Flight 协议[2]做列式传输,GreptimeDB 内部也用 Arrow 做内存格式,写入接近 zero-copy,所以能到 200 万/秒。代价是需要提前建表。
InfluxDB LP 和 OTLP 都走 HTTP,每个批次一个完整的请求-响应周期,这是它们的天花板。InfluxDB LP 用文本格式,小批次时文本解析开销更明显,大批次时和 OTLP 的 Protobuf 差距收窄。
SQL 慢有两层原因。第一是处理路径长:客户端拼 INSERT INTO ... VALUES (...) 文本,服务端解析 SQL,逐行做类型转换,再写入,每一步都有开销,文本体积也远大于二进制格式。第二是并发模型的限制:MySQL 和 PostgreSQL 协议都是同步连接模型,一个连接同一时间只能处理一条语句,并发能力受连接数限制,跟 gRPC 的异步流式模型差距很大。这不是 GreptimeDB 特有的问题,任何通过 SQL 协议写入的时序数据库 (Time Series Database) 都面临同样的开销。
怎么选
大多数场景用 gRPC SDK。 约 120 万 rows/sec,代码简单,支持 Schemaless,我们的官方 SDK 覆盖 Go、Java、Rust、Erlang、.NET。没有特殊需求的话,这是最稳妥的起点。如果技术栈是 JS/TS(目前没有 gRPC 的 JS 客户端),用 InfluxDB LP 或 OTLP 替代,它们有成熟的 JS 库,性能也在百万级。
批量导入用 gRPC Bulk。 数据迁移、历史回填、ETL 场景。200 万 rows/sec,1000 万行 5 秒写完。需要提前建好表。Erlang SDK 暂不支持这个模式。
高频或持续高吞吐用 gRPC Stream。 IoT 网关、监控采集器这种长时间不间断写入的场景,或者写入频率很高、每次数据量不大但频次密集的场景。双向流复用连接避免了反复建连的开销,吞吐 120-150 万 rows/sec,支持 Schemaless。
已有 InfluxDB 生态就用 InfluxDB Line Protocol。 在跑 Telegraf,或者应用已经输出 Line Protocol?直接接 GreptimeDB 的兼容接口,约 99 万 rows/sec,迁移成本接近零。
已有 OTel 生态就用 OTLP。 在用 OpenTelemetry Collector 或 OTel SDK?OTLP 约 105 万 rows/sec,支持 Schemaless。Metrics 和 Logs 的数据模型不同[3]:Metrics 按 metric name 分表,适合 Prometheus 式监控;Logs 写入统一的日志表,适合结构灵活的数据。根据实际数据模型选。
开发调试用 MySQL / PostgreSQL。 写入吞吐低,但 mysql、psql 命令行、DBeaver、各种 ORM 和语言驱动都能直接连。不支持 Schemaless,需先建表。写入慢不代表查询慢,MySQL/PG 协议是 GreptimeDB 查询的主要接口。
速查表
| gRPC SDK | gRPC Stream | gRPC Bulk | InfluxDB LP | OTLP | MySQL/PG | |
|---|---|---|---|---|---|---|
| 吞吐 | 119 万/s | 145 万/s | 201 万/s | 99 万/s | 105 万/s | 3.6-6.9 万/s |
| Schemaless | ✅ | ✅ | ❌ 需建表 | ✅ | ✅ | ❌ 需建表 |
| 传输格式 | Protobuf | Protobuf | Arrow IPC | 文本 | Protobuf | SQL 文本 |
| SDK 覆盖 | Go/Java/Rust/Erlang/.NET | 同左 | 同左(Erlang 除外) | 各语言 | 各语言 | 各语言 |
| 场景 | 通用默认 | 高频/持续写入 | 批量导入 | InfluxDB 迁移 | OTel 生态 | 查询和调试 |
一句话总结:性能敏感选 gRPC(SDK 起步,需要更高吞吐再上 Stream 或 Bulk),已有生态选对应的兼容协议(InfluxDB LP / OTLP),SQL 用来查询和调试。
自己跑一遍
git clone https://github.com/killme2008/greptimedb-ingestion-benchmark.git
cd greptimedb-ingestion-benchmark
bin/run.sh脚本自动下载 GreptimeDB、启动、跑完全部协议、输出结果。支持自定义:
bin/run.sh -protocols grpc,grpc_bulk,influxdb -batch-size 500,1000,2000
bin/run.sh -host 10.0.0.1 # 连接远程实例测试结果和这里的有差异?或者在特定场景下有不同发现?欢迎到 GitHub Discussion 或 Slack 聊聊。



