mysql数据库分表

先说一下我的版本和场景,如何你情况和我相同,可以参考,否则,就不浪费你宝贵的时间了。

版本:5.7.34  (select version()返回)

场景:每天大概产生2000w数据,需要入库,且一段时间后(30天)需要删除旧数据。如果插入到一张表,那么后果不可设想。且在删除数据时,根据时间条件根本就查不出来数据。

如果解决了你的问题,请点个赞。

分区的建表SQL:

CREATE TABLE `t_alarm` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',
  `alarm_type` int NOT NULL COMMENT '告警类型',
  `alarm_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '告警产生时间',
  `content` longtext,
  PRIMARY KEY (`id`, `alarm_time`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='告警表'
PARTITION BY RANGE(TO_DAYS(alarm_time))(
    PARTITION p20230831 VALUES less than (TO_DAYS('20230901')),
    PARTITION p20230901 VALUES less than (TO_DAYS('20230902')),
    PARTITION p20230902 VALUES less than (TO_DAYS('20230903')),
    PARTITION p20230903 VALUES less than (TO_DAYS('20230904')),
);

解释下:

  1. primary key必须包含分区的判断字段(alarm_time),否则,语法会报错,建议设置id和分区字段的复合主键,即PRIMARY KEY (`id`, `send_time`)。
  2. p20230831是分区表的名称,插入条件是日期小于明天,相当于是今天, TO_DAYS会把日期转为数字,在插入时,MYSQL会自己判断,然后插入到对应的分区中。

如何查询数据?

查询时,select * from t_alarm 可以直接查询,系统会自动查询所有分区的数据,如果要指定分区,那么,在查询条件中限定alarm_time的值即可。即select * from t_alarm where alarm_time >= '20230101' and alarm_time <= '20230105',如果时间不是连续的,即我要查询1,3,5号的数据,那么直接拼接对应的条件即可,无非就是多加几个 or 条件。

如何查看所有分区的情况和每个分区的记录数?

SQL为:

SELECT TABLE_NAME,PARTITION_NAME, TABLE_ROWS FROM INFORMATION_SCHEMA.PARTITIONS WHERE TABLE_SCHEMA = 'test' AND TABLE_NAME = 'alarm';

 schema和table名字,请自行换成自己的。

如何增加分区?

ALTER TABLE alarm ADD PARTITION 
(
    PARTITION p20230903 VALUES LESS THAN (to_days('2022-09-04'))
);

请自行修改分区名和条件。

如何删除分区?

ALTER TABLE alarm DROP PARTITION p20230831;

如何自动新增和删除旧分区?

如果你使用的是java或者Python,那么,需要你自己写个周期函数了,然后去拼接SQL语句,使用SqlSession去执行SQL。

注意:如果系统时间不对,那么可能会把业务数据清除。所以,不建议添加自动删除分区的逻辑。如果需要这个功能,可以保留接口,在界面手动触发。

你可能感兴趣的:(数据库,mysql)