MySQL分区表语法解读
作者:Why9310
MySQL分区表主要用于提高查询效率,通过将数据分割成更小的部分进行管理,文章详细介绍了如何创建、查询、修改和存储分区表,包括创建复合主键、按年份和月份分区、删除分区、查询分区数据以及利用存储过程批量转换非分区表为分区表等方法
MySQL分区表语法
1.创建分区表
分区键需要和主键设置为复合主键,分区表不可直接转换成非分区表,需要重新建非分区表并导入数据
- 按年份
CREATE TABLE partitioned_table_year ( id INT, content VARCHAR(50), created_time DATETIME, PRIMARY KEY (id,created_time) ) PARTITION BY RANGE(YEAR(created_time)) ( PARTITION p2024 VALUES LESS THAN (2025), PARTITION p2025 VALUES LESS THAN (2026), PARTITION p2026 VALUES LESS THAN (2027) );
- 按月份
CREATE TABLE partitioned_table_month ( id INT, content VARCHAR(50), created_time DATETIME, PRIMARY KEY (id,created_time) ) PARTITION BY RANGE COLUMNS(created_time) ( PARTITION p202410 VALUES LESS THAN ('2024-11-01'), PARTITION p202411 VALUES LESS THAN ('2024-12-01'), PARTITION p202412 VALUES LESS THAN ('2025-01-01') );
- 修改表结构,增加分区
ALTER TABLE `partitioned_table_month` MODIFY COLUMN `created_time` datetime(0) NOT NULL , DROP PRIMARY KEY, ADD PRIMARY KEY (`id`, `created_time`) USING BTREE; ALTER TABLE partitioned_table_month PARTITION BY RANGE COLUMNS(created_time) ( PARTITION p202410 VALUES LESS THAN ('2024-11-01'), PARTITION p202411 VALUES LESS THAN ('2024-12-01'), PARTITION p202412 VALUES LESS THAN ('2025-01-01') );
- 删除分区,注意:删除分区的时候会同时删除数据
ALTER TABLE partitioned_table_month DROP PARTITION p202407,p202408;
2.查询
- 查看表分区
SELECT TABLE_NAME, PARTITION_NAME, PARTITION_METHOD, PARTITION_EXPRESSION, PARTITION_DESCRIPTION, TABLE_ROWS, AVG_ROW_LENGTH, DATA_LENGTH, INDEX_LENGTH FROM information_schema.PARTITIONS WHERE TABLE_SCHEMA = 'xxx' and TABLE_NAME = 'partitioned_table_month';
- 查看分区数据
select * from partitioned_table PARTITION (p2024,p2025)
3.利用存储过程批量修改非分区表为分区表
- 创建联合主键存储过程,先设置联合主键字段非空,再删除原id去掉主键,再设置联合主键
DELIMITER $$ DROP PROCEDURE IF EXISTS auto_create_pk$$ CREATE PROCEDURE `auto_create_pk`(IN `table_name` varchar(64),IN `column_name` varchar(64),IN `column_comment` varchar(64)) BEGIN SET @sql = CONCAT("ALTER TABLE `",table_name,"` MODIFY COLUMN `",column_name,"` datetime NOT NULL COMMENT '",column_comment,"', DROP PRIMARY KEY, ADD PRIMARY KEY ( `id`, `",column_name,"` ) USING BTREE;"); PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt; END$$ DELIMITER ;
- 创建按年自动分区存储过程
DELIMITER $$ DROP PROCEDURE IF EXISTS auto_create_partition_year$$ CREATE PROCEDURE `auto_create_partition_year`(IN `table_name` varchar(64),IN `column_name` varchar(64)) BEGIN DECLARE partitioned LONGTEXT; DECLARE n INT; set n = 2025; set partitioned = ''; WHILE n <= 2027 DO SET partitioned = CONCAT(partitioned,",PARTITION p",n," VALUES LESS THAN (",n+1,")"); SET n = n + 1; END WHILE; SET @sql = CONCAT ("ALTER TABLE ",table_name," PARTITION BY RANGE(YEAR(",column_name,")) (",SUBSTR(partitioned,2,LENGTH(partitioned)),");") ; PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt; END$$ DELIMITER ;
- 创建按月自动分区存储过程
DELIMITER $$ DROP PROCEDURE IF EXISTS auto_create_partition_month$$ CREATE PROCEDURE `auto_create_partition_month`(IN `table_name` varchar(64),IN `column_name` varchar(64)) BEGIN DECLARE partitioned LONGTEXT; DECLARE n INT; DECLARE m INT; set n = 2015; set partitioned = ''; WHILE n <= 2030 DO set m = 1; WHILE m < 12 DO SET partitioned = CONCAT(partitioned,",PARTITION p",n,LPAD(m,2,0)," VALUES LESS THAN ('",n,"-",LPAD(m+1,2,0),"-01')"); SET m = m + 1; END WHILE; IF m = 12 THEN SET partitioned = CONCAT(partitioned,",PARTITION p",n,"12 VALUES LESS THAN ('",n+1,"-01-01')"); END IF; SET n = n + 1; END WHILE; SET @sql = CONCAT ("ALTER TABLE ",table_name," PARTITION BY RANGE COLUMNS(",column_name,") (",SUBSTR(partitioned,2,LENGTH(partitioned)),");") ; PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt; END$$ DELIMITER ;
-- 查询存储过程 show procedure status like 'auto_create_partition%'; -- 执行联合主键 CALL auto_create_pk('table_a','a_time','时间'); -- 执行按年自动分区 CALL auto_create_partition_year('table_b','b_time'); -- 执行按月自动分区 CALL auto_create_partition_month('table_c','c_time');
总结
以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。