# 简介

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

分表(Sharding):

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

分区(Partitioning):

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

区别:

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

# 实现细节

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

# 给表添加分区
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'),
    -- 继续定义更多的分区...
);
# 按指定表名创建当前年月的分区
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
# 调用创建新分区
CALL create_monthly_partition('表名');
# 删除指定分区
ALTER TABLE 表名 drop PARTITION 分区名;
# 每月执行一次调用指定表添加新分区
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 支付宝

支付宝