阿东的笔记_  工具

MySQL存储过程自动按年/月/日分表分区

PARTITION 创建分区

  1. DROP PROCEDURE IF EXISTS `proc_create_partition`;
  2. DELIMITER ;;
  3. CREATE DEFINER=`root`@`%` PROCEDURE `proc_create_partition`(
  4. p_table VARCHAR(128), -- 表名
  5. p_date DATETIME, -- 生成指定起始日期
  6. p_time_field VARCHAR(32), -- 时间字段
  7. p_counts INT, -- 生成多少个分区
  8. p_type VARCHAR(12) -- day按天 month 按月,year按年
  9. )
  10. BEGIN
  11. SET @partition_table = 'p';
  12. IF( p_time_field IS NULL ) THEN
  13. SET p_time_field = 'pubtime'; -- 没有传参数,默认字段名 pubtime
  14. END IF;
  15. SET @has = NULL;
  16. SELECT REPLACE(`partition_name`,@partition_table,'') INTO @has
  17. FROM INFORMATION_SCHEMA.PARTITIONS
  18. WHERE table_name = p_table
  19. ORDER BY partition_ordinal_position DESC LIMIT 1; -- 获得最大的时间分区表
  20. SET @partition_names = '';
  21. IF (@has IS NULL) THEN
  22. SET @partition_names = CONCAT('ALTER TABLE ',p_table,' PARTITION BY RANGE (TO_DAYS(',p_time_field,'))');-- 新建
  23. ELSE
  24. SET @partition_names = CONCAT('ALTER TABLE ',p_table,' ADD PARTITION');-- 添加
  25. END IF;
  26. IF( p_counts IS NULL OR p_counts < 3) THEN
  27. SET p_counts = 3; -- 没有传参数,默认生成指定时间后面三个的分区
  28. END IF;
  29. IF( p_date IS NULL ) THEN
  30. SET p_date = now(); -- 没有传参数,默认从当前时间
  31. END IF;
  32. IF( p_type IS NULL ) THEN
  33. SET p_type = 'month'; -- 没有传参数,默认从当前时间
  34. END IF;
  35. SET @total = p_counts;
  36. SET @month_time = 0;
  37. SET @months = '';
  38. WHILE @month_time < @total DO -- 生成 当前,未来3次分区 (网页文本问题,‹ 不是小于号注意自行修改)
  39. SET @time = DATE_FORMAT( DATE_ADD( p_date , INTERVAL @month_time MONTH) ,'%Y%m'); -- 默认按月分区
  40. SET @date_time = DATE_FORMAT( DATE_ADD( p_date , INTERVAL (@month_time+1) MONTH) ,'%Y-%m-01');
  41. IF(p_type='year') THEN -- 按年分区
  42. SET @time = DATE_FORMAT( DATE_ADD( p_date , INTERVAL @month_time YEAR) ,'%Y');
  43. SET @date_time = DATE_FORMAT( DATE_ADD( p_date , INTERVAL (@month_time+1) YEAR) ,'%Y-01-01');
  44. END IF;
  45. IF(p_type='day') THEN -- 按天分区
  46. SET @time = DATE_FORMAT( DATE_ADD( p_date , INTERVAL @month_time DAY) ,'%Y%m%d');
  47. SET @date_time = DATE_FORMAT( DATE_ADD( p_date , INTERVAL (@month_time+1) DAY) ,'%Y-%m-%d');
  48. END IF;
  49. SET @day_has = NULL;
  50. SELECT partition_name INTO @day_has
  51. FROM INFORMATION_SCHEMA.PARTITIONS
  52. WHERE table_name = p_table AND partition_name = CONCAT('p',@time)
  53. ORDER BY partition_ordinal_position DESC LIMIT 1; -- 查询是否存在分区
  54. IF (@day_has IS NULL AND @total > @month_time ) THEN
  55. SET @months = CONCAT(@months,'PARTITION ',@partition_table,@time,' VALUES LESS THAN (TO_DAYS (''',DATE(@date_time),''')),');
  56. END IF;
  57. SET @month_time = @month_time + 1;
  58. END WHILE;
  59. IF ( length(@months) > 0 AND SUBSTRING(@months,-1) = ',' ) THEN
  60. SET @months = left(@months, length(@months)-1); -- 去掉末尾逗号
  61. END IF;
  62. SET @s1 = '';
  63. IF (@months IS NOT NULL AND @months != '') THEN
  64. SET @s1 = CONCAT(@partition_names,'(',@months,')');
  65. -- 执行生成
  66. PREPARE stmt2 FROM @s1;
  67. EXECUTE stmt2;
  68. DEALLOCATE PREPARE stmt2;
  69. END IF;
  70. SELECT @s1,@days,@has,@partition_names; -- 查看结果
  71. END;;
  72. DELIMITER;
  73. -- 调用
  74. CALL proc_create_partition('user',now(),'pubtime',3,'year') -- 生成user表未来三年分区
  75. CALL proc_create_partition('user',now(),'pubtime',3,'month') -- 生成user表未来三个月分区
  76. CALL proc_create_partition('user',now(),'pubtime',365,'day') -- 生成user表当前时间一整年365天分区

TABLE 创建分表

  1. DROP PROCEDURE IF EXISTS `proc_create_partition_table`;
  2. DELIMITER ;;
  3. CREATE DEFINER=`root`@`%` PROCEDURE `proc_create_partition_table`(
  4. p_dbname varchar(32),-- 数据库
  5. p_table varchar(128), -- 目标表名
  6. p_tag_table varchar(128), -- 模版表名
  7. p_type varchar(12), -- month 按月分表,year按年分表
  8. p_partition_type varchar(12), -- 分区类型,day按天分区,month按月分区
  9. p_date datetime -- 生成指定年月
  10. )
  11. BEGIN
  12. IF( p_date IS NULL ) THEN
  13. SET p_date = now(); -- 没有传参数,默认从当前时间
  14. END IF;
  15. IF( p_type IS NULL ) THEN
  16. SET p_type = 'year'; -- 没有传参数,默认按年
  17. END IF;
  18. SET @table_name = CONCAT(p_table,'_',DATE_FORMAT( p_date ,'%Y')); -- 按年分表
  19. IF(p_type='month') THEN
  20. SET @table_name = CONCAT(p_table,'_',DATE_FORMAT( p_date ,'%Y%m'));-- 按月分表
  21. END IF;
  22. SET @s1 = CONCAT('CREATE TABLE ',@table_name,'(LIKE ',p_tag_table,')');
  23. SET @has_table = 0;
  24. SELECT count(1) INTO @has_table
  25. FROM information_schema.`tables`
  26. where table_type='BASE TABLE' and table_schema = p_dbname and table_name = @table_name;
  27. IF (@has_table = 0) THEN
  28. -- 执行生成表
  29. PREPARE stmt2 FROM @s1;
  30. EXECUTE stmt2;
  31. DEALLOCATE PREPARE stmt2;
  32. SELECT @s1; -- 查看结果
  33. -- 生成分区
  34. IF p_type='year' and p_partition_type = 'day' THEN -- 按年分表,按天分区,
  35. SET @f_day = DATE_FORMAT( p_date ,'%Y-01-01');
  36. CALL proc_create_partition(@table_name, @f_day ,'pubtime', datediff(date_add(@f_day,interval 1 year),@f_day) ,'day');
  37. END IF;
  38. IF p_type='year' and p_partition_type = 'month' THEN -- 按年分表,按月分区,
  39. CALL proc_create_partition(@table_name,DATE_FORMAT( p_date ,'%Y-01-01'),'pubtime',12,'month');
  40. END IF;
  41. IF p_type='month' and p_partition_type = 'day' THEN -- 按月分表,按天分区,
  42. CALL proc_create_partition(@table_name,p_date,'pubtime',day(LAST_DAY(p_date)),'day');
  43. END IF;
  44. ELSE
  45. SELECT 'nothing todo' as result;
  46. END IF;
  47. END;;
  48. DELIMITER;
  49. -- 调用
  50. CALL `fun_create_partition_table`('dbname','user','user','year','month','2020-01-01'); -- 按年分表,按月分区
adddge@sohu.com  | 桂ICP备2022009838号-2