使用存储过程和事件调度程序在 mysql 中动态创建分区

Mee*_*bhi 2 mysql database-partitioning

我有一个表,我想在其上创建自动分区方案,首先按月对表进行分区,然后按 id 进行子分区。

我最近了解到mysql不支持自动分区,创建动态分区的唯一方法是通过存储过程和事件调度程序。

我的要求是新条目自动创建到新分区中,一年后自动删除旧记录。

我该怎么做呢?

请建议我一些关于如何实现存储过程和事件调度程序以支持动态分区并自动删除旧记录的方法。

这是架构:

CREATE TABLE `ORDER_HISTORY` (
  `Id` bigint(20) NOT NULL,
  `Invoice_Number` varchar(16) NOT NULL,
  `User_Id` int(10) NOT NULL,
  `Store_ID` mediumint(6) NOT NULL,
  `Store_Entity_Id` mediumint(8) NOT NULL,
  `Item_List` blob NOT NULL,
  `Order_Time` datetime NOT NULL,
  `Payment_Time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
  `Payment_Type` tinyint(2) NOT NULL,
  `Payment_Retry_Attempts` tinyint(1) NOT NULL,
  `Payment_TransactionID` varchar(32) NOT NULL,
  `Sub_Total_Amount` decimal(10,2) NOT NULL DEFAULT '0.00',
  `CGST_Tax_Amount` decimal(6,2) NOT NULL DEFAULT '0.00',
  `SGST_Tax_Amount` decimal(6,2) NOT NULL DEFAULT '0.00',
  `Other_Tax_Amount` decimal(6,2) NOT NULL DEFAULT '0.00',
  `Service_Fee` decimal(6,2) NOT NULL DEFAULT '0.00',
  `Earned_Cashback_Amount` decimal(4,2) NOT NULL DEFAULT '0.00',
  `Used_Cashback_Amount` decimal(4,2) NOT NULL DEFAULT '0.00',
  `Used_Coupon` mediumint(8) DEFAULT NULL,
  `Used_Coupon_Discount` decimal(4,2) NOT NULL DEFAULT '0.00',
  `Grand_Total_Amount` decimal(10,2) NOT NULL DEFAULT '0.00',
  `Status` tinyint(3) NOT NULL,
  `Manager_Id` smallint(5) DEFAULT NULL,
  `Store_Name` varchar(32) DEFAULT NULL,
  `User_Name` varchar(32) DEFAULT NULL,
  `User_Phone_Number` varchar(10) DEFAULT NULL,
  `Manager_Phone_Number` varchar(10) NOT NULL,
  `Manager_Name` varchar(32) DEFAULT NULL,
  PRIMARY KEY (`Id`),
  UNIQUE KEY `Id_UNIQUE` (`Id`),
  KEY `Store_ID_idx` (`Store_ID`),
  KEY `Table_ID_idx` (`Store_Entity_Id`),
  KEY `Phone_Number_idx` (`User_Id`),
  KEY `oh_payment_type_id_fk_idx` (`Payment_Type`),
  KEY `oh_coupon_id_fk_idx` (`Used_Coupon`),
  KEY `oh_status_id_fk_idx` (`Status`),
  KEY `oh_manager_id_fk` (`Manager_Id`),
  CONSTRAINT `oh_coupon_id_fk` FOREIGN KEY (`Used_Coupon`) REFERENCES `COUPONS` (`Id`) ON DELETE CASCADE ON UPDATE CASCADE,
  CONSTRAINT `oh_manager_id_fk` FOREIGN KEY (`Manager_Id`) REFERENCES `MANAGER` (`Id`),
  CONSTRAINT `oh_payment_type_id_fk` FOREIGN KEY (`Payment_Type`) REFERENCES `PAYMENT_TYPES` (`Id`) ON DELETE CASCADE ON UPDATE CASCADE,
  CONSTRAINT `oh_status_id_fk` FOREIGN KEY (`Status`) REFERENCES `STATUS` (`Id`) ON DELETE CASCADE ON UPDATE CASCADE,
  CONSTRAINT `oh_store_entity_id_fk` FOREIGN KEY (`Store_Entity_Id`) REFERENCES `STORE_ENTITY` (`Id`) ON DELETE CASCADE ON UPDATE CASCADE,
  CONSTRAINT `oh_store_id_fk` FOREIGN KEY (`Store_ID`) REFERENCES `STORE` (`Id`) ON DELETE CASCADE ON UPDATE CASCADE,
  CONSTRAINT `oh_user_id_fk` FOREIGN KEY (`User_Id`) REFERENCES `USERS` (`Id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=latin1
Run Code Online (Sandbox Code Playgroud)

提前致谢!

gvg*_*yan 5

首先,分区是您遇到的问题的最佳用例。原因是您使用的存储引擎innodb是基于事务的引擎。因此,它将所有完成的操作记录在日志中,从而获得更高的I/O资源。即使删除也需要更多资源。但是带有子分区的分区是多余的,因为您需要每年清理一次表数据,因此您可以使用每年运行一次的作业RANGE COLUMN子句。cron

partition您可以通过执行以下命令来检查您的 MySQL 支持:

SHOW PLUGINS;
Run Code Online (Sandbox Code Playgroud)

这将显示一个表格数据,请检查您partitionnameACTIVE中的数据Status

分区类型:

有两种类型的分区。第一种是垂直分区(按列分区),MySQL 不支持这种分区;第二种是水平分区(按行分区)。

分区定义:

        PARTITION partition_name
        [VALUES
            {LESS THAN {(expr | value_list) | MAXVALUE}
            |
            IN (value_list)}]
        [[STORAGE] ENGINE [=] engine_name]
        [COMMENT [=] 'string' ]
        [DATA DIRECTORY [=] 'data_dir']
        [INDEX DIRECTORY [=] 'index_dir']
        [MAX_ROWS [=] max_number_of_rows]
        [MIN_ROWS [=] min_number_of_rows]
        [TABLESPACE [=] tablespace_name]
        [(subpartition_definition [, subpartition_definition] ...)]
Run Code Online (Sandbox Code Playgroud)

解决方案:

第 1 步: 使用分区更改表架构,如下所示(参考链接 3)

CREATE TABLE members (
    firstname VARCHAR(25) NOT NULL,
    lastname VARCHAR(25) NOT NULL,
    username VARCHAR(16) NOT NULL,
    email VARCHAR(35),
    joined DATE NOT NULL
)
PARTITION BY RANGE COLUMNS(joined) (
    /*PARTITION y2013 VALUES LESS THAN ('2014-01-01'),
    PARTITION y2014 VALUES LESS THAN ('2015-01-01'),
    PARTITION y2015 VALUES LESS THAN ('2016-01-01'),
    PARTITION y2016 VALUES LESS THAN ('2017-01-01'),*/ #This are older partition it may deleted before 2017 itself
    PARTITION y2017 VALUES LESS THAN ('2018-01-01'),
    PARTITION future VALUES LESS THAN MAXVALUE
);
Run Code Online (Sandbox Code Playgroud)

第 2 步: 您可以使用任何编程语言(例如 PHP、Ruby、Python、Perl)动态创建此查询。考虑这是使用 cron 于 2019 年 1 月 1 日运行的。

ALTER TABLE members 
    DROP PARTITION y2017;
ALTER TABLE members 
    REORGANIZE PARTITION future INTO
        y2018 VALUES LESS THAN ('2019-01-01'),
        future VALUES LESS THAN MAXVALUE;
Run Code Online (Sandbox Code Playgroud)

查询获取前几年的格式:

SELECT concat('Y', YEAR(DATE_SUB(CURDATE(), INTERVAL 1 YEAR))) as prev_year
Run Code Online (Sandbox Code Playgroud)

更改间隔以进一步增加年份。

步骤 3: 使用任何调度程序(如 cron)每年执行一次上述查询。例如

@yearly /home/meenu/ubuntu/bin/annual-maintenance.sh
Run Code Online (Sandbox Code Playgroud)

参考:

更多关于分区的信息:

  1. 创建表分区

  2. 分区官方文档

  3. 分区范围

克朗:

  1. 带有解释的 Cron 示例

  2. 定期运行 MySQL 查询

大删除:

  1. Big删除各种替代品

分区维护:

  1. 分区维护