大家好,我是工藤学编程 | 一个正在努力学习的小博主,期待你的关注 |
---|---|
实战代码系列最新文章 | C++实现图书管理系统(Qt C++ GUI界面版) |
SpringBoot实战系列 | 【SpringBoot实战系列】Sharding-Jdbc实现分库分表到分布式ID生成器Snowflake自定义wrokId实战 |
环境搭建大集合 | 环境搭建大集合(持续更新) |
分库分表 | 分库分表之优缺点分析 |
前情摘要:
垂直分表是将单张大表按字段功能拆分为「主表」与「扩展表」,通过减少单次查询的IO数据量提升性能,尤其适用于以下场景:
三大拆分原则:
商品表拆分实例:
-- 拆分前(单表12字段,含4个大字段)
CREATE TABLE `product` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`title` varchar(524) DEFAULT NULL COMMENT '商品标题',
`cover_img` varchar(524) DEFAULT NULL COMMENT '封面图',
`price` int(11) DEFAULT NULL COMMENT '价格(分)',
`total` int(10) DEFAULT '0' COMMENT '总库存',
`left_num` int(10) DEFAULT '0' COMMENT '剩余库存',
`learn_base` text COMMENT '课前须知',
`learn_result` text COMMENT '学习目标',
`summary` varchar(1026) DEFAULT NULL COMMENT '商品概述',
`detail` text COMMENT '商品详情',
`create_time` datetime DEFAULT CURRENT_TIMESTAMP,
`update_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
-- 拆分后(主表6字段+扩展表6字段)
CREATE TABLE `product_main` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`title` varchar(524) DEFAULT NULL COMMENT '商品标题',
`cover_img` varchar(524) DEFAULT NULL COMMENT '封面图',
`price` int(11) DEFAULT NULL COMMENT '价格(分)',
`total` int(10) DEFAULT '0' COMMENT '总库存',
`left_num` int(10) DEFAULT '0' COMMENT '剩余库存',
`create_time` datetime DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
KEY `idx_price` (`price`),
KEY `idx_stock` (`left_num`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
CREATE TABLE `product_extend` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`product_id` int(11) NOT NULL COMMENT '主表ID',
`learn_base` text COMMENT '课前须知',
`learn_result` text COMMENT '学习目标',
`summary` varchar(1026) DEFAULT NULL COMMENT '商品概述',
`detail` text COMMENT '商品详情',
`update_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
UNIQUE KEY `uk_product_id` (`product_id`),
KEY `idx_update` (`update_time`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
垂直分库是按业务模块将数据拆分到不同数据库(如用户库、订单库、商品库),核心解决:
典型演进路径:
单体架构(单库) → 垂直分库(按业务拆库) → 微服务架构(库+服务解耦)
电商系统分库实例:
拆分前:
- 数据库:ecommerce_db(含用户、订单、商品表)
- 问题:订单高峰期写入导致商品查询超时,CPU利用率95%
拆分后:
- 用户库:user_db(用户表、会员表)
- 订单库:order_db(订单表、订单详情表)
- 商品库:product_db(商品主表、商品扩展表)
- 效果:各库CPU利用率降至40-60%,连接数利用率降低30%
垂直分库分表虽能提升并发与IO效率,但无法解决单表数据量过大的问题:
当单表数据量突破500万行时,索引效率大幅下降,全表扫描耗时从毫秒级飙升至秒级。水平分表通过将单表数据按规则拆分到N个结构相同的小表中,核心解决:
三大主流拆分策略:
策略类型 | 拆分逻辑 | 典型场景 | 实现复杂度 |
---|---|---|---|
RANGE范围拆分 | 按时间/ID范围分片(如order_2024 表存2024年订单) |
日志表、交易表等有时间特征的数据 | ★☆☆☆☆ |
HASH取模拆分 | 按字段哈希值取模(如user_id % 100 ) |
用户中心、订单表等需均匀分布的数据 | ★★☆☆☆ |
复合拆分 | 组合RANGE+HASH(如先按年分表,再按用户ID取模) | 大规模历史数据归档场景 | ★★★☆☆ |
当水平分表后单库仍面临资源瓶颈(如CPU利用率>90%、带宽跑满),需进一步水平分库,将数据分布到多个物理服务器,解决:
典型分库方案对比:
方案类型 | 拆分维度 | 部署实例 | 适用场景 |
---|---|---|---|
按业务分库 | 按模块拆分(如用户库、订单库) | 电商系统拆分为用户库+订单库+商品库 | 业务解耦优先,初期架构 |
按数据分库 | 按数据特征拆分(如用户ID取模分库) | 100个库,每个库存1%用户数据 | 高并发、海量数据场景 |
混合分库 | 先按业务分库,再按数据分表 | 订单库拆分为100个分库,每个库含10张分表 | 超大规模系统(如日活千万级应用) |
问题类型 | 具体表现 | 解决方案 |
---|---|---|
跨库Join查询 | 订单库与商品库分库后,无法直接JOIN | 1. 冗余字段(订单表冗余商品名称) 2. 应用层聚合(先查订单ID,再批量查商品) |
分布式事务 | 跨库更新时事务一致性问题 | 1. 最终一致性(消息队列补偿) 2. 强一致性(2PC/3PC协议) |
全局主键生成 | 分库后自增ID冲突 | 1. 雪花算法(64位唯一ID) 2. 分布式ID生成器(如百度UidGenerator) |
分页排序 | 跨库查询时LIMIT 1000,10 性能差 |
1. 前端限制分页深度 2. 二次查询优化(先查ID列表,再查详情) |