我有一张巨大的表格,存储许多跟踪事件,例如用户点击。
这张表已经超过了数千万行,并且每天都在不断增长。当我尝试从一个较长时间范围内获取事件时,查询开始变慢。阅读了很多相关主题后,我明白分区表可能会提高性能。
我想做的是按月份对表进行分区。
我只找到了手动分区每个月的指南,是否有一种方式可以告诉MySQL按月份分区并自动完成?
如果没有,考虑到我的分区列是日期时间,手动执行分区的命令是什么?
CREATE TABLE ti (id INT, amount DECIMAL(7,2), tr_date DATE)
ENGINE=INNODB
PARTITION BY HASH( MONTH(tr_date) )
PARTITIONS 6;
请注意,这仅按月份进行分区,而不是按年份进行分区,并且在此示例中只有6个分区(因此为6个月)。
如果要对现有表进行分区(手动: https://dev.mysql.com/doc/refman/5.7/en/alter-table-partition-operations.html):
ALTER TABLE ti
PARTITION BY HASH( MONTH(tr_date) )
PARTITIONS 6;
查询可以从整个表中进行:
SELECT * from ti;
或从特定的分区:
SELECT * from ti PARTITION (HASH(MONTH(some_date)));
CREATE TABLE `mytable` (
`post_id` int DEFAULT NULL,
`viewid` int DEFAULT NULL,
`user_id` int DEFAULT NULL,
`post_Date` datetime DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
PARTITION BY RANGE (extract(year_month from `post_Date`))
(PARTITION P0 VALUES LESS THAN (202012) ENGINE = InnoDB,
PARTITION P1 VALUES LESS THAN (202104) ENGINE = InnoDB,
PARTITION P2 VALUES LESS THAN (202108) ENGINE = InnoDB,
PARTITION P3 VALUES LESS THAN (202112) ENGINE = InnoDB,
PARTITION P4 VALUES LESS THAN MAXVALUE ENGINE = InnoDB)
extract(year_month...)
?(在“PARTITION”语句中可以有效使用的表达式非常有限。) - Rick James哈希
按月分区,使用6个分区意味着每年会有两个月落在同一个分区中。那有什么好处呢?
不必分区,对表进行索引。
假设这是您唯一使用的两个查询:
SELECT * from ti;
SELECT * from ti PARTITION (HASH(MONTH(some_date)));
然后使用the_date
开始PRIMARY KEY
。
第一个查询只是读取整个表格;在分区和非分区之间没有变化。
第二个查询,假设您只想要一个月份,而不是映射到同一分区的所有月份,则需要进行以下操作:
SELECT * FROM ti WHERE the_date >= '2019-03-01'
AND the_date < '2019-03-01' + INTERVAL 1 MONTH;
如果您有其他疑问,请告诉我们。
(我没有找到任何性能证明,表明使用 PARTITION BY HASH
是必要的。)
PARTITION BY HASH((YEAR(TIMESTAMP) * 100) + MONTH(TIMESTAMP))
,它可以给出格式良好的日期(例如201511、201512、201601等),与concat函数相同。 - keithl8041