# 简介

当单表数据量过大时,就需要考虑对表进行分表或者分区了。分表和分区都是用来解决数据库中大量数据存储和查询效率的问题,但它们的实现方式和解决的问题有所不同。

分表(Sharding):

  • 分表是将一个大表按照某种规则拆分成多个较小的表,每个小表称为一个分表,这些分表可以分布在不同的数据库实例中。
  • 分表通常基于某种规则进行拆分,例如按照用户 ID、地理位置等进行拆分。
  • 分表的主要目的是解决单个表过大的问题,提高查询效率和并发能力。

分区(Partitioning):

  • 分区是将一个表按照某种规则拆分成多个逻辑上的部分,每个部分称为一个分区,但这些分区仍然属于同一个表。
  • 分区通常基于某种规则进行拆分,例如按照时间、范围、哈希值等进行拆分。
  • 分区的主要目的是提高数据的管理和查询效率,通过将数据分散到不同的分区中,可以提高查询性能和管理灵活性。

区别:

  • 实现方式:分表是将一个表拆分成多个子表,每个子表都是一个独立的表;而分区是将一个表按照某种规则拆分成多个逻辑上的部分,这些部分仍然属于同一个表。
  • 解决的问题:分表主要解决单个表过大的问题,提高查询效率和并发能力;而分区主要提高数据的管理和查询效率,通过将数据分散到不同的分区中,可以提高查询性能和管理灵活性。
  • 适用场景:分表适用于单表数据量巨大的情况,例如大型电商平台的订单表;而分区适用于需要根据某种规则对数据进行划分管理的情况,例如按照时间对日志表进行分区。

# 实现细节

本文章介绍的是如何对单表进行分区。

# 给表添加分区

1
2
3
4
5
6
7
8
ALTER TABLE 表名(字段)
PARTITION BY RANGE COLUMNS (时间字段名) (
-- 分区条件(时间小于2022-02-01的数据放入p202201分区中)
PARTITION p202201 VALUES LESS THAN ('2022-02-01'),
PARTITION p202202 VALUES LESS THAN ('2022-03-01'),
PARTITION p202203 VALUES LESS THAN ('2022-04-01'),
-- 继续定义更多的分区...
);

# 按指定表名创建当前年月的分区

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
CREATE PROCEDURE create_monthly_partition(IN tableName VARCHAR(255))
BEGIN
DECLARE currentYear INT;
DECLARE currentMonth INT;
DECLARE nextYear INT;
DECLARE nextMonth INT;
DECLARE partitionName VARCHAR(255);
SET currentYear = YEAR(CURRENT_DATE);
SET currentMonth = MONTH(CURRENT_DATE);
-- 计算下一个月的年份和月份
IF currentMonth = 12 THEN
SET nextYear = currentYear + 1;
SET nextMonth = 1;
ELSE
SET nextYear = currentYear;
SET nextMonth = currentMonth + 1;
END IF;
SET partitionName = CONCAT('p', currentYear, LPAD(currentMonth, 2, 0));
SET @sql = CONCAT('ALTER TABLE ', tableName,
' ADD PARTITION (PARTITION ', partitionName,
' VALUES LESS THAN (\'', nextYear, '-', LPAD(nextMonth, 2, 0), '-01\'', '))');
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
END

# 调用创建新分区

1
CALL create_monthly_partition('表名');

# 删除指定分区

1
ALTER TABLE 表名 drop PARTITION 分区名;

# 每月执行一次调用指定表添加新分区

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
CREATE EVENT create_monthly_partition_event
ON SCHEDULE EVERY 1 MONTH
STARTS '2024-01-01 00:00:00.000'
ON COMPLETION NOT PRESERVE
ENABLE
DO begin
DECLARE CONTINUE HANDLER FOR SQLEXCEPTION
BEGIN
-- 捕获异常,记录错误信息,然后继续执行
SET @error_message = CONCAT('Error occurred while processing table: ', @tableName);
-- 可以将错误信息插入到日志表,或者使用 SELECT 输出错误信息
SELECT @error_message;
END;
-- 定义需要分区的表名列表
   SET @tables = '表名1,表名2';
-- 遍历表名列表并为每个表创建分区
WHILE CHAR_LENGTH(@tables) > 0 DO
SET @tableName = SUBSTRING_INDEX(@tables, ',', 1);
SET @tables = SUBSTRING(@tables, CHAR_LENGTH(@tableName) + 2);
CALL create_monthly_partition(@tableName);
END WHILE;
end

更新于 阅读次数

请我喝[茶]~( ̄▽ ̄)~*

Hito Li 微信支付

微信支付

Hito Li 支付宝

支付宝