1. 首页 > MariaDB教程 > 正文

MariaDB教程FG020-MariaDB分表分库与水平垂直拆分最佳实践

本文档风哥主要介绍MariaDB的分表分库与水平垂直拆分最佳实践,包括分片策略、分区实施和性能优化等内容。风哥教程参考MariaDB官方文档Partitioning、Sharding内容,适合数据库管理员学习。

Part01-基础概念与理论知识

1.1 分表分库概述

分表分库是指将数据分散存储到多个表或多个数据库中,以提高系统性能和可扩展性,包括:

  • 水平分表:将一个表的数据分散到多个表中
  • 水平分库:将一个数据库的数据分散到多个数据库中
  • 垂直分表:将一个表的列分散到多个表中
  • 垂直分库:将一个数据库的表分散到多个数据库中

1.2 分区概述

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

  • RANGE分区:按范围分区
  • LIST分区:按列表分区
  • HASH分区:按哈希值分区
  • KEY分区:按键值分区

1.3 分片策略

常见的分片策略包括:

  • 按范围分片:如按时间范围
  • 按哈希分片:如按用户ID哈希
  • 按列表分片:如按地区
  • 复合分片:结合多种策略
更多视频教程www.fgedu.net.cn

Part02-生产环境规划与建议

2.1 分表分库规划

风哥提示:生产环境分表分库规划应根据业务需求、数据量和查询模式进行综合考虑,选择合适的分片策略。

2.2 分区规划

分区规划建议:

  • 选择合适的分区类型
  • 合理设置分区键
  • 考虑分区的数量
  • 定期维护分区

2.3 性能规划

性能规划建议:

  • 优化查询语句
  • 创建合适的索引
  • 使用连接池
  • 监控性能指标
学习交流加群风哥微信: itpux-com

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

3.1 分表分库实施

更多学习教程公众号风哥教程itpux_com

# 分表分库实施

# 1. 水平分表
# 创建多个表
CREATE TABLE fgedu_users_0 (
user_id INT PRIMARY KEY,
username VARCHAR(50),
email VARCHAR(100)
);

CREATE TABLE fgedu_users_1 (
user_id INT PRIMARY KEY,
username VARCHAR(50),
email VARCHAR(100)
);

CREATE TABLE fgedu_users_2 (
user_id INT PRIMARY KEY,
username VARCHAR(50),
email VARCHAR(100)
);

# 插入数据(根据user_id取模分片)
INSERT INTO fgedu_users_0 SELECT * FROM fgedu_users WHERE user_id % 3 = 0;
INSERT INTO fgedu_users_1 SELECT * FROM fgedu_users WHERE user_id % 3 = 1;
INSERT INTO fgedu_users_2 SELECT * FROM fgedu_users WHERE user_id % 3 = 2;

# 2. 水平分库
# 创建多个数据库
CREATE DATABASE fgedu_db0;
CREATE DATABASE fgedu_db1;
CREATE DATABASE fgedu_db2;

# 在每个数据库中创建表
CREATE TABLE fgedu_db0.fgedu_users (
user_id INT PRIMARY KEY,
username VARCHAR(50),
email VARCHAR(100)
);

CREATE TABLE fgedu_db1.fgedu_users (
user_id INT PRIMARY KEY,
username VARCHAR(50),
email VARCHAR(100)
);

CREATE TABLE fgedu_db2.fgedu_users (
user_id INT PRIMARY KEY,
username VARCHAR(50),
email VARCHAR(100)
);

# 3. 垂直分表
# 创建主表
CREATE TABLE fgedu_users_main (
user_id INT PRIMARY KEY,
username VARCHAR(50),
email VARCHAR(100)
);

# 创建扩展表
CREATE TABLE fgedu_users_ext (
user_id INT PRIMARY KEY,
bio TEXT,
avatar BLOB,
FOREIGN KEY (user_id) REFERENCES fgedu_users_main(user_id)
);

# 4. 垂直分库
# 创建用户数据库
CREATE DATABASE fgedu_user_db;

# 创建订单数据库
CREATE DATABASE fgedu_order_db;

# 在用户数据库中创建用户表
CREATE TABLE fgedu_user_db.fgedu_users (
user_id INT PRIMARY KEY,
username VARCHAR(50),
email VARCHAR(100)
);

# 在订单数据库中创建订单表
CREATE TABLE fgedu_order_db.fgedu_orders (
order_id INT PRIMARY KEY,
user_id INT,
amount DECIMAL(10,2)
);

3.2 分区实施

# 分区实施

# 1. RANGE分区
CREATE TABLE fgedu_sales_range (
sale_id INT PRIMARY KEY,
sale_date DATE,
amount DECIMAL(10,2)
) PARTITION BY RANGE (YEAR(sale_date)) (
PARTITION p2024 VALUES LESS THAN (2025),
PARTITION p2025 VALUES LESS THAN (2026),
PARTITION p2026 VALUES LESS THAN (2027),
PARTITION p2027 VALUES LESS THAN (2028),
PARTITION pfuture VALUES LESS THAN MAXVALUE
);

# 2. LIST分区
CREATE TABLE fgedu_sales_list (
sale_id INT PRIMARY KEY,
region_id INT,
amount DECIMAL(10,2)
) PARTITION BY LIST (region_id) (
PARTITION pnorth VALUES IN (1, 2, 3),
PARTITION peast VALUES IN (4, 5, 6),
PARTITION psouth VALUES IN (7, 8, 9),
PARTITION pwest VALUES IN (10, 11, 12)
);

# 3. HASH分区
CREATE TABLE fgedu_sales_hash (
sale_id INT PRIMARY KEY,
user_id INT,
amount DECIMAL(10,2)
) PARTITION BY HASH (user_id) PARTITIONS 4;

# 4. KEY分区
CREATE TABLE fgedu_sales_key (
sale_id INT PRIMARY KEY,
sale_date DATE,
amount DECIMAL(10,2)
) PARTITION BY KEY (sale_date) PARTITIONS 4;

# 5. 管理分区
# 查看分区信息
SHOW CREATE TABLE fgedu_sales_range;

# 维护分区
ALTER TABLE fgedu_sales_range REORGANIZE PARTITION pfuture INTO (
PARTITION p2028 VALUES LESS THAN (2029),
PARTITION pfuture VALUES LESS THAN MAXVALUE
);

# 重建分区
ALTER TABLE fgedu_sales_range REBUILD PARTITION p2024, p2025;

# 优化分区
ALTER TABLE fgedu_sales_range OPTIMIZE PARTITION p2024, p2025;

# 分析分区
ALTER TABLE fgedu_sales_range ANALYZE PARTITION p2024, p2025;

# 检查分区
ALTER TABLE fgedu_sales_range CHECK PARTITION p2024, p2025;

# 修复分区
ALTER TABLE fgedu_sales_range REPAIR PARTITION p2024, p2025;

# 截断分区
ALTER TABLE fgedu_sales_range TRUNCATE PARTITION p2024;

# 删除分区
ALTER TABLE fgedu_sales_range DROP PARTITION p2024;

# 添加分区
ALTER TABLE fgedu_sales_range ADD PARTITION (
PARTITION p2029 VALUES LESS THAN (2030)
);

3.3 性能优化

风哥提示:分表分库和分区的性能优化需要综合考虑查询模式、数据分布和硬件配置等因素。

# 性能优化

# 1. 索引优化
# 在分区表上创建索引
CREATE INDEX idx_sale_date ON fgedu_sales_range(sale_date);

# 2. 查询优化
# 利用分区裁剪
SELECT * FROM fgedu_sales_range WHERE sale_date BETWEEN ‘2025-01-01’ AND ‘2025-12-31’;

# 避免全表扫描
SELECT * FROM fgedu_sales_range WHERE sale_id = 1000;

# 3. 连接优化
# 使用分区连接
SELECT * FROM fgedu_sales_range s
JOIN fgedu_customers c ON s.customer_id = c.customer_id
WHERE s.sale_date BETWEEN ‘2025-01-01’ AND ‘2025-12-31’;

# 4. 负载均衡
# 使用代理进行负载均衡
# 例如使用ProxySQL、MaxScale等

# 5. 监控与调优
# 监控分区使用情况
SELECT TABLE_NAME, PARTITION_NAME, TABLE_ROWS
FROM information_schema.PARTITIONS
WHERE TABLE_SCHEMA = ‘fgedu_db’ AND TABLE_NAME = ‘fgedu_sales_range’;

风哥提示:安全开发是防止SQL注入的第一道防线

Part04-生产案例与实战讲解

4.1 分表分库实战

# 分表分库实战

# 案例1:用户表水平分表
# 1. 创建分表
CREATE TABLE fgedu_users_0 (
user_id INT PRIMARY KEY,
username VARCHAR(50),
email VARCHAR(100),
created_at DATETIME
);

CREATE TABLE fgedu_users_1 (
user_id INT PRIMARY KEY,
username VARCHAR(50),
email VARCHAR(100),
created_at DATETIME
);

CREATE TABLE fgedu_users_2 (
user_id INT PRIMARY KEY,
username VARCHAR(50),
email VARCHAR(100),
created_at DATETIME
);

# 2. 创建存储过程处理数据插入
DELIMITER //
CREATE PROCEDURE insert_user(IN p_user_id INT, IN p_username VARCHAR(50), IN p_email VARCHAR(100))
BEGIN
DECLARE shard INT;
SET shard = p_user_id % 3;

IF shard = 0 THEN
INSERT INTO fgedu_users_0 (user_id, username, email, created_at)
VALUES (p_user_id, p_username, p_email, NOW());
ELSEIF shard = 1 THEN
INSERT INTO fgedu_users_1 (user_id, username, email, created_at)
VALUES (p_user_id, p_username, p_email, NOW());
ELSE
INSERT INTO fgedu_users_2 (user_id, username, email, created_at)
VALUES (p_user_id, p_username, p_email, NOW());
END IF;
END //
DELIMITER ;

# 3. 插入数据
CALL insert_user(1, ‘user1’, ‘user1@fgedu.net.cn’);
CALL insert_user(2, ‘user2’, ‘user2@fgedu.net.cn’);
CALL insert_user(3, ‘user3’, ‘user3@fgedu.net.cn’);
CALL insert_user(4, ‘user4’, ‘user4@fgedu.net.cn’);
CALL insert_user(5, ‘user5’, ‘user5@fgedu.net.cn’);
CALL insert_user(6, ‘user6’, ‘user6@fgedu.net.cn’);

# 4. 查询数据
# 创建视图统一查询
CREATE VIEW fgedu_users AS
SELECT * FROM fgedu_users_0
UNION ALL
SELECT * FROM fgedu_users_1
UNION ALL
SELECT * FROM fgedu_users_2;

# 查询所有用户
SELECT * FROM fgedu_users;

# 根据user_id查询
SELECT * FROM fgedu_users WHERE user_id = 1;

4.2 分区实战

# 分区实战

# 案例2:销售表按时间分区
# 1. 创建分区表
CREATE TABLE fgedu_sales (
sale_id INT PRIMARY KEY AUTO_INCREMENT,
sale_date DATE NOT NULL,
customer_id INT NOT NULL,
amount DECIMAL(10,2) NOT NULL,
created_at DATETIME DEFAULT NOW()
) PARTITION BY RANGE (YEAR(sale_date)) (
PARTITION p2024 VALUES LESS THAN (2025),
PARTITION p2025 VALUES LESS THAN (2026),
PARTITION p2026 VALUES LESS THAN (2027),
PARTITION p2027 VALUES LESS THAN (2028),
PARTITION pfuture VALUES LESS THAN MAXVALUE
);

# 2. 插入测试数据
INSERT INTO fgedu_sales (sale_date, customer_id, amount) VALUES
(‘2024-01-01’, 1, 1000.00),
(‘2024-06-01’, 2, 2000.00),
(‘2025-01-01’, 3, 1500.00),
(‘2025-06-01’, 1, 3000.00),
(‘2026-01-01’, 2, 2500.00),
(‘2026-06-01’, 3, 4000.00);

# 3. 分区查询
# 查询2025年的销售数据(只扫描p2025分区)
SELECT * FROM fgedu_sales WHERE sale_date BETWEEN ‘2025-01-01’ AND ‘2025-12-31’;

# 查询2026年的销售数据(只扫描p2026分区)
SELECT * FROM fgedu_sales WHERE sale_date BETWEEN ‘2026-01-01’ AND ‘2026-12-31’;

# 4. 分区维护
# 添加新分区
ALTER TABLE fgedu_sales ADD PARTITION (
PARTITION p2028 VALUES LESS THAN (2029)
);

# 查看分区信息
SELECT TABLE_NAME, PARTITION_NAME, TABLE_ROWS
FROM information_schema.PARTITIONS
WHERE TABLE_SCHEMA = ‘fgedu_db’ AND TABLE_NAME = ‘fgedu_sales’;

4.3 性能优化实战

# 性能优化实战

# 案例3:分表分库性能优化
# 1. 索引优化
CREATE INDEX idx_created_at ON fgedu_users_0(created_at);
CREATE INDEX idx_created_at ON fgedu_users_1(created_at);
CREATE INDEX idx_created_at ON fgedu_users_2(created_at);

# 2. 查询优化
# 避免使用UNION ALL的全表扫描
# 直接查询对应的分表
SELECT * FROM fgedu_users_0 WHERE user_id = 1;

# 3. 连接池配置
# 在应用程序中配置连接池
# 例如使用HikariCP、Druid等

# 4. 监控与调优
# 监控慢查询
SHOW GLOBAL VARIABLES LIKE ‘slow_query_log’;
SET GLOBAL slow_query_log = ‘ON’;
SET GLOBAL slow_query_log_file = ‘/mariadb/app/logs/slow_query.log’;
SET GLOBAL long_query_time = 1;

# 分析慢查询
EXPLAIN SELECT * FROM fgedu_users WHERE created_at BETWEEN ‘2026-01-01’ AND ‘2026-12-31’;

Part05-风哥经验总结与分享

5.1 常见问题与解决

  • 数据分布不均:使用合适的分片策略,如哈希分片
  • 跨分片查询性能差:减少跨分片查询,使用本地查询
  • 分片键选择困难:根据业务查询模式选择合适的分片键
  • 分区维护复杂:定期进行分区维护,如合并、拆分分区
  • 数据迁移困难:使用工具进行数据迁移,如MariaDB的工具

5.2 最佳实践

  • 合理规划分片策略:根据业务需求选择合适的分片策略
  • 使用分区表:对于时间序列数据,使用RANGE分区
  • 优化查询语句:避免全表扫描,使用索引
  • 定期维护:定期进行分区维护和索引优化
  • 监控性能:使用监控工具监控数据库性能

5.3 分表分库检查清单

  • ✓ 选择合适的分片策略
  • ✓ 设计合理的分片键
  • ✓ 考虑数据分布均匀性
  • ✓ 优化跨分片查询
  • ✓ 定期进行分片维护
  • ✓ 监控分片性能
  • ✓ 制定数据迁移策略
  • ✓ 考虑系统可扩展性
from MariaDB视频:www.itpux.com

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

联系我们

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

微信号:itpux-com

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