Mysql --分区表(2)
2016-08-09 15:10
155 查看
分区类型
RANGE分区range分区的表是利用取值范围将数据分成分区,区间要连续并且不能互相重叠,使用values less than操作符进行分区定义
LIST分区
LIST分区是建立离散的值列表告诉数据库特定的值属于哪个分区,LIST分区在很多方面类似于RANGE分区,区别在LIST分区是从属于一个枚举列表的值得集合,RANGE分区是从属于一个连续区间值得集合。
LIST分区通过使用PARTITION BY LIST(expr)子句来实现,expr是某列值或一个局域某列值返回一个整数值得表达式,然后通过VALUES IN(value_list)的方式来定义分区,其中value_list是一个逗号分隔的整数列表。与RANGE分区不同,LIST分区不必声明任何特定顺序
HASH分区
HASH分区主要用来分散热点读,确保数据在预先确定个数的分区中尽可能平均分布。对一个表执行HASH分区时,MySQL会对分区键应用一个散列函数,以此确定数据应当放在N个分区中的哪个分区
MySQL支持两种HASH分区,常规HASH分区和线性HASH分区(LINEAR HASH);常规HASH使用的是取模算法,线性HASH分区使用的是一个线性的2的幂的运算法则
Key分区
按照Key进行分区非常类似于按照HASH进行分区,只不过HASH分区允许使用用户自定义的表达式,而Key分区不允许使用用户自定义的表达式,需要使用MySQL提供的HASH函数
数据库分区的一个非常常见的用途是按日期分离数据,一些数据库系统支持明确的日期分区,然而Mysql5.7并不支持(明确的)。然后使用DATE, TIME, or DATETIME 列来分区并不是什么难事儿,甚至基于表达式利用这样的列来创建分区。
当通过partition by KEY或LINEAR KEY的方式分区,你可以直接使用 DATE, TIME, or DATETIME column列作为分区键而不用对它们进行任何处理。
CREATE TABLE members ( firstname VARCHAR(25) NOT NULL, lastname VARCHAR(25) NOT NULL, username VARCHAR(16) NOT NULL, email VARCHAR(35), joined DATE NOT NULL ) PARTITION BY KEY(joined) PARTITIONS 6; 创建一个存储过程插入一些数据 delimiter $$ drop procedure if exists pr_insertdate$$ create procedure pr_insertdate(in begindate date,in enddate date) begin while begindate<enddate do insert into members values('fan','boshi','duyalan',null,begindate); set begindate = date_add(begindate,interval 1 day); end while; end$$ delimiter ; 调用存储过程插入数据 mysql> call pr_insertdate('2015-01-01','2016-08-08'); Query OK, 1 row affected (0.06 sec) mysql> select count(*) from members; +----------+ | count(*) | +----------+ | 585 | +----------+ 1 row in set (0.00 sec) 查看数据分布 select partition_name part, partition_expression expr, partition_description descr, table_rows from information_schema.partitions where table_schema = schema() and table_name='members'; +------+----------+-------+------------+ | part | expr | descr | table_rows | +------+----------+-------+------------+ | p0 | `joined` | NULL | 177 | | p1 | `joined` | NULL | 0 | | p2 | `joined` | NULL | 208 | | p3 | `joined` | NULL | 0 | | p4 | `joined` | NULL | 200 | | p5 | `joined` | NULL | 0 | +------+----------+-------+------------+ 6 rows in set (0.00 sec) 然而根据我的实验这种分区貌似没什么卵子用,p1 p3 p5都用不上。这种分区方法也不能很好地利用分区裁剪特性
MySQL 5.6也支持 DATE or DATETIME 类型列进行range和list分区
CREATE TABLE members_year ( firstname VARCHAR(25) NOT NULL, lastname VARCHAR(25) NOT NULL, username VARCHAR(16) NOT NULL, email VARCHAR(35), joined DATE NOT NULL ) PARTITION BY RANGE( YEAR(joined) ) ( PARTITION p0 VALUES LESS THAN (1960), PARTITION p1 VALUES LESS THAN (1970), PARTITION p2 VALUES LESS THAN (1980), PARTITION p3 VALUES LESS THAN (1990), PARTITION p4 VALUES LESS THAN MAXVALUE ); 普通的range和list分区还是要被分区键列转换成整型 创建一个可以传入表名的过程,用到了prepare statement,因为表名无法作为参数传递 delimiter $$ drop procedure if exists pr_insertdate_1$$ create procedure pr_insertdate_1(in begindate date,in enddate date,in tabname varchar(40)) begin while begindate<enddate do set @s=concat_ws(' ','insert into',tabname,'values(''fan'',''boshi'',''duyalan'',null,''',begindate,''')'); prepare stmt from @s; execute stmt; drop prepare stmt; set begindate = date_add(begindate,interval 1 day); end while; end$$ delimiter ; 调用存储过程插入数据 mysql> call pr_insertdate_1('1960-01-01','1990-12-31','members_mon'); Query OK, 0 rows affected (3.17 sec) mysql> select count(*) from members_year; +----------+ | count(*) | +----------+ | 11322 | +----------+ 1 row in set (0.01 sec) 查看数据分布 select partition_name part, partition_expression expr, partition_description descr, table_rows from information_schema.partitions where table_schema = schema() and table_name='members_year'; +------+---------------+----------+------------+ | part | expr | descr | table_rows | +------+---------------+----------+------------+ | p0 | YEAR(joined) | 1960 | 0 | | p1 | YEAR(joined) | 1970 | 3653 | | p2 | YEAR(joined) | 1980 | 3652 | | p3 | YEAR(joined) | 1990 | 3653 | | p4 | YEAR(joined) | MAXVALUE | 364 | +------+---------------+----------+------------+ 查看是否可以使用到分区裁剪特性 mysql> explain partitions select * from members_year where joined='1970-02-01'; +----+-------------+--------------+------------+------+---------------+------+---------+------+------+-------------+ | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+--------------+------------+------+---------------+------+---------+------+------+-------------+ | 1 | SIMPLE | members_year | p2 | ALL | NULL | NULL | NULL | NULL | 3652 | Using where | +----+-------------+--------------+------------+------+---------------+------+---------+------+------+-------------+ 1 row in set (0.00 sec)
分区表可以指定DATA Directory Directory
对于myisam表可以还可以指定index directoryCREATE TABLE users_myisam ( uid INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY, name VARCHAR(30) NOT NULL DEFAULT '', email VARCHAR(30) NOT NULL DEFAULT '' ) engine=myisam PARTITION BY RANGE (uid) ( PARTITION p0 VALUES LESS THAN (10) DATA DIRECTORY = '/data/data1' INDEX DIRECTORY = '/data/idx1', PARTITION p1 VALUES LESS THAN (20) DATA DIRECTORY = '/data/data2' INDEX DIRECTORY = '/data/idx2' ); [root@uz6535 fandb]# ls -l /data/mysql55/fandb|grep users_myisam -rw-r----- 1 mysql mysql 8620 May 18 09:09 users_myisam.frm -rw-r----- 1 mysql mysql 28 May 18 09:09 users_myisam.par lrwxrwxrwx 1 mysql mysql 33 May 18 09:09 users_myisam#P#p0.MYD -> /data/data1/users_myisam#P#p0.MYD lrwxrwxrwx 1 mysql mysql 32 May 18 09:09 users_myisam#P#p0.MYI -> /data/idx1/users_myisam#P#p0.MYI lrwxrwxrwx 1 mysql mysql 33 May 18 09:09 users_myisam#P#p1.MYD -> /data/data2/users_myisam#P#p1.MYD lrwxrwxrwx 1 mysql mysql 32 May 18 09:09 users_myisam#P#p1.MYI -> /data/idx2/users_myisam#P#p1.MYI
对于innodb表,只能指定data directory参数
CREATE TABLE users_innodb ( uid INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY, name VARCHAR(30) NOT NULL DEFAULT '', email VARCHAR(30) NOT NULL DEFAULT '' ) PARTITION BY RANGE (uid) ( PARTITION p0 VALUES LESS THAN (10) DATA DIRECTORY = '/data/data1', PARTITION p1 VALUES LESS THAN (20) DATA DIRECTORY = '/data/data2' );
在指定的路径下会创建 库名文件夹
[root@uz6535 fandb]# ls -l /data/data1/fandb/users_innodb* -rw-r----- 1 mysql mysql 98304 May 18 09:09 /data/data1/fandb/users_innodb#P#p0.ibd [root@uz6535 fandb]# ls -l /data/data2/fandb/users_innodb* -rw-r----- 1 mysql mysql 98304 May 18 09:09 /data/data2/fandb/users_innodb#P#p1.ibd
在datadir/库名 下包含frm文件和isl文件
[root@uz6535 fandb]# ls -l /data/mysql55/fandb/users_innodb* -rw-r----- 1 mysql mysql 8620 May 18 09:09 /data/mysql55/fandb/users_innodb.frm -rw-r----- 1 mysql mysql 39 May 18 09:09 /data/mysql55/fandb/users_innodb#P#p0.isl -rw-r----- 1 mysql mysql 39 May 18 09:09 /data/mysql55/fandb/users_innodb#P#p1.isl
isl文件是一个文本文件,指明了分区ibd文件实际存储路径
[root@uz6535 fandb]# file /data/mysql55/fandb/users_innodb#P#p0.isl /data/mysql55/fandb/users_innodb#P#p0.isl: ASCII text, with no line terminators [root@uz6535 fandb]# more /data/mysql55/fandb/users_innodb#P#p0.isl /data/data1/fandb/users_innodb#P#p0.ibd
相关文章推荐
- mysql 删除分区表
- MySQL的经典用法(四)----大幅度提高性能方案,分区表
- mysql创建分区表
- 高性能MySql进化论(十二):Mysql中分区表的使用总结
- MySQL 分区表
- [转]mysql在已有无分区表增加分区,mysql5.5才有,可以是innodb_file_per_table关闭状态.
- 高性能MySql进化论(十二):Mysql中分区表的使用总结
- mysql 5.6 分区表
- [MySQL] 分区表
- Mysql 分区表测试
- Mysql 分区表
- MySQL 分区表 partition线上修改分区字段,后续进一步学习partition (1)
- MySQL 分区表 partition线上修改分区字段,后续进一步学习partition (1)
- 分区表的使用--mysql
- mysql使用教程之分区表的使用方法(删除分区表)
- MySql创建分区表
- MySQL 5.5 外键不能引用分区表主键
- MYSQL-分区表
- mysql 5.6 分区表
- mysql分表与分区表