• 企业400电话
  • 网络优化推广
  • AI电话机器人
  • 呼叫中心
  • 全 部 栏 目

    网站建设 商标✡知产 微网小程序 电商运营 彩铃•短信 增值拓展业务
    MySQL分区表的正确使用方法
    POST TIME:2021-10-18 20:41

    MySQL分区表概述

    我们经常遇到一张表里面保存了上亿甚至过十亿的记录,这些表里面保存了大量的历史记录。 对于这些历史数据的清理是一个非常头疼事情,由于所有的数据都一个普通的表里。所以只能是启用一个或多个带where条件的delete语句去删除(一般where条件是时间)。 这对数据库的造成了很大压力。即使我们把这些删除了,但底层的数据文件并没有变小。面对这类问题,最有效的方法就是在使用分区表。最常见的分区方法就是按照时间进行分区。

    分区一个最大的优点就是可以非常高效的进行历史数据的清理。

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

    命令:

    show plugins;

    2. MySQL分区表的特点

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

    HASH分区(HASH)

    HASH分区的特点

    如何建立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

    演示

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

    查询

    范围分区(RANGE)

    RANGE分区特点

    如何建立RANGE分区

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

    RANGE分区的适用场景

    LIST分区

    LIST分区的特点

    如何建立LIST分区

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

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

    业务场景

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

    分区后的用户登录日志表

    按年份分区存储,所以用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)
    ) 

    插入并查询数据

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

    SELECT table_name,partition_name,partition_description,table_rows FROM
    information_schema.`PARTITIONS` WHERE table_name = 'customer_login_log';

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

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

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

    我们可以通过下面语句

    增加分区

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

    增加分区,并插入数据

    删除分区

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

    ALTER TABLE customer_login_log DROP PARTITION p0;

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

    归档分区历史数据

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

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

    分区数据归档迁移条件:

    建表并交换分区

    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;

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

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

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

    ALTER TABLE customer_login_log ENGINE=ARCHIVE;

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

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

    关于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的索引和数据一起保存在表空间里。

    总结

    以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对脚本之家的支持。

    您可能感兴趣的文章:
    • MySQL高级特性——数据表分区的概念及机制详解
    • MySql分表、分库、分片和分区知识深入详解
    • MySql分表、分库、分片和分区知识点介绍
    • MySQL分表和分区的具体实现方法
    • mysql通过Navicat分区实操讲解
    • Mysql优化之Zabbix分区优化
    • MySQL分区字段列有必要再单独建索引吗?
    • MySQL数据库表分区注意事项大全【推荐】
    • Mysql数据表分区技术PARTITION浅析
    • MySQL数据表分区策略及优缺点分析
    上一篇:MySQL慢查询日志的基本使用教程
    下一篇:数据库查询优化之子查询优化
  • 相关文章
  • 

    关于我们 | 付款方式 | 荣誉资质 | 业务提交 | 代理合作


    © 2016-2020 巨人网络通讯

    时间:9:00-21:00 (节假日不休)

    地址:江苏信息产业基地11号楼四层

    《增值电信业务经营许可证》 苏B2-20120278

    X

    截屏,微信识别二维码

    微信号:veteran88

    (点击微信号复制,添加好友)

     打开微信