目录
什么是分区表
分区表注意事项:唯一索引
分区表:无法提升性能
分区表:用于数据管理
总结
什么是分区表
简单来说,分区表就是把物理表结构相同的几张表,通过一定算法,组成一张逻辑大表。这种算法叫“分区函数”,当前 MySQL 数据库支持的分区函数类型有 RANGE、LIST、HASH、KEY、COLUMNS。无论选择哪种分区函数,都要指定相关列成为分区算法的输入条件,这些列就叫“分区列”。
在 MySQL 分区表中,分区表的主键一定要包含分区函数的列,唯一索引也一定要包含分区函数的列。
--创建分区表
CREATE TABLE t (
a INT,
b INT,
c DATETIME,
d VARCHAR(32),
PRIMARY KEY (a,b,c)
)
PARTITION BY RANGE COLUMNS(c) (
PARTITION p0000 VALUES LESS THAN ('2019-01-01'),
PARTITION p2019 VALUES LESS THAN ('2020-01-01'),
PARTITION p2020 VALUES LESS THAN ('2021-01-01'),
PARTITION p9999 VALUES LESS THAN (MAXVALUE)
);
--生成四张表:t#p#p0000.ibd t#p#p2019.ibd t#p#p2020.ibd t#p#p9999.ibd
--增加唯一索引
ALTER TABLE t ADD UNIQUE KEY idx_d(d,c);
分区表注意事项:唯一索引
在 MySQL 数据库中,分区表的索引都是局部,而非全局。也就是说,索引在每个分区文件中都是独立的,所以分区表上的唯一索引必须包含分区列信息,否则创建会报错。
那如何实现全局唯一索引呢? 和之前表结构设计时一样,使用全局唯一的字符串(如类似 UUID 的实现)。
分区表:无法提升性能
分区表技术不是用于提升 MySQL 数据库的性能。
以上面的分区表t为例,我们根据时间拆成每年一张表,这时虽然 B+ 树的高度从 4 降为了 3,但是这个提升微乎其微。除此之外,分区表还会引入新的性能问题,比如非分区列的查询。即使分区列上已经创建了索引,但因为索引是每个分区文件对应的本地索引,所以要查询每个分区。假设需要访问 4 个分区,每个分区需要 3 次 I/O,则总共要 12 次 I/O。但是如果使用普通表,也就 4 次 I/O 的时间。
所以,分区表设计时,务必使得查询条件都带有分区字段,否则会扫描所有分区的数据或索引。
分区表:用于数据管理
分区表技术是方便数据的管理,更多的是解决数据迁移和备份的问题。
在某个场景下,我们需要删除某一年的历史数据,使用普通表时用delete … from …where …删除,可这条 SQL 的执行相当慢,产生大量二进制日志,在生产系统上也会导致数据库主从延迟的问题。
DELETE FROM t
WHERE c >= '2019-01-01'
AND c < '2020-01-01'
而使用分区表的话,直接使用清空分区的命令就行。这条SQL 执行非常快,因为实际执行过程是把分区文件删除和重建。另外也只产生一条 DDL 日志,也不会导致主从复制延迟问题。
ALTER TABLE t
TRUNCATE PARTITION p2019
总结
- 当前 MySQL 的分区表支持 RANGE、LIST、HASH、KEY、COLUMNS 等分区算法;
- 分区表的创建需要主键包含分区列,唯一索引包含分区列;
- 在分区表中唯一索引仅在当前分区文件唯一,而不是全局唯一。分区表唯一索引推荐使用类似 UUID 实现全局唯一;
- 分区表不解决性能问题,如果使用非分区列查询,性能反而会更差;
- 分区表的优势在于数据管理、速度快、日志小。