1. 首页 > 国产数据库教程 > TiDB教程 > 正文

tidb教程FG016-TiDB分区表原理与使用场景

本文档详细介绍TiDB分区表的原理与使用场景,包括分区表的概念、类型、原理、创建方法、管理维护等内容。风哥教程参考TiDB官方文档分区表相关内容,适合DBA和开发人员在日常使用TiDB时参考。更多视频教程www.fgedu.net.cn

Part01-基础概念与理论知识

1.1 分区表概念

分区表是将表数据按照一定的规则分散存储到多个物理文件中的表。

  • 分区键:用于确定数据所属分区的列
  • 分区规则:决定数据如何分配到不同分区的规则
  • 分区:表的一个逻辑部分,对应一个或多个物理文件
TiDB分区表特点:

  • 兼容MySQL分区表语法
  • 支持Range、Hash、List分区
  • 提高查询性能
  • 便于数据管理

1.2 分区类型

TiDB支持三种分区类型:

1.2.1 Range分区

# Range分区
– 基于列值的范围进行分区
– 适用于按时间、ID等连续值分区
– 示例:按日期范围分区

1.2.2 Hash分区

# Hash分区
– 基于列值的哈希值进行分区
– 适用于均匀分布数据
– 示例:按用户ID哈希分区

1.2.3 List分区

# List分区
– 基于列值的列表进行分区
– 适用于离散值分区
– 示例:按地区、状态等分区

1.3 分区原理

TiDB分区表的原理:

  • 逻辑结构:分区表在逻辑上是一个整体,对外表现为一个表
  • 物理结构:数据分散存储在多个物理文件中
  • 分区裁剪:查询时只扫描相关分区,提高查询性能
  • 数据管理:可以单独管理每个分区,如备份、恢复、删除等
  • 风哥提示:

风哥提示:分区表可以显著提高大表的查询性能和管理效率。学习交流加群风哥微信: itpux-com

Part02-生产环境规划与建议

2.1 分区设计

2.1.1 分区键选择

# 分区键选择
– 选择频繁用于查询条件的列
– 选择数据分布均匀的列
– 选择稳定的列,避免频繁更新
– 考虑数据增长模式

## 示例
– 按时间分区:created_at, order_date
– 按ID分区:user_id, order_id
– 按地区分区:region_id, country_code

2.1.2 分区数量

# 分区数量
– 考虑数据量大小
– 考虑查询性能
– 考虑管理复杂度
– 建议:
– 中小表:10-50个分区
– 大表:50-200个分区
– 超大表:200+个分区

2.2 分区策略选择

2.2.1 Range分区适用场景

# Range分区适用场景
– 时间序列数据:如日志、订单、交易记录
– 按ID范围分区:如用户数据、产品数据
– 需要按范围查询的场景
– 需要按范围删除数据的场景

2.2.2 Hash分区适用场景

# Hash分区适用场景
– 需要均匀分布数据的场景
– 没有明显范围特征的数据
– 随机访问模式的场景
– 不需要按范围查询的场景

2.2.3 List分区适用场景

# List分区适用场景
– 离散值数据:如地区、状态、类型
– 需要按特定值分组的场景
– 数据有明确分类的场景

2.3 性能考虑

# 性能考虑

## 1. 查询性能
– 分区裁剪:只扫描相关分区
– 并行查询:多个分区并行处理
– 索引优化:每个分区有独立的索引

## 2. 写入性能
– 分散写入:数据分散到多个分区
– 减少锁竞争:不同分区的操作相互独立

## 3. 维护性能
– 快速备份:只备份特定分区
– 快速恢复:只恢复特定分区
– 快速删除:通过删除分区快速清理数据

## 4. 存储考虑
– 数据分布:均匀分布数据
– 空间管理:更灵活的空间管理

生产环境建议:根据业务需求和数据特征选择合适的分区策略,以获得最佳性能。学习交流加群风哥QQ113257174

Part03-生产环境项目实施方案

3.1 分区表创建

3.1.1 Range分区表创建

# Range分区表创建

## 1. 基本语法学习交流加群风哥QQ113257174
CREATE TABLE table_name (

) PARTITION BY RANGE (partition_key) (
PARTITION partition_name VALUES LESS THAN (value),
PARTITION partition_name VALUES LESS THAN (value),

);

## 2. 示例:按日期分区
CREATE TABLE fgedu_orders (
id INT PRIMARY KEY AUTO_INCREMENT,
order_no VARCHAR(32) UNIQUE,
user_id INT,
amount DECIMAL(10,2) NOT NULL,
status VARCHAR(20) DEFAULT ‘pending’,
created_at DATETIME NOT NULL,
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
) PARTITION BY RANGE (YEAR(created_at)) (
PARTITION p2023 VALUES LESS THAN (2024),
PARTITION p2024 VALUES LESS THAN (2025),
PARTITION p2025 VALUES LESS THAN (2026)
);

## 3. 示例:按ID分区
CREATE TABLE fgedu_users (
id INT PRIMARY KEY,
name VARCHAR(50) NOT NULL,
email VARCHAR(100) UNIQUE,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
) PARTITION BY RANGE (id) (
PARTITION p0 VALUES LESS THAN (10000),
PARTITION p1 VALUES LESS THAN (20000),
PARTITION p2 VALUES LESS THAN (30000),
PARTITION p3 VALUES LESS THAN (MAXVALUE)
);

3.1.2 Hash分区表创建

# Hash分区表创建

## 1. 基本语法
CREATE TABLE table_name (

) PARTITION BY HASH (partition_key) PARTITIONS partition_count;

## 2. 示例:按用户ID哈希分区
CREATE TABLE fgedu_user_logs (
id INT PRIMARY KEY AUTO_INCREMENT,
user_id INT NOT NULL,
action VARCHAR(50) NOT NULL,
detail TEXT,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
) PARTITION BY HASH (user_id) PARTITIONS 8;

## 3. 示例:按订单ID哈希分区
CREATE TABLE fgedu_order_items (
id INT PRIMARY KEY AUTO_INCREMENT,
order_id INT NOT NULL,
product_id INT NOT NULL,
quantity INT NOT NULL,
price DECIMAL(10,2) NOT NULL,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
) PARTITION BY HASH (order_id) PARTITIONS 16;

3.1.3 List分区表创建

# List分区表创建

## 1. 基本语法
CREATE TABLE table_name (

) PARTITION BY LIST (partition_key) (
PARTITION partition_name VALUES IN (value1, value2, …),
PARTITION partition_name VALUES IN (value1, value2, …),

);

## 2. 示例:按地区分区
CREATE TABLE fgedu_customers (
id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(50) NOT NULL,
region VARCHAR(20) NOT NULL,
email VARCHAR(100) UNIQUE,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
) PARTITION BY LIST (region) (
PARTITION p_north VALUES IN (‘北京’, ‘天津’, ‘河北’, ‘山西’, ‘内蒙古’),
PARTITION p_east VALUES IN (‘上海’, ‘江苏’, ‘浙江’, ‘安徽’, ‘福建’, ‘江西’, ‘山东’),
PARTITION p_south VALUES IN (‘广东’, ‘广西’, ‘海南’),
PARTITION p_other VALUES IN (‘其他’)
);

## 3. 示例:按状态分区
CREATE TABLE fgedu_orders (
id INT PRIMARY KEY AUTO_INCREMENT,
order_no VARCHAR(32) UNIQUE,
user_id INT,
amount DECIMAL(10,2) NOT NULL,
status VARCHAR(20) NOT NULL,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
) PARTITION BY LIST (status) (
PARTITION p_pending VALUES IN (‘pending’),
PARTITION p_processing VALUES IN (‘processing’),
PARTITION p_completed VALUES IN (‘completed’),
PARTITION p_cancelled VALUES IN (‘cancelled’)
);

3.2 分区管理

3.2.1 添加分区

# 添加分区

## 1. Range分区添加
ALTER TABLE fgedu_orders ADD PARTITION (
PARTITION p2026 VALUES LESS THAN (2027)
);

## 2. List分区添加
ALTER TABLE fgedu_customers ADD PARTITION (
PARTITION p_west VALUES IN (‘重庆’, ‘四川’, ‘贵州’, ‘云南’, ‘西藏’)
);

## 3. Hash分区添加
# Hash分区不能直接添加,需要重建表
ALTER TABLE fgedu_user_logs PARTITION BY HASH (user_id) PARTITIONS 16;

3.2.2 删除分区

# 删除分区

## 1. Range分区删除
ALTER TABLE fgedu_orders DROP PARTITION p2023;

## 2. List分区删除
ALTER TABLE fgedu_customers DROP PARTITION p_other;

## 3. Hash分区删除
# Hash分区不能直接删除,需要重建表
ALTER TABLE fgedu_user_logs PARTITION BY HASH (user_id) PARTITIONS 8;

3.2.3 拆分分区

# 拆分分区

## 1. Range分区拆分
ALTER TABLE fgedu_orders REORGANIZE PARTITION p2024 INTO (
PARTITION p2024_q1 VALUES LESS THAN (20240401),
PARTITION p2024_q2 VALUES LESS THAN (20240701),
PARTITION p2024_q3 VALUES LESS THAN (20241001),
PARTITION p2024_q4 VALUES LESS THAN (20250101)
);

## 2. List分区拆分
ALTER TABLE fgedu_customers REORGANIZE PARTITION p_east INTO (
PARTITION p_east_north VALUES IN (‘江苏’, ‘浙江’, ‘上海’),
PARTITION p_east_south VALUES IN (‘安徽’, ‘福建’, ‘江西’, ‘山东’)
);

3.3 分区维护

3.3.1 查看分区信息

# 查看分区信息

## 1. 查看表的分区信息
SHOW CREATE TABLE fgedu_orders;

## 2. 查看分区列表
SHOW PARTITIONS FROM fgedu_orders;

## 3. 查看分区统计信息
SELECT
table_schema,
table_name,
partition_name,
table_rows,
data_length,
index_length
FROM
information_schema.partitions
WHERE
table_schema = ‘fgedudb’
AND table_name = ‘fgedu_orders’;

3.3.2 分区优化

# 分区优化

## 1. 重建分区
ALTER TABLE fgedu_orders REBUILD PARTITION p2024;

## 2. 分析分区
ALTER TABLE fgedu_orders ANALYZE PARTITION p2024;

## 3. 检查分区
ALTER TABLE fgedu_orders CHECK PARTITION p2024;

## 4. 优化分区
ALTER TABLE fgedu_orders OPTIMIZE PARTITION p2024;

风哥提示:定期维护分区表可以保持良好的性能和可靠性。更多学习教程公众号风哥教程itpux_com

Part04-生产案例与实战讲解

4.1 Range分区实战案例

# Range分区实战案例

## 1. 创建按日期分区的订单表
mysql> CREATE TABLE fgedu_orders (
-> id INT PRIMARY KEY AUTO_INCREMENT,
-> order_no VARCHAR(32) UNIQUE,
-> user_id INT,
-> amount DECIMAL(10,2) NOT NULL,
-> status VARCHAR(20) DEFAULT ‘pending’,
-> created_at DATETIME NOT NULL,
-> updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
-> ) PARTITION BY RANGE (TO_DAYS(created_at)) (
-> PARTITION p202401 VALUES LESS THAN (TO_DAYS(‘2024-02-01’)),
-> PARTITION p202402 VALUES LESS THAN (TO_DAYS(‘2024-03-01’)),
-> PARTITION p202403 VALUES LESS THAN (TO_DAYS(‘2024-04-01’)),
-> PARTITION p202404 VALUES LESS THAN (TO_DAYS(‘2024-05-01’)),
-> PARTITION p202405 VALUES LESS THAN (TO_DAYS(‘2024-06-01’)),
-> PARTITION p202406 VALUES LESS THAN (TO_DAYS(‘2024-07-01’)),
-> PARTITION p202407 VALUES LESS THAN (TO_DAYS(‘2024-08-01’)),
-> PARTITION p202408 VALUES LESS THAN (TO_DAYS(‘2024-09-01’)),
-> PARTITION p202409 VALUES LESS THAN (TO_DAYS(‘2024-10-01’)),
-> PARTITION p202410 VALUES LESS THAN (TO_DAYS(‘2024-11-01’)),
-> PARTITION p202411 VALUES LESS THAN (TO_DAYS(‘2024-12-01’)),
-> PARTITION p202412 VALUES LESS THAN (TO_DAYS(‘2025-01-01’))
-> );

## 2. 插入测试数据
mysql> INSERT INTO fgedu_orders (order_no, user_id, amount, status, created_at) VALUES
-> (‘FG202401010001’, 1, 100.00, ‘completed’, ‘2024-01-01 10:00:00’),
-> (‘FG202402010001’, 2, 200.00, ‘completed’, ‘2024-02-01 10:00:00’),
-> (‘FG202403010001’, 3, 300.00, ‘completed’, ‘2024-03-01 10:00:00’),
-> (‘FG202404010001’, 4, 400.00, ‘completed’, ‘2024-04-01 10:00:00’),
-> (‘FG202405010001’, 5, 500.00, ‘completed’, ‘2024-05-01 10:00:00’);

## 3. 查看分区信息
mysql> SHOW PARTITIONS FROM fgedu_orders;
+—————-+—————-+————-+———————+———————+————+—————-+————————+———————–+
| Partition Name | Subpartition | Partition Method | Partition Expression | Partition Values | Subpartitions | Parent Table | Table Space | Log File Group |
+—————-+—————-+————-+———————+———————+————+—————-+————————+———————–+
| p202401 | NULL | RANGE | TO_DAYS(created_at) | LESS THAN (739232) | NULL | fgedu_orders | NULL | NULL |
| p202402 | NULL | RANGE | TO_DAYS(created_at) | LESS THAN (739260) | NULL | fgedu_orders | NULL | NULL |
| p202403 | NULL | RANGE | TO_DAYS(created_at) | LESS THAN (739291) | NULL | fgedu_orders | NULL | NULL |
| p202404 | NULL | RANGE | TO_DAYS(created_at) | LESS THAN (739321) | NULL | fgedu_orders | NULL | NULL |
| p202405 | NULL | RANGE | TO_DAYS(created_at) | LESS THAN (739352) | NULL | fgedu_orders | NULL | NULL |
| p202406 | NULL | RANGE | TO_DAYS(created_at) | LESS THAN (739382) | NULL | fgedu_orders | NULL | NULL |
| p202407 | NULL | RANGE | TO_DAYS(created_at) | LESS THAN (739413) | NULL | fgedu_orders | NULL | NULL |
| p202408 | NULL | RANGE | TO_DAYS(created_at) | LESS THAN (739444) | NULL | fgedu_orders | NULL | NULL |
| p202409 | NULL | RANGE | TO_DAYS(created_at) | LESS THAN (739474) | NULL | fgedu_orders | NULL | NULL |
| p202410 | NULL | RANGE | TO_DAYS(created_at) | LESS THAN (739505) | NULL | fgedu_orders | NULL | NULL |
| p202411 | NULL | RANGE | TO_DAYS(created_at) | LESS THAN (739535) | NULL | fgedu_orders | NULL | NULL |
| p202412 | NULL | RANGE | TO_DAYS(created_at) | LESS THAN (739566) | NULL | fgedu_orders | NULL | NULL |
+—————-+—————-+————-+———————+———————+————+—————-+————————+———————–+

## 4. 测试分区裁剪
mysql> EXPLAIN SELECT * FROM fgedu_orders WHERE created_at BETWEEN ‘2024-01-01’ AND ‘2024-01-31’;

## 5. 添加新分区
mysql> ALTER TABLE fgedu_orders ADD PARTITION (
-> PARTITION p202501 VALUES LESS THAN (TO_DAYS(‘2025-02-01’))
-> );

## 6. 删除旧分区
mysql> ALTER TABLE fgedu_orders DROP PARTITION p202401;

4.2 Hash分区实战案例

# Hash分区实战案例

## 1. 创建按用户ID哈希分区的用户日志表
mysql> CREATE TABLE fgedu_user_logs (
-> id INT PRIMARY KEY AUTO_INCREMENT,
-> user_id INT NOT NULL,
-> action VARCHAR(50) NOT NULL,
-> detail TEXT,
-> created_at DATETIME DEFAULT CURRENT_TIMESTAMP
-> ) PARTITION BY HASH (user_id) PARTITIONS 8;

## 2. 插入测试数据
mysql> INSERT INTO fgedu_user_logs (user_id, action, detail) VALUES
-> (1, ‘login’, ‘用户登录’),
-> (2, ‘logout’, ‘用户登出’),
-> (3, ‘register’, ‘用户注册’),
-> (4, ‘update_profile’, ‘更新个人资料’),
-> (5, ‘password_reset’, ‘重置密码’),
-> (6, ‘login’, ‘用户登录’),
-> (7, ‘logout’, ‘用户登出’),
-> (8, ‘register’, ‘用户注册’),
-> (9, ‘update_profile’, ‘更新个人资料’),
-> (10, ‘password_reset’, ‘重置密码’);

## 3. 查看分区信息
mysql> SELECT
-> table_schema,
-> table_name,
-> partition_name,
-> table_rows
-> FROM
-> information_schema.partitions
-> WHERE
-> table_schema = ‘fgedudb’
-> AND table_name = ‘fgedu_user_logs’;

## 4. 测试查询
mysql> SELECT * FROM fgedu_user_logs WHERE user_id = 1;

## 5. 扩展分区
mysql> ALTER TABLE fgedu_user_logs PARTITION BY HASH (user_id) PARTITIONS 16;

4.3 List分区实战案例

# List分区实战案例

## 1. 创建按地区分区的客户表
mysql> CREATE TABLE fgedu_customers (
-> id INT PRIMARY KEY AUTO_INCREMENT,
-> name VARCHAR(50) NOT NULL,
-> region VARCHAR(20) NOT NULL,
-> email VARCHAR(100) UNIQUE,
-> created_at DATETIME DEFAULT CURRENT_TIMESTAMP
-> ) PARTITION BY LIST (region) (
-> PARTITION p_north VALUES IN (‘北京’, ‘天津’, ‘河北’, ‘山西’, ‘内蒙古’),
-> PARTITION p_east VALUES IN (‘上海’, ‘江苏’, ‘浙江’, ‘安徽’, ‘福建’, ‘江西’, ‘山东’),
-> PARTITION p_south VALUES IN (‘广东’, ‘广西’, ‘海南’),
-> PARTITION p_central VALUES IN (‘河南’, ‘湖北’, ‘湖南’),
-> PARTITION p_west VALUES IN (‘重庆’, ‘四川’, ‘贵州’, ‘云南’, ‘西藏’, ‘陕西’, ‘甘肃’, ‘青海’, ‘宁夏’, ‘新疆’),
-> PARTITION p_other VALUES IN (‘其他’)
-> );

## 2. 插入测试数据
mysql> INSERT INTO fgedu_customers (name, region, email) VALUES
-> (‘张三’, ‘北京’, ‘zhangsan@example.com’),
-> (‘李四’, ‘上海’, ‘lisi@example.com’),
-> (‘王五’, ‘广东’, ‘wangwu@example.com’),
-> (‘赵六’, ‘四川’, ‘zhaoliu@example.com’),
-> (‘孙七’, ‘河南’, ‘sunqi@example.com’),
-> (‘周八’, ‘其他’, ‘zhouba@example.com’);

## 3. 查看分区信息
mysql> SHOW PARTITIONS FROM fgedu_customers;

## 4. 测试分区查询
mysql> SELECT * FROM fgedu_customers WHERE region = ‘北京’;

## 5. 添加新分区
mysql> ALTER TABLE fgedu_customers ADD PARTITION (
-> PARTITION p_hongkong VALUES IN (‘香港’, ‘澳门’, ‘台湾’)
-> );

## 6. 拆分分区
mysql> ALTER TABLE fgedu_customers REORGANIZE PARTITION p_west INTO (
-> PARTITION p_northwest VALUES IN (‘陕西’, ‘甘肃’, ‘青海’, ‘宁夏’, ‘新疆’),
-> PARTITION p_southwest VALUES IN (‘重庆’, ‘四川’, ‘贵州’, ‘云南’, ‘西藏’)
-> );

生产环境建议:根据业务需求选择合适的分区策略,并定期维护分区表以保持良好的性能。from tidb视频:www.itpux.com

Part05-风哥经验总结与分享

5.1 最佳实践

TiDB分区表的最佳实践:

  • 分区键选择:选择频繁用于查询条件的列,确保数据分布均匀
  • 分区策略:根据数据特征选择合适的分区类型
  • 分区数量:根据数据量和查询模式确定合理的分区数量
  • 分区维护:定期添加新分区,删除旧分区,优化分区
  • 性能监控:监控分区表的性能,及时调整分区策略
  • 备份策略:考虑分区级别的备份和恢复
  • 权限管理:根据分区数据的敏感性设置不同的权限

5.2 性能优化技巧

# 性能优化技巧

## 1. 查询优化
– 使用分区键作为查询条件
– 避免跨分区查询
– 合理使用索引
– 利用分区裁剪

## 2. 写入优化
– 均匀分布写入数据
– 避免热点分区
– 批量写入
– 使用并行写入

## 3. 维护优化
– 定期重建分区
– 定期分析分区统计信息
– 定期检查分区
– 合理规划分区生命周期

## 4. 存储优化
– 合理设置分区大小
– 利用分区进行数据归档
– 考虑使用不同的存储介质

5.3 常见问题与解决

# 常见问题与解决

## 1. 分区键选择不当
– 问题:数据分布不均匀,导致热点分区
– 解决:选择更合适的分区键,或使用复合分区

## 2. 分区数量过多
– 问题:管理复杂,元数据开销大
– 解决:合理规划分区数量,避免过多分区

## 3. 分区裁剪失效
– 问题:查询没有使用分区键,导致全表扫描
– 解决:确保查询条件包含分区键

## 4. 分区维护成本高
– 问题:手动管理分区繁琐
– 解决:使用自动化脚本管理分区

## 5. 性能下降
– 问题:分区表性能不如预期
– 解决:检查分区策略,优化查询,维护分区

## 6. 数据迁移困难
– 问题:分区表数据迁移复杂
– 解决:使用TiDB的备份恢复工具,或分区级别的操作

风哥提示:分区表是提高大表性能的有效手段,但需要根据具体业务场景合理设计和使用。

持续学习:分区表的设计和使用是一个不断优化的过程,建议定期关注TiDB的新特性和最佳实践。

本文由风哥教程整理发布,仅用于学习测试使用,转载注明出处:http://www.fgedu.net.cn/10327.html

联系我们

在线咨询:点击这里给我发消息

微信号:itpux-com

工作日:9:30-18:30,节假日休息