设为首页 收藏本站
查看: 492|回复: 0

[经验分享] MySQL5.5的分区表

[复制链接]
累计签到:1 天
连续签到:1 天
发表于 2016-10-27 09:41:32 | 显示全部楼层 |阅读模式
变更普通表baby_user_change_log为分区表



一、 表列描述
     mysql> desc baby_user_change_log ;
     +--------------+------------------+------+-----+---------+----------------+
     | Field        | Type             | Null | Key | Default | Extra          |
     +--------------+------------------+------+-----+---------+----------------+
     | id           | int(11) unsigned | NO   | PRI | NULL    | auto_increment |
     | account_id   | int(11) unsigned | NO   | MUL | NULL    |                |
     | app_id       | int(11)          | YES  |     | NULL    |                |
     | operate      | varchar(20)      | YES  |     | NULL    |                |
     | old_data     | varchar(2000)    | YES  |     | NULL    |                |
     | new_data     | varchar(2000)    | YES  |     | NULL    |                |
     | change_data  | varchar(2000)    | YES  |     | NULL    |                |
     | operate_time | int(11)          | YES  |     | NULL    |                |
     +--------------+------------------+------+-----+---------+----------------+

二、 表结构特征

      CREATE TABLE `baby_user_change_log` (
      `id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增id',
      `account_id` int(11) unsigned NOT NULL COMMENT 'account_id',
      `app_id` int(11) DEFAULT NULL COMMENT '平台ID',
      `operate` varchar(20) DEFAULT NULL COMMENT '操作类型',
      `old_data` varchar(2000) DEFAULT NULL COMMENT '修改之前的数据',
      `new_data` varchar(2000) DEFAULT NULL COMMENT '修改之后的数据',
      `change_data` varchar(2000) DEFAULT NULL COMMENT '被修改的数据',
      `operate_time` int(11) DEFAULT NULL COMMENT '时间',
      PRIMARY KEY (`id`),
      KEY `idx_account_id` (`account_id`)
      )ENGINE=MyISAM AUTO_INCREMENT=18543058 DEFAULT CHARSET=utf8;

三、适合的分区方案

      1)表总数据记录条数:
      mysql> select count(*) from baby_user_change_log;
      +----------+
      | count(*) |
      +----------+
      | 18552945 |
      +----------+  

      2)其中app_id 列具有按照RANGE分区的特征

      mysql> select distinct(app_id) from baby_user_change_log;
      +--------+
      | app_id |
      +--------+
      |      7 |
      |      5 |
      |      3 |
      |      1 |  
      +--------+  

      3)具体的分区表结构SQL

       CREATE TABLE `baby_user_change_log_partition` (
       `id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增id',
       `account_id` int(11) unsigned NOT NULL COMMENT 'account_id',
       `app_id` int(11) DEFAULT NULL COMMENT '平台ID',
       `operate` varchar(20) DEFAULT NULL COMMENT '操作类型',
       `old_data` varchar(2000) DEFAULT NULL COMMENT '修改之前的数据',
       `new_data` varchar(2000) DEFAULT NULL COMMENT '修改之后的数据',
       `change_data` varchar(2000) DEFAULT NULL COMMENT '被修改的数据',
       `operate_time` int(11) DEFAULT NULL COMMENT '时间',
       PRIMARY KEY (`id`,`app_id`),
       KEY `idx_account_id` (`account_id`)
       )ENGINE=MyISAM AUTO_INCREMENT=0 DEFAULT CHARSET=utf8
       PARTITION BY RANGE (app_id) (
       PARTITION p0 VALUES LESS THAN (1),
       PARTITION p1 VALUES LESS THAN (3),
       PARTITION p2 VALUES LESS THAN (5),
       PARTITION p3 VALUES LESS THAN (7),
       PARTITION p4 VALUES LESS THAN MAXVALUE
       );  

      4)插入数据

        insert into baby_user_change_log_partition select* from baby_user_change_log;

      5)验证结果

      mysql> explain partitions select *  from baby_user_change_log_partition where app_id=1;
      +----+-------------+-----------------------------------------+------------+------+---------------+------------+---------+-------+-------+-------+
      | id | select_type | table                                   | partitions | type | possible_keys | key        | key_len | ref   | rows  | Extra |
      +----+-------------+-----------------------------------------+------------+------+---------------+------------+---------+-------+-------+-------+
      |  1 | SIMPLE      | baby_user_change_log_partition | p1         | ref  | idx_app_id    | idx_app_id | 4       | const | 25739 |       |
      +----+-------------+-----------------------------------------+------------+------+---------------+------------+---------+-------+-------+-------+
      1 row in set (0.00 sec)

      mysql> explain partitions select *  from baby_user_change_log_partition where app_id=7;
      +----+-------------+-----------------------------------------+------------+------+---------------+------------+---------+-------+------+-------+
      | id | select_type | table                                   | partitions | type | possible_keys | key        | key_len | ref   | rows | Extra |
      +----+-------------+-----------------------------------------+------------+------+---------------+------------+---------+-------+------+-------+
      |  1 | SIMPLE      | baby_user_change_log_partition | p4         | ref  | idx_app_id    | idx_app_id | 4       | const |  276 |       |
      +----+-------------+-----------------------------------------+------------+------+---------------+------------+---------+-------+------+-------+
      1 row in set (0.00 sec)

      mysql> explain partitions select *  from baby_user_change_log_partition;
      +----+-------------+-----------------------------------------+----------------+------+---------------+------+---------+------+-------+-------+
      | id | select_type | table                                   | partitions     | type | possible_keys | key  | key_len | ref  | rows  | Extra |
      +----+-------------+-----------------------------------------+----------------+------+---------------+------+---------+------+-------+-------+
      |  1 | SIMPLE      | baby_user_change_log_partition | p0,p1,p2,p3,p4 | ALL  | NULL          | NULL | NULL    | NULL | 56269 |       |
      +----+-------------+-----------------------------------------+----------------+------+---------------+------+---------+------+-------+-------+
      1 row in set (0.00 sec)


四、 分区表的原理及优缺点


     1)分区表是什么?分区表是由多个相关的底层表实现,这些底层表也是由句柄对象表示,所以我们也可以直接访问各个分区,
        存储引擎管理分区的各个底层表和管理普通表一样(所有的底层表都必须使用相同的存储引擎),分区表的索引只是在各个
        底层表上各自加上一个相同的索引,从存储引擎的角度来看,底层表和一个普通表没有任何不同,存储引擎也无须知道这是
        一个普通表还是一个分区表的一部分。

     2)在分区表上的操作按照下面的操作逻辑进行:

        1.select查询:

          当查询一个分区表的时候,分区层先打开并锁住所有的底层表,优化器判断是否可以过滤部分分区,
          然后再调用对应的存储引擎接口访问各个分区的数据

        2.insert操作:

          当写入一条记录时,分区层打开并锁住所有的底层表,然后确定哪个分区接受这条记录,再将记录写入对应的底层表

        3.delete操作:

          当删除一条记录时,分区层先打开并锁住所有的底层表,然后确定数据对应的分区,最后对相应底层表进行删除操作

        4.update操作:

          当更新一条数据时,分区层先打开并锁住所有的底层表,mysql先确定需要更新的记录在哪个分区,然后取出数据并更新,
          再判断更新后的数据应该放在哪个分区,然后对底层表进行写入操作,并对原数据所在的底层表进行删除操作

     3)虽然每个操作都会打开并锁住所有的底层表,但这并不是说分区表在处理过程中是锁住全表的,如果存储引擎能够自己实现行级锁,
         如:innodb,则会在分区层释放对应的表锁,这个加锁和解锁过程与普通Innodb上的查询类似。

     4)分区表适用的场景

        1.表非常大以至于无法全部都放在内存中,或者只在表的最后部分有热点数据,其他都是历史数据

        2.分区表的数据更容易维护,如:想批量删除大量数据可以使用清除整个分区的方式。另外,
          还可以对一个独立分区进行优化、检查、修复等操作

        3.分区表的数据可以分布在不同的物理设备上,从而高效地利用多个硬件设备

        4.可以使用分区表来避免某些特殊的瓶颈,如:innodb的单个索引的互斥访问,ext3文件系统的inode锁竞争等

        5.如果需要,还可以备份和恢复独立的分区,这在非常大的数据集的场景下效果非常好

        6.优化查询,在where字句中包含分区列时,可以只使用必要的分区来提高查询效率,
          同时在涉及sum()和count()这类聚合函数的查询时,可以在每个分区上面并行处理,
          最终只需要汇总所有分区得到的结果。

     5)分区表的限制


        1.一个表最多只能有1024个分区,包含子分区(mysql5.6之后支持8192个分区)

        2.在mysql5.1中分区表达式必须是整数,或者是返回整数的表达式,
          在5.5之后某些场景可以直接使用字符串列和日期类型列来进行分区
          使用varchar字符串类型列时,一般还是字符串的日期作为分区。

        3.如果分区字段中有主键或者唯一索引列,那么所有主键列和唯一索引列都必须包含进来,
          如果表中有主键或唯一索引,那么分区键必须是主键或唯一索引

        4.分区表中无法使用外键约束

        5.mysql数据库支持的分区类型为水平分区,并不支持垂直分区,
          因此mysql数据库的分区中索引是局部分区索引,一个分区中既存放了数据又存放了索引,
          而全局分区是指的数据库放在各个分区中,但是所有的数据的索引放在另外一个对象中

        6.目前mysql不支持空间类型和临时表类型进行分区。不支持全文索引


五、分区表的分区类型

    1)分区表根据数据类型的特征适用不同的分区类型主要的类型有:

       1.RANGE分区:基于属于一个给定连续区间的列值,把多行分配给分区。

       2.LIST分区:类似于按RANGE分区,区别在于LIST分区是基于列值匹配一个离散值集合中的某个值来进行选择。

       3.HASH分区:基于用户定义的表达式的返回值来进行选择的分区,该表达式使用将要插入到表中的这些行的列值进行计算。
         这个函数可以包含MySQL 中有效的、产生非负整数值的任何表达式。

       4.KEY分区:类似于按HASH分区,区别在于KEY分区只支持计算一列或多列,且MySQL服务器提供其自身的哈希函数。
         必须有一列或多列包含整数值。



     分区表官方文档的解释与说明:

     http://dev.mysql.com/doc/refman/5.5/en/partitioning.html



运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-291882-1-1.html 上篇帖子: MySQL错误Another MySQL daemon already running with the same unix socket. 下篇帖子: linux下mysql修改root密码
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表