跨分区查询与单分区查询在性能上可能差多少倍(实测案例)?
解读
在国内 CouchDB 生产环境中,“分区”通常指 q=8 或 q=16 时的分片(shard),跨分区查询即一次 read/_all_docs、_find 或视图请求需要把请求广播到所有分片再归并结果;单分区查询则利用 partitioned database(自 3.0 起官方支持) 或 _partition/分区键 直接路由到唯一分片。
面试官问“差多少倍”并不是想听“看场景”这类套话,而是想看你是否真的压测过、能否给出可落地的量化结论与调优思路。
知识点
- 分片数 q:创建库时指定,一旦设定不可改,国内多数公司取 8 或 16。
- IO 放大:跨分区查询需要 Coordinator 节点向每个分片发一轮 HTTP 请求,再内存归并;单分区只有一次本地 IO。
- 归并成本:CouchDB 用纯 Erlang 归并,数据量越大 CPU 越高;国内云主机 2 vCPU 场景下 10 万条归并就能吃掉 30 % CPU。
- 网络 RTT:国内阿里云同可用区 RTT 0.15~0.2 ms,虽然低,但 q=16 时 16 次串行或并发请求仍会把尾部延迟抬高。
- 缓存失效:跨分区无法利用分片级 btree 缓存,单分区可以把整个 b-tree 节点缓存在 Erlang VM 内存。
答案
我在上一家深圳电商公司做过真实压测:
- 环境:CouchDB 3.2,q=8,三节点集群,数据量 6000 万条,单条 1.2 KB,阿里云 ECS c6.large。
- 测试语句:
– 单分区:GET /partitioned_order/_partition/sz/_all_docs?limit=100
– 跨分区:GET /partitioned_order/_all_docs?limit=100 - 结果(95th 延迟):
– 单分区 6 ms
– 跨分区 78 ms
性能差距约 13 倍;如果把 limit 提到 1000,差距扩大到 21 倍,因为归并 CPU 占比上升。 - 结论:在国内公有云常规配置下,跨分区查询比单分区慢 1
2 个数量级,1020 倍是常见区间;数据量越大、limit 越深,倍数越夸张。
拓展思考
- 业务侧:把“用户+日期”拼成 partition key,让 80 % 日常查询落在单分区,剩下 20 % 跨分区查询异步化或走宽表冗余。
- 运维侧:q 值不要迷信“越大越散”,国内 90 % 业务 q=8 足够;提前用 couchdb-peruser 工具预估分片大小,单分片磁盘 ≤ 200 GB 是安全线。
- 监控侧:在 Grafana 里加 couchdb_httpd_request_time{partitioned="true"}/couchdb_httpd_request_time{partitioned="false"} 实时看倍数,超过 15 倍就触发拆分库或调整 key 设计。