docdb 是 yugabytedb 底层分布式键值存储,不对外暴露 api;应用必须通过 ysql(postgresql 兼容)或 ycql(cassandra 风格)交互,选型应基于事务需求、join 依赖及生态适配,而非误信“直连 docdb 更快”。

DocDB 是底层存储引擎,不是你该直接调用的 API
YugabyteDB 的 DocDB 是分布式键值存储层,负责数据分片、复制和一致性;它不暴露给应用开发者,docdb 也不是你写 SQL 或应用代码时能接触到的接口。所有客户端交互都走上层 API:YSQL(PostgreSQL 兼容)、YCQL(Cassandra 风格)或可选的 Redis 兼容层。误以为“用 DocDB 就更快”是常见误区——你根本没法绕过 YSQL/YCQL 去直连 DocDB。
实操建议:
- 别在应用里搜
docdb_connect或尝试调用docdb_client:这些不存在于公开 SDK 中 - 性能优化应聚焦在 YSQL 的索引设计、YCQL 的分区键选择,而非“切换到 DocDB”
- 运维监控里看到
docdb相关指标(如docdb_op_latency)只用于排查底层延迟,不用于应用逻辑
YSQL vs YCQL:选型取决于你是否需要 JOIN、事务语义和现有生态
YSQL 是 PostgreSQL 协议兼容层,支持完整 SQL:外键、视图、存储过程、JOIN、可串行化隔离级别;YCQL 是类 Cassandra 的查询语言,主打宽列模型、强最终一致性、无 JOIN、轻量级事务(LWT),适合高吞吐写入与按主键/分区键查。
常见错误现象:
- 用 YCQL 写
SELECT * FROM users WHERE status = 'active'(没指定分区键)→ 全表扫描,超时或被拒绝 - 在 YSQL 中建了 50 个
FOREIGN KEY约束,但业务实际从不跨表更新 → 白增事务开销,没带来数据一致性收益 - 把 YCQL 当作“轻量版 PostgreSQL”用,硬套关系模型 → 查询变慢、schema 变得难维护
实操建议:
- 已有 PostgreSQL 应用或依赖 ORM(如 Django、Hibernate)→ 优先试
ysqlsh连接,90% 场景无需改代码 - 写多读少、设备上报/日志类场景、已用 Cassandra 生态(如 DataStax driver)→ 选
ycqlsh,用CREATE TABLE ... PRIMARY KEY ((tenant_id), event_time)明确分区 - 混合需求(比如要 JOIN + 高并发写)?先压测 YSQL:它在 2.15+ 版本已支持并行查询和批量插入优化,未必比 YCQL 慢
YSQL 的 pg_stat_statements 不默认开启,但它是定位慢查询的第一工具
很多人上线后发现查询变慢,却在 YSQL 里执行 SELECT * FROM pg_stat_statements 报错:relation "pg_stat_statements" does not exist。这不是 bug,而是扩展未启用。
实操建议:
- 连接
ysqlsh后,先运行CREATE EXTENSION IF NOT EXISTS pg_stat_statements - 该扩展会增加少量内存开销(默认采样 1000 条最耗时语句),但能直接看到
total_exec_time和mean_exec_time - 注意:YCQL 没有等价机制,慢查询只能靠
yb-admin查 tablet 日志或开启--rpc_dump_interval_sec - 别依赖
EXPLAIN ANALYZE单次结果:分布式执行计划中,Nested Loop在 YSQL 里可能触发跨节点拉取,实际耗时远高于本地估算
YCQL 的 lightweight transaction(LWT)有明确限制,不是通用乐观锁
YCQL 支持 IF EXISTS / IF NOT EXISTS 和条件更新(UPDATE ... IF col = value),但背后是 Paxos 协议协调,每次 LWT 至少 2 轮 RPC,且不能用于集合类型(SET, LIST)的原子更新。
常见错误现象:
- 在高频计数场景用
UPDATE counters SET val = val + 1 IF val >= 0→ QPS 上不去,大量失败重试 - 以为 LWT 能替代应用层分布式锁 → 实际在高冲突下,成功率骤降,且无法设置超时
实操建议:
- 仅对低频、关键状态变更(如“用户订单从 pending → paid”)用 LWT
- 高频计数/累加 → 改用 YSQL 的
SEQUENCE或INSERT ... ON CONFLICT DO UPDATE - 需要锁语义 → 外接 Redis 或用 YSQL 的
SELECT ... FOR UPDATE(需在可串行化事务内)
真正卡住选型的,往往不是语法差异,而是事务边界怎么划:YSQL 里一个 BEGIN; UPDATE; INSERT; COMMIT; 是强一致的,YCQL 里三个独立语句就是三个独立的最终一致操作——这点一旦想错,后面所有优化都是徒劳。










