Mysql根据创建时间表分区实践

背景

最近订单表遇到大数据量的问题,并且表中随着时间的积累会变得更大,当数据量较大时,存储的物理文件会变得非常大、使用性能很差。
我们用的是GaussDB。为了提高查询效率,建议表大于500w进行分区,所以在规划阶段我们就进行分区。根据公司业务发展评估,按照年进行表分区。目的就是缓解磁盘io,提高查询效率。

解决方式

文件太大,常用思路是拆表、减少单表数据量,这样每个表文件变小、性能和维护都会更容易。
一般有两种拆分方式:
水平拆分。即同个结构的表建多个,按一定规则将不同的行放到不同的表。
按主键、数据所属用户或其他列,使用Hash、一致性Hash、Hash字典等方式
垂直拆分。将不同的表放到不同的数据库。
一般按业务模块拆分。

方式:MySQL partition

根据我的的需求,按照创建时间按照年分区
分区命令:
将表ar_sale_order_to_c 根据创建时间creation_date
创建时间格式为:(2023-07-04 04:30:29),需要用年,所以通过函数 YEAR(creation_date) 获取字段年,然后进行分区

ALTER TABLE ar_sale_order_to_c PARTITION BY RANGE (YEAR(creation_date)) (
PARTITION p2020 VALUES LESS THAN (2021),
PARTITION p2021 VALUES LESS THAN (2022),
PARTITION p2022 VALUES LESS THAN (2023),
PARTITION p2023 VALUES LESS THAN (2024),
PARTITION p2024 VALUES LESS THAN (2025),
PARTITION p2025 VALUES LESS THAN (2026),
PARTITION p2026 VALUES LESS THAN (2027),
PARTITION p2027 VALUES LESS THAN (2028),
PARTITION p2028 VALUES LESS THAN (2029),
PARTITION p2029 VALUES LESS THAN (2030),
PARTITION p202X VALUES LESS THAN (MAXVALUE)
);

常见问题

分区键(用来分区的列)须同时存在于所有的primary key和unique key中,这是最容易出现问题。
我的表结构:

CREATE TABLE `ar_sale_order_to_c` (
  `order_id` bigint NOT NULL AUTO_INCREMENT,
  `order_number` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL COMMENT '订单号',
  `company_code` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL COMMENT '所属公司',
  `sales_organization` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL COMMENT '销售组织(弃用)',
  `batch_number` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL COMMENT '订单批次号',
  `source_system` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL COMMENT '来源系统',
  `order_type` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL COMMENT '订单类型',
  `rcc_status` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL COMMENT '对账状态',
  `rcc_date` datetime DEFAULT NULL COMMENT '对账完成时间',
  `order_reason` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL COMMENT '订单原因',
  `source_platform` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL COMMENT '来源平台',
  `platform_order_number` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL COMMENT '来源平台订单号',
  `currency` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL COMMENT '币种',
  `client` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL COMMENT '客户(shop_code)',
  `manual_orders_flag` varchar(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL COMMENT '是否为手工订单',
  `source_number` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL COMMENT '关联订单编号',
  `distribute_channel` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL COMMENT '分销渠道',
  `interface_call_time` datetime DEFAULT NULL COMMENT '接口时间戳',
  `statement_number` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL COMMENT '原始账单号',
  `discount_amount` decimal(20,6) DEFAULT NULL COMMENT '优惠金额',
  `order_create_time` datetime DEFAULT NULL COMMENT '订单时间戳',
  `merchant_remarks` varchar(1000) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL COMMENT '商家备注',
  `shipping_location` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL COMMENT '发货库位',
  `sales_channel` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL COMMENT '销售渠道',
  `sales_channel_des` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL COMMENT '销售渠道描述',
  `delivery_gen_flag` varchar(2) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT 'N' COMMENT '是否生成为交货单确认信息',
  `tenant_id` bigint NOT NULL DEFAULT '0' COMMENT '租户ID',
  `object_version_number` bigint DEFAULT '1' COMMENT '行版本号,用来处理锁',
  `creation_date` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
  `created_by` bigint NOT NULL DEFAULT '-1',
  `last_update_date` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
  `last_updated_by` bigint NOT NULL DEFAULT '-1',
  `partion_value` bigint DEFAULT NULL COMMENT '分库值',
  PRIMARY KEY (`order_id`) USING BTREE,
  UNIQUE KEY `ar_sale_order_to_c_u1` (`order_number`,`tenant_id`) USING BTREE,
  KEY `ar_sale_order_to_c_n1` (`statement_number`,`tenant_id`) USING BTREE,
  KEY `ar_sale_order_to_c_n3` (`source_platform`,`tenant_id`) USING BTREE,
  KEY `ar_sale_order_to_c_n4` (`platform_order_number`,`tenant_id`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=5299 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin ROW_FORMAT=DYNAMIC COMMENT='订单头(C端)';


因为我的分区键(用来分区的列)没有同时存在于所有的primary key和unique key中。所以创建分区键会报错

1、分区键不在primary key
报错提示:

A PRIMARY KEY must include all columns in the table's partitioning function

解决方式:
在 primary key中增加分区键creation_date

alter table ar_sale_order_to_c drop primary key,add primary key (`order_id`,`creation_date`); 

2、分区键不在unique key

报错提示:

A UNIQUE INDEX must include all columns in the table's partitioning function

解决方式
在unique key中增加分区键creation_date

alter table ar_sale_order_to_c drop index `ar_sale_order_to_c_u1`;
alter table ar_sale_order_to_c add unique key `ar_sale_order_to_c_u1` (`order_number`,`tenant_id`,`creation_date`);

最后:在重新执行以上得创建分区命令。

验证

为了验证以下两张表一个分区一个没有分区,数据都是一样得
ar_sale_order_line_to_c_no_partition(为分区)
ar_sale_order_line_to_c_partition(已分区)
未分区得表示例查询扫描4910872条数据
在这里插入图片描述
分区后表查询示例扫描:1984
在这里插入图片描述

执行时间:
在这里插入图片描述

结论

分区后,查询效率极大得提升

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
MySQL数据库分区是一种将大型表分解为更小和更可管理的部分的技术。它可以提高查询性能,减少维护时间和成本。以下是MySQL数据库分区的一些方法和步骤: 1. RANGE分区:按照给定的连续范围将数据行分配到分区中。例如,可以按照日期范围将数据行分配到不同的分区中。 2. LIST分区:与RANGE分区类似,但是使用枚举值而不是连续范围来定义分区。例如,可以按照国家/地区将数据行分配到不同的分区中。 3. HASH分区:使用用户定义的表达式计算每个数据行的哈希值,并将数据行分配到哈希值对应的分区中。例如,可以按照客户ID将数据行分配到不同的分区中。 4. KEY分区:类似于HASH分区,但是使用MySQL关键字来计算哈希值。例如,可以按照自增ID将数据行分配到不同的分区中。 以下是一个创建MySQL数据库分区的例子: ```sql CREATE TABLE sales ( id INT NOT NULL, region VARCHAR(100) NOT NULL, country VARCHAR(100) NOT NULL, amount DECIMAL(10,2) NOT NULL, date DATE NOT NULL ) PARTITION BY RANGE(YEAR(date)) ( PARTITION p0 VALUES LESS THAN (2010), PARTITION p1 VALUES LESS THAN (2011), PARTITION p2 VALUES LESS THAN (2012), PARTITION p3 VALUES LESS THAN (2013), PARTITION p4 VALUES LESS THAN MAXVALUE ); ``` 以上代码将sales表按照日期范围分为5个分区。第一个分区包含2010年之前的数据,第二个分区包含2010年的数据,以此类推,最后一个分区包含所有未包含在前面分区中的数据。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值