linux mysql 分区_MySQL分区表使用方法

1. 确认MySQL服务器是否支持分区表

命令:

show plugins;

ec8b9bc21ca255ddc90ef56a8e9e140c.png

2. MySQL分区表的特点

在逻辑上为一个表,在物理上存储在多个文件中

HASH分区(HASH)

HASH分区的特点

根据MOD(分区键,分区数)的值把数据行存储到表的不同分区中

数据可以平均的分布在各个分区中

HASH分区的键值必须是一个INT类型的值,或是通过函数可以转为INT类型

如何建立HASH分区表

以INT类型字段 customer_id为分区键

CREATE TABLE `customer_login_log` (

`customer_id` int(10) unsigned NOT NULL COMMENT '登录用户ID',

`login_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '用户登录时间',

`login_ip` int(10) unsigned NOT NULL COMMENT '登录IP',

`login_type` tinyint(4) NOT NULL COMMENT '登录类型:0未成功 1成功'

) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='用户登录日志表'

PARTITION BY HASH(customer_id) PARTITIONS 4;

以非INT类型字段 login_time 为分区键(需要先转换成INT类型)

CREATE TABLE `customer_login_log` (

`customer_id` int(10) unsigned NOT NULL COMMENT '登录用户ID',

`login_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '用户登录时间',

`login_ip` int(10) unsigned NOT NULL COMMENT '登录IP',

`login_type` tinyint(4) NOT NULL COMMENT '登录类型:0未成功 1成功'

) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='用户登录日志表'

PARTITION BY HASH(UNIX_TIMESTAMP(login_time)) PARTITIONS 4;

customer_login_log 表如果不分区,在物理磁盘上文件为

customer_login_log.frm # 存储表原数据信息

customer_login_log.ibd # Innodb数据文件

如果按上面的建HASH分区表,则有五个文件

customer_login_log.frm

customer_login_log#P#p0.ibd

customer_login_log#P#p1.ibd

customer_login_log#P#p2.ibd

customer_login_log#P#p3.ibd

演示

774cf5c73cb1fb94916b3da358de3e4c.png

f8fb5736f4198dbe94403f8522cf9a48.png

24b316cf47e00135ba7b65b1d601bd88.png

使用起来和不分区是一样的,看起来只有一个数据库,其实有多个分区文件,比如我们要插入一条数据,不需要指定分区,MySQL会自动帮我们处理

f1b18c0fe57170080c2ae566cd66728b.png

查询

51162eeb3cdcb7f1544cfd2e062bcec9.png

范围分区(RANGE)

RANGE分区特点

根据分区键值的范围把数据行存储到表的不同分区中

多个分区的范围要连续,但是不能重叠

默认情况下使用VALUES LESS THAN属性,即每个分区不包括指定的那个值

如何建立RANGE分区

5c1ef3e3966ce7f6b53fe105e1809a11.png

如果没有定义p3分区,当插入的customer_id大于29999时会报错,定义了则超过的数据都存入p3中

RANGE分区的适用场景

分区键为日期或是时间类型 (可以使得各个分区表的数据比较均衡,如果按上面的例子中以整型id为分区键,假如活跃用户集中在10000-19999之间,则p1中的数据量就会比其他分区的数据量大很多,这就失去了分区的意义;而且按时间类型分区,如果要按时间顺序进行数据的归档,则只需要对某一个分区进行归档就可以了)

所有查询中都包括分区键(避免跨分区查询)

定期按分区范围清理历史数据

LIST分区

LIST分区的特点

按分区键取值的列表进行分区

同范围分区一样,各分区的列表值不能重复

每一行数据必须能找到对应的分区列表,否则数据插入失败

如何建立LIST分区

71b3f79110387ae7458062d6944da58e.png

如果插入一条login_type为10的数据行,则会报错

3. 如何为登录日志表(customer_login_log)分区

业务场景

用户每次登录都会记录customer_login_log日志

用户登录日志保存一年,1年后可以删除或者归档

登录日志表的分区类型及分区键

使用RANGE分区

以login_time为分区键

分区后的用户登录日志表

按年份分区存储,所以用YEAR函数进行了转化

CREATE TABLE `customer_login_log` (

`customer_id` int(10) unsigned NOT NULL COMMENT '登录用户ID',

`login_time` DATETIME NOT NULL COMMENT '用户登录时间',

`login_ip` int(10) unsigned NOT NULL COMMENT '登录IP',

`login_type` tinyint(4) NOT NULL COMMENT '登录类型:0未成功 1成功'

) ENGINE=InnoDB

PARTITION BY RANGE (YEAR(login_time))(

PARTITION p0 VALUES LESS THAN (2017),

PARTITION p1 VALUES LESS THAN (2018),

PARTITION p2 VALUES LESS THAN (2019)

)

插入并查询数据

dbf235dd148bbcc74be603a07c3b73d2.png

查询指定表中的分区数据情况

SELECT table_name,partition_name,partition_description,table_rows FROM

information_schema.`PARTITIONS` WHERE table_name = 'customer_login_log';

ca31e858a8a80d1a25f58fa1b01adb81.png

再插入2条18年的日志,会存入p2表中

01f070bb10c1d948a12e2ab4b4ae9f56.png

之前说过建立分区表时,最好建立一个MAXVALUE的分区,这里之所以没有建立,是为了数据维护的方便,如果我们建立了MAXVALUE分区,很容易忽视一个问题,当我们2019年有的数据插入时,会自动存入那个MAXVALUE分区中,之后在做数据维护时会不方便,所以没有建立MAXVALUE分区

而是通过计划任务的方式,在每年年底的时候增加这个分区,比如我们现在在2018年年底,我们需要在日志表中为2019年建立日志分区,否则2019年的日志都会插入失败

f1f8de7aa39c9de7a7044fcce8f43c73.png

我们可以通过下面语句

增加分区

ALTER TABLE customer_login_log ADD PARTITION (PARTITION p3 VALUES LESS THAN(2020))

增加分区,并插入数据

6c87466d5ab293cfb31f8a5dc02705f2.png

删除分区

假如我们现在要删除2016年到2017年间一年的数据,因为我们已经做了分区,所以只需要通过一条语句,删除p0分区即可

ALTER TABLE customer_login_log DROP PARTITION p0;

356393eb87d586997cf7020d4395f524.png

可以发现p0分区已被删除,且2016年的日志全部被清除了

归档分区历史数据

我们可能有另一种需求对数据进行归档

Mysql版本>=5.7,归档分区历史数据非常方便,提供了一个交换分区的方法

分区数据归档迁移条件:

MySQL>=5.7

结构相同

归档到的数据表一定要是非分区表

非临时表;不能有外键约束

归档引擎要是:archive

建表并交换分区

CREATE TABLE `arch_customer_login_log` (

`customer_id` INT unsigned NOT NULL COMMENT '登录用户ID',

`login_time` DATETIME NOT NULL COMMENT '用户登录时间',

`login_ip` INT unsigned NOT NULL COMMENT '登录IP',

`login_type` TINYINT NOT NULL COMMENT '登录类型:0未成功 1成功'

) ENGINE=InnoDB ;

ALTER TABLE customer_login_log

exchange PARTITION p1 WITH TABLE arch_customer_login_log;

d32300eed533700637a02d3532bcb5e4.png

e30f8eec53395fe500bec8dfb568785c.png

3fbf28065814a67ea6190b5da8245269.png

可以发现,原customer_login_log表中的2017年的数据(p1分区中的数据)已转移到了arch_customer_login_log表中,但是p1分区未删除,只是数据转移了,所以我们还需要执行DROP命令删除分区,以免有数据插入其中

将归档数据的存储引擎改为归档引擎

最后我们将归档数据的存储引擎改为归档引擎,命令为

ALTER TABLE customer_login_log ENGINE=ARCHIVE;

使用归档引擎的好处是:它比Innodb所占用的空间更少,但是归档引擎只能进行查询操作,不能进行写操作

4. 使用分区表的主要事项

结合业务场景选择分区键,避免跨分区查询

对分区表进行查询最好在WHERE从句中包含分区键

具有主键或唯一索引的表,主键或唯一索引必须是分区键的一部分(这也是为什么我们上面分区时去掉了主键登录日志id(login_id)的原因,不然就无法按照上面的按年份进行分区,所以分区表其实更适合在MyISAM引擎中)

关于MyISAM和Innodb的索引区别

1.关于自动增长

myisam引擎的自动增长列必须是索引,如果是组合索引,自动增长可以不是第一列,他可以根据前面几列进行排序后递增。

innodb引擎的自动增长咧必须是索引,如果是组合索引也必须是组合索引的第一列。

2.关于主键

myisam允许没有任何索引和主键的表存在,

myisam的索引都是保存行的地址。

innodb引擎如果没有设定主键或者非空唯一索引,就会自动生成一个6字节的主键(用户不可见)

innodb的数据是主索引的一部分,附加索引保存的是主索引的值。

3.关于count()函数

myisam保存有表的总行数,如果select count(*) from table;会直接取出出该值

innodb没有保存表的总行数,如果使用select count(*) from table;就会遍历整个表,消耗相当大,但是在加了wehre 条件后,myisam和innodb处理的方式都一样。

4.全文索引

myisam支持 FULLTEXT类型的全文索引

innodb不支持FULLTEXT类型的全文索引,但是innodb可以使用sphinx插件支持全文索引,并且效果更好。(sphinx 是一个开源软件,提供多种语言的API接口,可以优化mysql的各种查询)

5.delete from table

使用这条命令时,innodb不会从新建立表,而是一条一条的删除数据,在innodb上如果要清空保存有大量数据的表,最 好不要使用这个命令。(推荐使用truncate table,不过需要用户有drop此表的权限)

6.索引保存位置

myisam的索引以表名+.MYI文件分别保存。

innodb的索引和数据一起保存在表空间里。

0b1331709591d260c1c78e86d0c51c18.png

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
MySQL分区是一种将大型表水平分成多个部分的技术,这有助于提高查询和数据管理的效率。在 MySQL 中,可以使用 RANGE、LIST、HASH 和 KEY 四种分区类型来定义分区方式。 下面是 MySQL分区的详细操作步骤: 1. 创建表时定义分区方式 在创建表的时候,可以指定表的分区方式。例如,使用 RANGE 分区方式将表按照数值范围进行分区: ``` CREATE TABLE mytable ( id INT, value INT ) PARTITION BY RANGE (value) ( PARTITION p0 VALUES LESS THAN (10), PARTITION p1 VALUES LESS THAN (20), PARTITION p2 VALUES LESS THAN (MAXVALUE) ); ``` 2. 插入数据 向表中插入数据时,MySQL 会自动将数据插入到正确的分区中。例如,插入一个 value 值为 5 的数据: ``` INSERT INTO mytable (id, value) VALUES (1, 5); ``` 3. 查询数据 在查询数据时,MySQL 可以仅查询特定的分区,而不必扫描整个表。例如,查询 value 值在 10 到 20 之间的数据: ``` SELECT * FROM mytable PARTITION (p1); ``` 4. 修改分区 可以使用 ALTER TABLE 语句修改表的分区方式,例如,将表从 RANGE 分区方式修改为 HASH 分区方式: ``` ALTER TABLE mytable PARTITION BY HASH(value) PARTITIONS 4; ``` 5. 合并分区 可以使用 ALTER TABLE 语句将相邻的分区合并为一个分区,例如,将分区 p1 和 p2 合并为一个分区: ``` ALTER TABLE mytable COALESCE PARTITION p1, p2 INTO p3; ``` 6. 删除分区 可以使用 ALTER TABLE 语句删除表的某个分区,例如,删除分区 p0: ``` ALTER TABLE mytable DROP PARTITION p0; ``` 以上就是 MySQL分区的详细操作步骤,可以根据实际需求选择不同的分区方式来提高查询和数据管理的效率。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值