MySQL实现数据库分表(水平、垂直、分区表)详细操作步骤

 更新时间:2026年07月09日 10:24:05   作者:繁星蓝雨  
MySQL分区表是一种将大表数据按特定规则拆分成多个独立存储单元的技术,能有效提升大数据量下的查询性能和管理效率,这篇文章主要介绍了MySQL实现数据库分表(水平、垂直、分区表)详细操作的相关资料,需要的朋友可以参考下

0 背景

因为数据库库的表数据量过大以及字段过多,产生了分表的想法。搜索网上资料后,得知有三种分表方式,最终结合其中的方式,实现了最终的分表效果。

1 理论

1.1 定义与区别

水平分表(水平拆分/水平分片)

  • 定义:将一张表按照进行拆分,将不同的行数据分散到多个表中
  • 特点:拆分后表结构相同,数据按规则分布在不同表中
  • 核心:按记录(行)维度拆分,数据分布为"同结构不同行"

垂直分表(垂直拆分/垂直分片)

  • 定义:将一张表按照进行拆分,将不同的列拆分到不同的表中
  • 特点:拆分后表结构不同,数据按功能或使用频率分布
  • 核心:按字段(列)维度拆分,数据分布为"不同结构同数据"

分区表(分区)

  • 定义:将一张表按照某种规则(时间、哈希等)进行分区,物理上分离但逻辑上统一
  • 特点:数据库系统内部实现,对应用层透明
  • 核心:数据库内部物理存储机制,通常由数据库引擎自动管理

1.2 详细对比

特性水平分表垂直分表分区表
拆分维度按行(记录)按列(字段)按规则(行或列)
表结构拆分后结构相同拆分后结构不同逻辑结构相同,物理分离
数据分布不同表存储同类型的不同记录不同表存储不同类型的字段物理上分离,逻辑上统一
对应用层影响需要应用层处理跨表查询需要应用层处理多表查询通常对应用层透明
适用场景单表数据量过大(千万级+)表字段过多、存在大字段数据量大、需高效管理
优点降低单表压力,提高扩展性降低单表字段数量,提升查询效率提升性能,简化数据管理
缺点复杂性增加,事务管理复杂跨表查询复杂,数据冗余实施复杂,内存使用可能增加
与分片关系水平分片的一种实现方式垂直分片的一种实现方式数据分片的一种实现方式

2 实践

2.1 水平分表

将一张表按行拆分成多张结构相同的表,解决单表数据量过大的问题。

2.1.1 按哈希取模分表

  1. 创建表;
-- 创建4个分表(实际应用中可以使用程序动态创建)
CREATE TABLE orders_0 (
    order_id INT PRIMARY KEY,
    user_id INT,
    amount DECIMAL(10,2),
    create_time DATETIME
) ENGINE=InnoDB;

CREATE TABLE orders_1 (
    order_id INT PRIMARY KEY,
    user_id INT,
    amount DECIMAL(10,2),
    create_time DATETIME
) ENGINE=InnoDB;

CREATE TABLE orders_2 (
    order_id INT PRIMARY KEY,
    user_id INT,
    amount DECIMAL(10,2),
    create_time DATETIME
) ENGINE=InnoDB;

CREATE TABLE orders_3 (
    order_id INT PRIMARY KEY,
    user_id INT,
    amount DECIMAL(10,2),
    create_time DATETIME
) ENGINE=InnoDB;
  1. 插入数据(因为user_id12345 % 4 = 1,故插入到orders_1表中);
- 插入数据示例:user_id=12345会插入到orders_1表(12345 % 4 = 1)
INSERT INTO orders_1 (order_id, user_id, amount, create_time) 
VALUES (1001, 12345, 200.00, NOW());

2.1.2 按时间范围分表

1.创建表;

-- 创建按月份分表
CREATE TABLE orders_202301 (
    order_id INT PRIMARY KEY,
    user_id INT,
    amount DECIMAL(10,2),
    create_time DATETIME
) ENGINE=InnoDB;

CREATE TABLE orders_202302 (
    order_id INT PRIMARY KEY,
    user_id INT,
    amount DECIMAL(10,2),
    create_time DATETIME
) ENGINE=InnoDB;
  1. 插入数据;
-- 创建按月份分表
CREATE TABLE orders_202301 (
    order_id INT PRIMARY KEY,
    user_id INT,
    amount DECIMAL(10,2),
    create_time DATETIME
) ENGINE=InnoDB;

CREATE TABLE orders_202302 (
    order_id INT PRIMARY KEY,
    user_id INT,
    amount DECIMAL(10,2),
    create_time DATETIME
) ENGINE=InnoDB;

2.2 垂直分表

垂直分表是将一张表按列拆分成多张表,解决表结构过宽的问题。

  1. 假设有如下的原始表:
-- 原始表(包含大字段和常用字段)
CREATE TABLE users (
    user_id INT PRIMARY KEY,
    username VARCHAR(50),
    email VARCHAR(100),
    address VARCHAR(255),
    phone VARCHAR(20),
    created_at DATETIME,
    updated_at DATETIME,
    profile TEXT  -- 大字段,可能会影响查询性能
) ENGINE=InnoDB;
  1. 垂直分表后的结构;
-- 基本信息表(高频查询字段)
CREATE TABLE users_basic (
    user_id INT PRIMARY KEY,
    username VARCHAR(50),
    email VARCHAR(100),
    created_at DATETIME,
    updated_at DATETIME
) ENGINE=InnoDB;

-- 详情信息表(包含大字段和不常用字段)
CREATE TABLE users_detail (
    user_id INT PRIMARY KEY,
    address VARCHAR(255),
    phone VARCHAR(20),
    profile TEXT
) ENGINE=InnoDB;
  1. 插入数据;
-- 插入数据示例
INSERT INTO users_basic (user_id, username, email, created_at, updated_at)
VALUES (1, 'user123', 'user123@example.com', NOW(), NOW());

INSERT INTO users_detail (user_id, address, phone, profile)
VALUES (1, '123 Main St, City, Country', '123-456-7890', 'This is a user profile');

2.3 分区表

分区表是将一张表在物理上分成多个分区,但逻辑上仍是一张表,由MySQL内部管理。

2.3.1 按范围分区(按年份)

  1. 创建表;
-- 创建按年份范围分区的表
CREATE TABLE orders (
    order_id INT ,
    user_id INT,
    amount DECIMAL(10,2),
    create_time DATETIME,
		PRIMARY KEY(order_id, create_time)
) ENGINE=InnoDB
PARTITION BY RANGE (YEAR(create_time)) (
    PARTITION p2023 VALUES LESS THAN (2024),
    PARTITION p2024 VALUES LESS THAN (2025),
    PARTITION p2025 VALUES LESS THAN (2026)
);

MySQL要求主键必须包含分区键(即分区表达式中使用的列)

  1. 插入数据;
-- 插入数据示例:2023年的数据会自动插入到p2023分区
INSERT INTO orders (order_id, user_id, amount, create_time)
VALUES (1001, 12345, 200.00, '2023-01-15 10:30:00');
  1. 查询数据;
-- 查询2023年的数据(优化器会只扫描p2023分区)
SELECT * FROM orders WHERE create_time >= '2023-01-01' AND create_time < '2024-01-01';

2.3.2 按范围分区(按年份)

  1. 创建表;
-- 创建按user_id哈希分区的表
CREATE TABLE orders_4 (
    order_id INT ,
    user_id INT,
    amount DECIMAL(10,2),
    create_time DATETIME,
		PRIMARY KEY (order_id, user_id)
) ENGINE=InnoDB
PARTITION BY HASH (user_id)
PARTITIONS 4;
  1. 插入数据;
-- 插入数据示例:user_id=12345会自动分配到分区1(12345 % 4 = 1)
INSERT INTO orders_4 (order_id, user_id, amount, create_time)
VALUES (1001, 12345, 200.00, NOW());
  1. 查询数据
-- 查询示例(需包含分区键,才能进行分区裁剪)
SELECT * FROM orders_4 WHERE user_id = 12345;

2.3.3

  1. 创建表;
CREATE TABLE orders_5 (
    order_id INT ,
    user_id INT,
    amount DECIMAL(10,2),
    create_time DATETIME,
    region VARCHAR(20),
		PRIMARY KEY (order_id, region)
) ENGINE=InnoDB
PARTITION BY LIST  COLUMNS(region) (
    PARTITION asia VALUES IN ('China', 'Japan', 'Korea'),
    PARTITION europe VALUES IN ('France', 'Germany', 'Italy'),
    PARTITION america VALUES IN ('USA', 'Canada', 'Mexico')
);
特性LIST (expr)LIST COLUMNS (col)
支持的数据类型仅整数表达式字符串、日期、整数等任意列类型
分区值格式必须是整数(如 VALUES IN (1,2,3)可直接使用字面量(如 VALUES IN ('China','USA')
MySQL 版本要求所有版本MySQL 5.5+(推荐 5.7+)
适用场景按整数ID分区按字符串/日期等业务字段分区
  1. 插入数据;
INSERT INTO orders_5 (order_id, user_id, amount, create_time, region)
VALUES (1001, 12345, 200.00, NOW(), 'China');
  1. 查询数据;
SELECT * FROM orders_5 WHERE region = 'China';

3. 适用场景

3.1 水平分表适用场景

  • 单表数据量持续增长,超过1000万条后查询、插入性能明显下降
  • 系统并发访问量高,单库单表无法承受并发压力(如电商平台的订单表)
  • 数据具有明显的分片维度(如时间、用户ID、地理位置)
  • 例如:互联网公司的用户行为日志表、电商平台的订单历史记录表

3.2 垂直分表适用场景

  • 表字段较多、存在大字段(如长文本、图片路径)的场景
  • 字段访问频率差异较大的场景
  • 例如:新闻网站的文章表(基本信息和内容分表)、社交平台的用户表(基本信息和动态信息分表)

3.3 分区表适用场景

  • 数据量巨大、查询频率高的场景
  • 需要按时间、地域等维度进行数据管理的场景
  • 例如:按时间范围分区的日志表、按地理位置分区的订单表

3.4 区分水平和分区表的使用

优先考虑分区表:
1,当数据量达到百万级,但不需要跨表查询
2,当查询主要基于分区键(如时间范围)
3,当希望简化应用层逻辑,减少开发复杂度

考虑水平分表:
1,当需要更高扩展性,需要跨数据库分片
2,当数据分布不均,分区表无法满足需求
3,当需要结合分库策略进行更高级别的扩展

4. 组合使用

在实际业务中,水平分表和垂直分表通常结合使用,形成"先垂直后水平"或"先水平后垂直"的拆分方案:

  1. 先垂直后水平

    • 先按业务模块对单库单表进行垂直拆分,降低业务耦合度
    • 再对垂直拆分后数据量较大的表进行水平拆分,突破数据量限制
    • 例如:电商系统的"订单表"垂直拆分为"订单基本表"、“订单支付表”、“订单物流表”,再对"订单基本表"按"下单时间+用户ID哈希"进行水平拆分
  2. 先水平后垂直

    • 对数据量极大但字段结构复杂的表,先按行进行水平拆分
    • 再对每个水平分表进行垂直拆分,优化单表查询性能
    • 例如:社交平台的"用户动态表"先按"用户ID哈希"水平拆分为多个分表,再对每个分表垂直拆分为"动态基本信息表"和"动态内容(大字段)表"

5. 总结

  • 水平分表:解决"数据量过大"问题,通过拆分数据行提升性能和扩展性
  • 垂直分表:解决"表结构过宽"问题,通过拆分字段提升查询效率和业务清晰度
  • 分区表:数据库内部优化机制,对应用层透明,主要提升查询性能和简化数据管理

在实际应用中,应根据具体业务需求和数据特点选择合适的分表策略,必要时结合使用水平分表和垂直分表,以达到最佳的数据库性能和可维护性。

到此这篇关于MySQL实现数据库分表(水平、垂直、分区表)详细操作步骤的文章就介绍到这了,更多相关MySQL数据库水平、垂直、分区表内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • MySQL创建定时任务实例(每天凌晨1点、每小时、每分钟、某一时间点)

    MySQL创建定时任务实例(每天凌晨1点、每小时、每分钟、某一时间点)

    在mysql中有时候要定时更新或者删除一部分数据需要用到mysql的定时任务,下面这篇文章主要给大家介绍了关于MySQL创建定时任务的相关资料,包括每天凌晨1点、每小时、每分钟、某一时间点等,需要的朋友可以参考下
    2023-03-03
  • MySQL笔记之数据备份与还原的使用详解

    MySQL笔记之数据备份与还原的使用详解

    数据很重要,这点用脚趾头想都知道,为了保证数据的安全,因此需要定期对数据备份
    2013-05-05
  • Linux中更改转移mysql数据库目录的步骤

    Linux中更改转移mysql数据库目录的步骤

    前几天发现由于MySQL的数据库太大,默认安装的/var盘已经再也无法容纳新增加的数据,只能想办法转移数据的目录。网上有很多相关的文章写到转移数据库目录的文章,但转载的过程中还会有一些错误,因为大部分人根本就没测试过,这篇文章是本文测试过整理好后分享给大家。
    2016-11-11
  • 删除MySQL数据库的简单教程

    删除MySQL数据库的简单教程

    这篇文章主要介绍了删除MySQL数据库的简单教程,是MySQL入门学习中的基础知识,需要的朋友可以参考下
    2015-05-05
  • mysql5.6.19下子查询为什么无法使用索引

    mysql5.6.19下子查询为什么无法使用索引

    这篇文章主要介绍了mysql5.6.19下子查询为什么无法使用索引,需要的朋友可以参考下
    2014-08-08
  • MySQL打开时在命令行输入密码后,按回车键闪退的解决方案

    MySQL打开时在命令行输入密码后,按回车键闪退的解决方案

    当MySQL在命令行中输入密码后闪退,无法显示欢迎信息时,可尝试通过计算机管理以管理员身份运行服务,启动MySQL服务,确保MySQL服务已经启动,再次进入命令行界面,应能看到欢迎信息,表明MySQL启动成功,这一方法简单易行,适用于遇到相同问题的用户
    2024-10-10
  • Centos7下MySQL安装教程

    Centos7下MySQL安装教程

    这篇文章主要为大家详细介绍了Centos7下MySQL安装教程,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-06-06
  • MySQL 定时新增分区的实现示例

    MySQL 定时新增分区的实现示例

    本文主要介绍了通过存储过程和定时任务实现MySQL分区的自动创建,解决大数据量下手动维护的繁琐问题,具有一定的参考价值,感兴趣的可以了解一下
    2025-07-07
  • MySQL设置允许远程连接与用户方式(Linux系统)

    MySQL设置允许远程连接与用户方式(Linux系统)

    允许MySQL远程连接需修改配置文件、设置root用户远程访问权限、创建新用户并授权,同时确保服务器端口开放安全
    2026-06-06
  • 在三台MySQL服务器下使用Keepalived实现VIP高可用的方案

    在三台MySQL服务器下使用Keepalived实现VIP高可用的方案

    本文章详细介绍了使用Keepalived实现MySQL主从架构的VIP漂移机制,确保始终指向当前主库,并与MySQL复制配合,确保应用连接正确的库,通过配置检测脚本,确保只有实际的主库才持有VIP,提升切换的可靠性,需要的朋友可以参考下
    2026-07-07

最新评论