mysql 5.5 非整数进行分区_MySQL5.5的分区表

变更普通表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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值