news 2026/4/15 13:29:14

MySQL 分区、分表、分库:从原理到生产实践

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
MySQL 分区、分表、分库:从原理到生产实践

目录

1、分库分表分区

1.1、联系

1.2、对比

2、分区(Partitioning)

2.1、介绍

2.2、核心原理

2.3、常见分区类型

2.4、分区管理命令

3、分表(Table Sharding)

3.1、介绍

3.2、使用原因

3.3、分片策略设计

3.4、MyBatis + 分表

4、分库(Database Sharding)

4.1、分库原因

4.2、分库分表组合模式

4.3、架构

5、最佳实践


前言

单机 MySQL 的瓶颈如下:

关于分库、分表和读写分离的架构图如下所示;


1、分库分表分区

1.1、联系

技术物理位置逻辑视图是否跨实例
分区(Partitioning)同一表、同一库、同一 MySQL 实例仍是一个表
分表(Table Sharding)多个表(如user_0,user_1),同一库应用需知道多个表
分库(Database Sharding)多个数据库(如db_0,db_1),可能跨 MySQL 实例应用需路由到不同库

核心思想

  • 分区:数据库内部优化
  • 分库分表:应用层或中间件实现的分布式架构

1.2、对比

能力分区分表分库
是否跨实例
应用是否感知❌(透明)✅(需拼表名)✅(需路由)
突破单机瓶颈❌(仍在单库)
支持跨分片查询✅(自动裁剪)❌(需中间件模拟)
扩容难度极高
典型工具MySQL 原生应用层ShardingSphere, Vitess

2、分区(Partitioning)

2.1、介绍

MySQL原生支持将一个大表的数据物理拆分到多个“分区”中,但逻辑上仍是一个表,数据库内置能力。

开发人员在数据操作时仍然是对这个整体大表进行操作,之后由数据库底层内部去寻找对应的分区进行操作,这样在数据操作时可以只对特定分区操作以提高效率,存储时也可以将不同分区的物理文件分开存放。

2.2、核心原理

  • 物理存储分离:每个分区是一个独立.ibd文件
  • 逻辑视图统一:应用仍操作一个表名
  • 查询自动裁剪:优化器只扫描相关分区

2.3、常见分区类型

1.RANGE 分区(按范围)

如下所示:

-- 按年份分区 CREATE TABLE sales ( id BIGINT, sale_date DATE, amount DECIMAL(10,2) ) PARTITION BY RANGE (YEAR(sale_date)) ( PARTITION p2022 VALUES LESS THAN (2023), PARTITION p2023 VALUES LESS THAN (2024), PARTITION p2024 VALUES LESS THAN (2025), PARTITION p_future VALUES LESS THAN MAXVALUE ); -- 查询自动裁剪 EXPLAIN SELECT * FROM sales WHERE sale_date = '2023-06-01'; -- 只扫描 p2023 分区

(2) LIST 分区(按枚举值)

如下所示:

-- 按地区分区 CREATE TABLE users ( id BIGINT, region VARCHAR(10) ) PARTITION BY LIST COLUMNS(region) ( PARTITION p_north VALUES IN ('BJ', 'TJ'), PARTITION p_south VALUES IN ('GZ', 'SZ'), PARTITION p_west VALUES IN ('CD', 'XA') );

(3) HASH 分区(均匀分布)

如下所示:

-- 按 user_id 均匀分布到 4 个分区 CREATE TABLE orders ( id BIGINT, user_id BIGINT ) PARTITION BY HASH(user_id) PARTITIONS 4;

(4) KEY 分区(类似 HASH,支持多列)

如下所示:

PARTITION BY KEY(user_id, order_type) PARTITIONS 8;

2.4、分区管理命令

-- 添加新分区 ALTER TABLE sales ADD PARTITION ( PARTITION p2025 VALUES LESS THAN (2026) ); -- 删除旧分区(秒级!) ALTER TABLE sales DROP PARTITION p2022; -- 重建分区(整理碎片) ALTER TABLE sales REBUILD PARTITION p2023;

✅ 优点

  • 对应用透明:SQL 不用改,SELECT * FROM logs WHERE create_time > '2024-01-01'自动只查p2024

  • 提升查询性能:分区裁剪(Partition Pruning)

  • 方便数据管理ALTER TABLE logs DROP PARTITION p2023;快速删除旧数据

❌ 缺点

  • 仍在单机:无法突破单 MySQL 实例的 CPU/内存/磁盘瓶颈

  • 分区数有限:通常建议 < 100 个分区

  • 不支持所有引擎:仅 InnoDB、MyISAM 支持

📌 适用场景

  • 单表过大(> 1000万行),但总数据量未超单机容量

  • 按时间冷热分离(如日志、订单)

  • 需要快速删除历史数据


3、分表(Table Sharding)

3.1、介绍

将一张大表拆成多张结构相同的表,应用层拆分。

如下所示:

3.2、使用原因

为什么需要分表?

  • InnoDB 单表建议 < 5000万行(B+树深度增加)

  • 表锁/元数据锁竞争(DDL 操作阻塞)

如:

  • user_0, user_1, user_2, user_3

如何路由?

通常用分片键(Shard Key) + 取模/哈希决定数据存哪张表。

如下所示:

示例:按 user_id 分 4 张表

// Java 伪代码 public String getTableName(Long userId) { int tableIndex = (int) (userId % 4); return "user_" + tableIndex; } // 查询用户 String sql = "SELECT * FROM " + getTableName(userId) + " WHERE id = ?";

3.3、分片策略设计

1.分片键选择

字段优点缺点
user_id用户数据聚集热点用户问题
order_id均匀分布无法按用户查订单
tenant_id多租户隔离租户数据不均

最佳实践:选高频查询字段作为分片键

2.分片算法

// 取模(简单但扩容难) int tableIndex = userId % tableCount; // 一致性哈希(扩容友好) HashFunction hash = Hashing.murmur3_32(); int bucket = hash.hashLong(userId).asInt() & Integer.MAX_VALUE; int tableIndex = bucket % tableCount;

3.4、MyBatis + 分表

步骤 1:定义分表路由

@Component public class TableShardingRouter { private static final int TABLE_COUNT = 4; public String getTableName(String baseName, Long shardKey) { int index = (int) (shardKey % TABLE_COUNT); return baseName + "_" + index; } }

步骤 2:MyBatis 动态表名

<!-- UserMapper.xml --> <select id="selectById" resultType="User"> SELECT * FROM ${tableName} WHERE id = #{id} </select>

步骤 3:Service 层调用

@Service public class UserService { @Autowired private TableShardingRouter router; @Autowired private UserMapper userMapper; public User getUser(Long userId) { String tableName = router.getTableName("user", userId); return userMapper.selectById(tableName, userId); } }

优点

  • 突破单表性能瓶颈(InnoDB 单表建议 < 5000万行)

  • 实现简单,无需中间件

缺点

  • 应用强耦合:每个 SQL 都要拼表名;

  • 无法跨表 JOIN / 聚合:select count(*) from user_* 需查 4 次再 sum;

  • 扩容困难:从 4 表扩到 8 表,需迁移一半数据;

适用场景

  • 单库能扛住,但单表太大

  • 查询基本都带分片键(如 where user_id = ?)


4、分库(Database Sharding)

4.1、分库原因

为什么需要分库?

  • 单机资源耗尽(CPU/内存/IO)

  • 连接数瓶颈(max_connections

  • 多租户数据隔离需求

4.2、分库分表组合模式

模式 1:库内分表(推荐)

  • 4 个库 × 每库 16 张表 = 64 分片

  • 优点:减少数据库连接数

模式 2:仅分库

  • 4 个库 × 每库 1 张表

  • 优点:简化表结构

📊计算公式

总分片数 = 库数量 × 表数量;

分片ID = hash(shard_key) % 总分片数;
库名 = 分片ID / 表数量;

表名 = 分片ID % 表数量

4.3、架构

如下所示:

是什么?

将数据分散到多个数据库实例(可能在不同机器),真正的分布式。

如:

  • db_0(IP: 10.0.0.1)

  • db_1(IP: 10.0.0.2)

通常分库 + 分表一起用,如:

  • db_0.user_0, db_0.user_1

  • db_1.user_0, db_1.user_1

架构图

Application

├── Router (ShardingSphere / MyCat / 自研)
│ │
│ ├── db_0 (10.0.0.1)
│ │ ├── user_0
│ │ └── user_1
│ │
│ └── db_1 (10.0.0.2)
│ ├── user_0
│ └── user_1

优点

  • 水平扩展:突破单机资源限制(CPU/内存/连接数)

  • 高可用:一个库挂了,其他库仍可用

  • 隔离性:租户/业务线数据物理隔离

缺点

  • 复杂度飙升

    • 跨库事务(需 Seata/TCC)

    • 跨库 JOIN(需应用层聚合)

    • 全局 ID(需 Snowflake/Leaf)

  • 运维成本高:备份、监控、扩容都变复杂

适用场景

  • 海量数据(> 1TB)

  • 超高并发(> 1万 QPS)

  • 多租户 SaaS 系统


5、最佳实践

1.不要过早分库分表→ 先优化 SQL、加索引、读写分离、缓存

2.分片键至关重要→ 选高频查询字段(如 user_id),避免热点

3.避免跨分片操作→ 设计时让关联数据落在同分片(如订单 & 订单项都按 user_id 分)

4.全局 ID 必须趋势递增→ 避免 UUID 导致 InnoDB 性能下降;


总结

结论:

分区是“治标”,分库分表是“治本”。90% 的系统,用好分区 + 读写分离 + 缓存就足够了;
只有真正遇到单机瓶颈,才考虑分库分表。


参考文章:

1、【MySQL】之分区、分库、分表

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/13 23:32:31

Dify平台能否用于股票分析?量化交易信号生成尝试

Dify平台能否用于股票分析&#xff1f;量化交易信号生成尝试 在金融市场的激烈博弈中&#xff0c;信息的处理速度与决策质量直接决定了投资成败。传统量化交易依赖于严密的数学模型和复杂的编程实现&#xff0c;虽然高效但门槛极高——不仅要求开发者精通Python、熟悉Pandas与T…

作者头像 李华
网站建设 2026/3/30 18:59:45

Dify如何支持多模态输入?图像+文本联合处理路径

Dify如何支持多模态输入&#xff1f;图像文本联合处理路径 在今天的AI应用开发中&#xff0c;一个越来越常见的场景是&#xff1a;用户上传一张图片&#xff0c;然后问“这是什么&#xff1f;”、“哪里出了问题&#xff1f;”或者“请根据这张图写一段说明”。这类需求早已超越…

作者头像 李华
网站建设 2026/4/14 0:19:30

面向工厂产线的CCS安装项目应用详解

工厂产线的CCS安装实战&#xff1a;从系统架构到现场调试&#xff0c;一文讲透 在一家汽车焊装车间里&#xff0c;一条自动化产线突然停机——机器人动作错乱、PLC通信中断、HMI画面上满屏报警。维修团队花了整整6小时才定位问题&#xff1a;原来是中央控制系统&#xff08;CCS…

作者头像 李华
网站建设 2026/4/14 21:31:19

R语言数组与矩阵的复制与赋值

在R语言编程中,数组和矩阵的操作是常见且复杂的任务之一。尤其是当涉及到复制矩阵到数组的不同索引时,可能会遇到一些不易察觉的问题。本文将通过一个具体的实例,详细解释如何正确地在R中进行数组与矩阵的复制和赋值操作。 问题背景 假设我们有一个三维数组test_array和一…

作者头像 李华
网站建设 2026/4/11 1:46:34

Dify如何平衡灵活性与易用性?产品设计理念解读

Dify如何平衡灵活性与易用性&#xff1f;产品设计理念解读 在AI技术快速渗透各行各业的今天&#xff0c;大语言模型&#xff08;LLM&#xff09;早已不再是实验室里的“黑科技”&#xff0c;而是企业构建智能客服、自动化内容生成、知识问答系统的核心引擎。然而&#xff0c;一…

作者头像 李华
网站建设 2026/4/14 12:03:59

Java Web 教学资源共享平台系统源码-SpringBoot2+Vue3+MyBatis-Plus+MySQL8.0【含文档】

摘要 随着信息技术的快速发展&#xff0c;教育资源共享平台成为高校信息化建设的重要组成部分。传统教学资源管理方式存在资源分散、共享效率低、更新不及时等问题&#xff0c;难以满足师生多样化需求。基于此&#xff0c;设计并实现一个高效、便捷的教学资源共享平台具有重要的…

作者头像 李华