垂直分库与垂直分表详解
垂直分库:按业务域拆分
垂直分库是将一个单一的数据库实例按业务模块拆分为多个独立的数据库实例,每个数据库只负责一个业务域。
典型拆分方式
电商系统单体数据库
├── user 表(用户模块)
├── order 表(订单模块)
├── product 表(商品模块)
├── payment 表(支付模块)
├── coupon 表(营销模块)
└── message 表(通知模块)
拆分为:
user_db(用户库):user、user_address、user_login_log
order_db(订单库):order、order_item、return_request
product_db(商品库):product、product_sku、category
payment_db(支付库):payment、refund
marketing_db(营销库):coupon、activity
message_db(消息库):message、notification
为什么要垂直分库
-
业务解耦:不同业务模块可以独立开发、部署、扩展。订单系统的故障不会影响商品浏览。
-
资源隔离:每个数据库独享连接池和 IO 资源,避免相互干扰。秒杀活动对用户库的冲击不会影响订单写入。
-
独立扩容:订单库负载高时,可以单独升级订单库的硬件或增加只读副本。
-
数据安全与权限控制:不同团队管理不同的数据库,便于权限管控。
垂直分库带来的挑战
- 跨库查询:JOIN 操作无法跨库,需要应用层组合数据或采用代码级别的聚合
- 分布式事务:跨库的数据一致性需要 XA 或 TCC 等方案保障
- 跨库统计:报表统计需要汇总多个数据库的数据
// 跨库查询的应用层实现
User user = userDbQuery(userId);
List<Order> orders = orderDbQuery(userId);
// 应用层组装
UserVO vo = new UserVO(user, orders);
垂直分表:按字段拆分
垂直分表是将一个字段数较多的表按字段使用频率和数据类型拆分为多个结构不同的关联表。
拆分策略
拆分时将字段分为三组:
- 高频组:每次查询都需要的字段(小字段)
- 低频组:偶尔查询的字段
- 大字段组:TEXT/BLOB 等占用空间大的字段
-- 原始文章表
article(
id, title, summary, content TEXT,
cover_url, category_id, status,
author_id, view_count, comment_count,
seo_keywords, ext_meta VARCHAR(5000),
created_at, updated_at
)
-- 拆分后
-- 主表(高频字段)
article_main(id, title, summary,
category_id, status, author_id,
view_count, comment_count,
created_at, updated_at)
-- 内容表(大字段)
article_content(article_id, content, cover_url)
-- 扩展表(低频字段)
article_extra(article_id, seo_keywords, ext_meta)
为什么要垂直分表
- 减小单行大小:InnoDB 一页(16KB)能存放更多行,降低 IO 次数
- 冷热分离:高频访问的小字段在 buffer pool 中更密集,提高缓存命中率
- 避免 IO 放大:查询主表字段时不需要读取 content 等大字段所在的页面
一页 16KB 存 1 行(含 TEXT) vs 一页 16KB 存 100 行(仅 main 字段)
→ 查询 title 时,后者 buffer pool 命中率显著更高
垂直分表的挑战
- 需要额外的 JOIN 来获取完整数据
- 事务中更新多张表需要保证一致性
- 应用代码复杂度增加
垂直拆分的最佳实践
- 先分析业务和查询模式:梳理高频查询涉及的字段,避免拆分后查询反而需要关联多表
- 分表时使用相同的主键类型:确保关联查询效率
- 控制拆分粒度:不是表越细越好,2-3 张表通常已经足够
- 虚拟列或视图辅助:MySQL 的视图或虚拟列可以帮助简化应用层查询
- 结合读写分离:主表走主库,扩展表可以走从库
垂直拆分 vs 反范式化
垂直拆分是一种”范式化”操作——把原来宽表拆分成多个窄表。但有时候反其道而行之(适当的反范式化,将常用 Join 表合并)反而性能更好。需要根据实际查询模式权衡。
面试要点
- 垂直分库解决的是”业务耦合”和”资源共享”问题
- 垂直分表解决的是”单行太大”和”冷热数据混存”问题
- 两者的本质都是按”列”的维度切分(而非”行”)
- 垂直分库后的跨库事务是引入的最大复杂度
- 垂直分表时选择合适的主键关联策略很重要
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END


暂无评论内容