一般在数据库设计中,要谨慎的使用分区表。
原因:1、分区表在物理上表现为多个文件,在逻辑上表现为一个表。
原因:2、谨慎的使用分区键,跨分区查询效率可能更低
建议采用物理分表的方式管理大数据。
但在特定的数据库模型中,分区表的表现是非常不错的。
如何使用Mysql服务器分区表
1.首先确认MySQL服务器是 否支持分区表
show plugins
如果出现partition证明是支持的。
建标语句之比正常的语句多出来那么点。
物理文件对比
Mysql分区类型一、按HASH分区
特点:根据MOD(分区建,分区数)的值把数据行 存储到表的不同分区中。数据可以平均的分布在各个分区中。HASH分区的建值必须是一个INT类型的值,或是通过函数可以转为INT类型。
如:直接用主键直接做键值分区、如上上图。
如:用非INT型数据可用MYSQL函数转为INT型。
create table `customer_login_log`(
`customer_id` INT(10) UNSIGNED NOT NULL,
`login_time` TIMESTAMP NOT NULL,
`login_ip` INT(10) UNSIGNED NOT NULL,
`login_type` TINYINT(4) NOT NULL
)ENGINE=INNODB
PARTITION BY HASH(UNIX_TIMESTAMP(login_time))
PARTITIONS 4;
可以建立哈希分区可以转INT型的函数列表
Mysql分区类型二、案范围分区(RANGE)
RANGE分区特点:1、根据分区键值得范围把数据行存储到表的不同分区中。2、多个分区的范围要连续,但是不能重叠。3、默认情况下使用VALUES LESS THAN属性,既每个分区不包括指定的那个值
建表语句
create table `customer_login_log`(
`customer_id` INT(10) UNSIGNED NOT NULL,
`login_time` TIMESTAMP NOT NULL,
`login_ip` INT(10) UNSIGNED NOT NULL,
`login_type` TINYINT(4) NOT NULL
)ENGINE=INNODB
PARTITION BY RANGE (customer_id)(
PARTITION p0 VALUES LESS THAN (1000),
PARTITION p1 VALUES LESS THAN (2000),
PARTITION p2 VALUES LESS THAN (3000),
PARTITION p3 VALUES LESS THAN MAXVALUE
);
RANGE分区的使用场景
1、分区键为日期或时间类型,2、适合定期按分区范围清理历史数据。
注意:所有查询中都应该包过分区的键,避免跨分区查询
MYSQL分区类型三、LIST分区
LIST分区的特点:1、按分区键取值得列表进行分区。2、同范围分区一样,各分区的列表值不能重复。3、每一行数据必须能找到对应的分区列表,否则数据插入失败
create table `customer_login_log`(
`customer_id` INT(10) UNSIGNED NOT NULL,
`login_time` TIMESTAMP NOT NULL,
`login_ip` INT(10) UNSIGNED NOT NULL,
`login_type` TINYINT(4) NOT NULL
)ENGINE=INNODB
PARTITION BY LIST (login_type)(
PARTITION p0 VALUES in (1,3,5,7,9),
PARTITION p1 VALUES in (2,4,6,8)
);
如果这时候插入login_type=10的数据那么,则会报错。
最适用登录日志表等
适用RANGE分区、以年份做条件、以login_time作为分区键
create table `customer_login_log`(
`customer_id` INT(10) UNSIGNED NOT NULL,
`login_time` DATETIME NOT NULL,
`login_ip` INT(10) UNSIGNED NOT NULL,
`login_type` TINYINT(4) NOT NULL
)ENGINE=INNODB
PARTITION BY RANGE (YEAR(login_time))(
PARTITION p0 VALUES LESS THAN (2018),
PARTITION p1 VALUES LESS THAN (2019)
);
需要注意的:这里的login_time类型是DATETIME不是TIMESTAMP。如果是TS则会报错。
插入两条数据查看分区信息
SQL语句
select table_name,partition_name,partition_description,table_rows
from information_schema.`PARTITIONS`
WHERE table_name='customer_login_log';
两条数据2018>2019房子啊P1分区里了,2017同理。
在每年的年底要做好修改并添加分区的计划任务
用alter语句添加分区
ALTER TABLE customer_login_log ADD PARTITION (
PARTITION p3 VALUES LESS THAN(2020));
删除一个分区
ALTER TABLE customer_login_log DROP PARTITION p0;
删除过期数据非常便捷
数据归档(5.7版本)
1、要求Mysql>=5.7。2、结构相同。归档到数据表一定要是非分区表。4.非临时表;不能有外键约束。5、归档引擎要是:archive.
新建个非分区表
create table `arch_customer_login_log`(
`customer_id` INT(10) UNSIGNED NOT NULL,
`login_time` DATETIME NOT NULL,
`login_ip` INT(10) UNSIGNED NOT NULL,
`login_type` TINYINT(4) NOT NULL
)ENGINE=INNODB
交换分区语句
ALTER TABLE customer_login_log exchange PARTITION p1
WITH TABLE arch_customer_login_log;
注意事项
合理的设计于使用分区表,
对分区表进行查询最好在WHERE从句中包含分区键,之前的表是那login_time做的分区键,
具有主键或唯一索引的表,主键或唯一索引必须是分区键的一部分