目录

什么是分区表

分区表注意事项:唯一索引

分区表:无法提升性能

分区表:用于数据管理

总结


什么是分区表

简单来说,分区表就是把物理表结构相同的几张表,通过一定算法,组成一张逻辑大表。这种算法叫“分区函数”,当前 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 实现全局唯一;
  • 分区表不解决性能问题,如果使用非分区列查询,性能反而会更差;
  • 分区表的优势在于数据管理、速度快、日志小。