mysql分区和分表

mysql分表和分区

1.mysql分表

什么是分表?

分表是将一个大表按照一定的规则分解成多张具有独立存储空间的实体表,每个表都对应三个文件,MYD数据文件,MYI索引文件,frm表结构文件。如果是Innodb存储引擎,索引文件和数据文件存放在同一个位置。这些表可以分布在同一块磁盘上,也可以在不同的机器上。

app读写的时候根据事先定义好的规则得到对应的的表明,然后去操作它。

将单个数据库表进行拆分,拆分成多个数据表,然后用户访问的时候,根据一定的算法(如用hash的方式,也可以用取余的方式),让用户访问不同的表,这样数据分散到多个数据表中,减少了单个数据表的访问压力。提升了数据库访问性能。

mysql分表分为垂直切分和水平切分

垂直切分是指数据表列的拆分,把一张列比较多的表拆分为多张表。

通常按一下原则进行垂直切分:

把不常用的字段单独放在一张表;

把text,blob(binary large object,二进制大对象)等大字段拆分出来放在附表中;

经常组合查询的列放在一张表中;

水平拆分是指数据表行的拆分,把一张表的数据拆分成多张表来存放。

水平拆分原则

通常情况下,我们使用hash、取模等方式来进行表的拆分

进行拆分后的表,这时我们就要约束用户查询行为。

分表的几种方式:

1)预先估计会出现大数据量并且访问频繁的表,将其分为若干个表

2)利用merge存储引擎来实现分表

创建一个完整表存储着所有的成员信息(表名为member)

并往里面插入点数据:

mysql> select * from member;

+----+------+-----+

| id | name | sex |

+----+------+-----+

|  1 | tom  |   1 |

|  2 | tom  |   1 |

|  3 | tom  |   1 |

|  4 | tom  |   1 |

|  5 | tom  |   1 |

|  6 | tom  |   1 |

|  7 | tom  |   1 |

|  8 | tom  |   1 |

|  9 | tom  |   1 |

| 10 | tom  |   1 |

| 11 | tom  |   1 |

| 12 | tom  |   1 |

| 13 | tom  |   1 |

| 14 | tom  |   1 |

| 15 | tom  |   1 |

| 16 | tom  |   1 |

+----+------+-----+

下面我们进行分表,这里我们把member分两个表tb_member1,tb_member2

mysql> use test;

mysql> create table tb_member1(

-> id bigint primary key,

-> name varchar(20),

-> sex tinyint not null default ‘0‘

-> )engine=myisam default charset=utf8;

用下面命令可以更简洁的创建出与tb_member1一样的表:

mysql>create table tb_member2 like tb_member1;

创建主表tb_member

mysql> create table tb_member(

-> id bigint primary key,

-> name varchar(20),

-> sex tinyint not null default ‘0‘

-> ) engine=merge union=(tb_member1,tb_member2) insert_method=last charset=utf8;

查看一下tb_member表的结构:

mysql> desc tb_member;                                                                 +-------+-------------+------+-----+---------+-------+

| Field | Type        | Null | Key | Default | Extra |

+-------+-------------+------+-----+---------+-------+

| id    | bigint(20)  | NO   | PRI | NULL    |       |

| name  | varchar(20) | YES  |     | NULL    |       |

| sex   | tinyint(4)  | NO   |     | 0       |       |

+-------+-------------+------+-----+---------+-------+

注:查看子表与主表的字段定义要一致

接下来,把数据分到两个分表中去:

mysql> insert into tb_member1(id,name,sex) select id,name,sex from member where id%2=0;

mysql> insert into tb_member2(id,name,sex) select id,name,sex from member where id%2=1;

查看两个子表的数据:

mysql> select * from tb_member1;

+----+------+-----+

| id | name | sex |

+----+------+-----+

|  2 | tom  |   1 |

|  4 | tom  |   1 |

|  6 | tom  |   1 |

|  8 | tom  |   1 |

| 10 | tom  |   1 |

| 12 | tom  |   1 |

| 14 | tom  |   1 |

| 16 | tom  |   1 |

+----+------+-----+

8 rows in set (0.00 sec)

mysql> select * from tb_member2;

+----+------+-----+

| id | name | sex |

+----+------+-----+

|  1 | tom  |   1 |

|  3 | tom  |   1 |

|  5 | tom  |   1 |

|  7 | tom  |   1 |

|  9 | tom  |   1 |

| 11 | tom  |   1 |

| 13 | tom  |   1 |

| 15 | tom  |   1 |

+----+------+-----+

8 rows in set (0.00 sec)

查看一下主表的数据:

mysql> select * from tb_member;

+----+------+-----+

| id | name | sex |

+----+------+-----+

|  2 | tom  |   1 |

|  4 | tom  |   1 |

|  6 | tom  |   1 |

|  8 | tom  |   1 |

| 10 | tom  |   1 |

| 12 | tom  |   1 |

| 14 | tom  |   1 |

| 16 | tom  |   1 |

|  1 | tom  |   1 |

|  3 | tom  |   1 |

|  5 | tom  |   1 |

|  7 | tom  |   1 |

|  9 | tom  |   1 |

| 11 | tom  |   1 |

| 13 | tom  |   1 |

| 15 | tom  |   1 |

+----+------+-----+

16 rows in set (0.00 sec)

总结:每个子表都有自己独立的表文件,主表只是一个壳,并没有完整的表文件。

[[email protected] ~]# ls -l /usr/local/mysql/data/test/tb_member*

-rw-r----- 1 mysql mysql 8614 Feb 13 21:44 /usr/local/mysql/data/test/tb_member1.frm

-rw-r----- 1 mysql mysql  160 Feb 13 21:47 /usr/local/mysql/data/test/tb_member1.MYD

-rw-r----- 1 mysql mysql 2048 Feb 13 21:47 /usr/local/mysql/data/test/tb_member1.MYI

-rw-r----- 1 mysql mysql 8614 Feb 13 21:44 /usr/local/mysql/data/test/tb_member2.frm

-rw-r----- 1 mysql mysql  160 Feb 13 21:47 /usr/local/mysql/data/test/tb_member2.MYD

-rw-r----- 1 mysql mysql 2048 Feb 13 21:47 /usr/local/mysql/data/test/tb_member2.MYI

-rw-r----- 1 mysql mysql 8614 Feb 13 21:46 /usr/local/mysql/data/test/tb_member.frm

-rw-r----- 1 mysql mysql   42 Feb 13 21:46 /usr/local/mysql/data/test/tb_member.MRG

2.分区

什么是分区?

分区与分表区别:分表将大表分解为若干个独立的实体表,而分区是将数据分段划分在多个位置存放,分区后,表还是一张大表,但数据散列到多个位置了。

app读写的时候操作的还是表名字,db自动去组织分区的数据。

分区主要有两种形式:

水平分区:对表的行进行分区,所有在表中定义的列在每个数据集中都能找到,所以表的特性得以保持。

垂直分区:通过对表的垂直划分来减少目标表的宽度,使某些特定的列被划分到特定的分区,每个分区都包含了其中的列所对应的行。

分区技术支持

在5.6之前,使用以下参数查看当前配置是否支持分区

mysql> show variables like ‘%partition%‘;

显示have_partition_engine选项后为YES

在5.6之后,则采用以下方式查看

mysql> show plugins;

显示结果中,可以看到partition是active的,表示支持分区

下面演示一个按照范围(range)方式的表分区

创建range分区表

mysql> create table user(

-> id int not null auto_increment,

-> name varchar(30) not null default‘‘,

-> sex int(1) not null default‘0‘,

-> primary key(id)

-> )default charset=utf8 auto_increment=1

-> partition by range(id)(

-> partition p0 values less than (3),

-> partition p1 values less than (6),

-> partition p2 values less than (9),

-> partition p3 values less than (12),

-> partition p4 values less than maxvalue);

插入数据:

mysql> insert into user(name,sex) values(‘tom1‘,‘0‘);

mysql> insert into user(name,sex) values(‘tom2‘,‘1‘);

mysql> insert into user(name,sex) values(‘tom3‘,‘2‘);

mysql> insert into user(name,sex) select name,sex from user;(多重复几遍得到双倍数据)

到存放数据库表文件的地方看一下

[[email protected] ~]# ls -l /usr/local/mysql/data/test/user*

-rw-r----- 1 mysql mysql  8614 Feb 13 21:59 /usr/local/mysql/data/test/user.frm

-rw-r----- 1 mysql mysql 98304 Feb 13 22:00 /usr/local/mysql/data/test/user#P#p0.ibd

-rw-r----- 1 mysql mysql 98304 Feb 13 22:00 /usr/local/mysql/data/test/user#P#p1.ibd

-rw-r----- 1 mysql mysql 98304 Feb 13 22:00 /usr/local/mysql/data/test/user#P#p2.ibd

-rw-r----- 1 mysql mysql 98304 Feb 13 22:00 /usr/local/mysql/data/test/user#P#p3.ibd

-rw-r----- 1 mysql mysql 98304 Feb 13 22:00 /usr/local/mysql/data/test/user#P#p4.ibd

从系统数据库中的partition表中查看分区信息

mysql> select * from information_schema.partitions where table_schema=‘test‘ and table_name=‘user‘\G;

合并分区:

Eg:将p1 - p3合并为2个p01 - p02

mysql> alter table user

-> reorganize partition p1,p2,p3 into

-> (partition p01 values less than (8),

-> partition p02 values less than (12)

-> );

再次查看数据库表文件:

[[email protected] ~]# ls -l /usr/local/mysql/data/test/user*

-rw-r----- 1 mysql mysql  8614 Feb 13 22:03 /usr/local/mysql/data/test/user.frm

-rw-r----- 1 mysql mysql 98304 Feb 13 22:03 /usr/local/mysql/data/test/user#P#p01.ibd

-rw-r----- 1 mysql mysql 98304 Feb 13 22:03 /usr/local/mysql/data/test/user#P#p02.ibd

-rw-r----- 1 mysql mysql 98304 Feb 13 22:00 /usr/local/mysql/data/test/user#P#p0.ibd

-rw-r----- 1 mysql mysql 98304 Feb 13 22:00 /usr/local/mysql/data/test/user#P#p4.ibd

未分区表和分区表性能测试

创建一个未分区的表

mysql> create table tab2(c1 int,c2 varchar(30),c3 date)

-> partition by range(year(c3))(partition p0 values less than (1995),

-> partition p1 values less than (1996),

-> partition p2 values less than (1997),

-> partition p3 values less than (1998),

-> partition p4 values less than (1999),

-> partition p5 values less than (2000),

-> partition p6 values less than (2001),

-> partition p7 values less than (2002),

-> partition p8 values less than (2003),

-> partition p9 values less than (2004),

-> partition p10 values less than (2010),

-> partition p11 values less than maxvalue);

通过存储过程插入10万条数据

创建存储过程:

mysql> delimiter $$

mysql> create procedure load_part_tab()

-> begin

-> declare v int default 0;

-> while v < 10000

-> do

-> insert into tab1

-> values (v,‘testing partitions‘,adddate(‘1995-01-01‘,(rand(v)*36520) mod 3652));

-> set v = v + 1;

-> end while;

-> end

-> $$

执行存储过程:

mysql> call load_part_tab();

向tab2表中插入数据

Insert into tab2 select * from tab1;

测试SQL性能

mysql> select count(*) from tab1 where c3 > ‘1995-01-01‘ and c3 < ‘1995-12-31‘;

+----------+

| count(*) |

+----------+

|      990 |

+----------+

1 row in set (0.11 sec)

mysql> select count(*) from tab2 where c3 > ‘1995-01-01‘ and c3 < ‘1995-12-31‘;

+----------+

| count(*) |

+----------+

|        0 |

+----------+

1 row in set (0.03 sec)

分区表比未分区表的执行时间少很多。

创建索引后情况测试

mysql> create index idx_of_c3 on tab1(c3);

Query OK, 0 rows affected (0.28 sec)

Records: 0  Duplicates: 0  Warnings: 0

mysql> create index idx_of_c3 on tab2(c3);

Query OK, 0 rows affected (0.22 sec)

Records: 0  Duplicates: 0  Warnings: 0

mysql> select count(*) from tab1 where c3 > ‘1996-01-01‘ and c3 < ‘1996-12-31‘;

+----------+

| count(*) |

+----------+

|     1006 |

+----------+

1 row in set (0.11 sec)

重启mysql服务

mysql> select count(*) from tab1 where c3 > ‘1996-01-01‘ and c3 < ‘1996-12-31‘;

+----------+

| count(*) |

+----------+

|     1006 |

+----------+

1 row in set (0.00 sec)

创建索引后分区表和未分区表相差不大(数据量越大差别会明显些)

时间: 2024-12-27 22:42:22

mysql分区和分表的相关文章

mysql分区及分表(一)

mysql分区分表 1.分表是将一个大表按照一定的规则分解成多张具有独立存储空间的实体表,每个表都对应三个文件,MYD数据文件,.MYI索引文件,.frm表结构文件 mysql分表分为垂直切分和水平切分 垂直切分是指数据表列的拆分,把一张列比较多的表拆分为多张表通常我们按以下原则进行垂直拆分:把不常用的字段单独放在一张表; 水平拆分是指数据表行的拆分,把一张的表的数据拆成多张表来存放. 水平拆分原则:通常情况下,我们使用hash.取模等方式来进行表的拆分 通过用ID取模的方法把数据分散到四张表内

Mysql分区和分表介绍

为什么要分区和分表 我们的数据库数据越来越大,随之而来的是单个表中数据太多,以至于查询速度过慢,而且由于表的锁机制导致应用操作也受到严重影响,出现数据库性能瓶颈. MySQL中有一种机制是表锁定和行锁定,是为了保证数据的完整性.表锁定表示你们都不能对这张表进行操作,必须等我对表操作完才行.行锁定也一样,别的sql必须等我对这条数据操作完了,才能对这条数据进行操纵.但出现这种情况时,我们可以考虑分表或者分区. 分表 什么是分表 分表是将一个大表按照一定的规则分解成多张具有独立存储空间的实体表,每个

mysql分区及分表(二)

mysql分区分表(二) 测试未分区表和分区表性能 重新创建新的测试数据库及未分区表back1 创建分区表back2,按照年月区分 maxvalue把对于2005的值全放在p11区里 创建大点的数据(方便测试的时候区分明显分区和未分区的区别) rand()函数在0和1之间产生一个随机数,如果一个整数参数N指定,它被用作种子值..每个种子产生的随机数序列是不同的 执行存储过程load_part_tab向back2中插入数据 向back1中插入数据 测试未分区和分区的性能 可以通过explain语句

关于Mysql分区和分表

[分区概念]分区就是把一张表的数据按照一定的规则分成多个区块,这些区块可以在同一个磁盘上,也可以在不同的磁盘上.分区后表还是一张表.分区根据一定的规则把数据文件和索引文件进行了分割,还多出了一个.par文件,打开.par文件后你可以看出这张表的分区信息. [分区好处]突破磁盘的I/O瓶颈,从而达到提高mysql性能的目的.便于表的维护管理,不需要修改程序代码. [分区方法]根据分区策略创建或修改表时对表数据进行分区(分区策略多样,实现容易) [分表概念]分表是真正的分表,一张表分成很多表后,每一

Mysql5.7—mysql优化分区、分表(必备)

小生博客:http://xsboke.blog.51cto.com 小生 Q Q:1770058260 -------谢谢您的参考,如有疑问,欢迎交流 一. 分表 1. 分表简介 分表是将一个大表按照一定的规则分解成多张具有独立存储空间的实体表. 如果正在使用的表需要进行分区,就需要同时修改app的规则,使mysql可以得知用户查询的数据在哪. 2. 分表类型 分为垂直切分和水平切分 垂直切分:将某些列分到另一个表 水平切分:将某些行分到另一个表 3. 分表的方式 1) Mysql集群 它并不是

大数据技术之_29_MySQL 高級面试重点串讲_02_Mysql 简介+Linux 版的安装+逻辑架构介绍+性能优化+性能分析+查询截取分析+分区分库分表简介+锁机制+主从复制

第1章 Mysql 简介1.1 概述1.2 高级 MySQL第2章 Mysql Linux 版的安装2.1 下载地址2.2 检查当前系统是否安装过 mysql2.3 修改 Mysql 配置文件位置2.4 修改字符集和数据存储路径2.5 MySQL 的安装位置说明2.6 Mysql 配置文件说明2.7 Mysql 的数据存放目录第3章 Mysql 逻辑架构介绍3.1 总体概览3.2 查询说明第4章 Mysql 性能优化4.1 影响 mysql 的性能因素4.2 查询与索引优化分析4.2.1 性能下

Mysql 数据库优化(三)——分区和分表【个人经验】

引:MyISAM存储引擎的表在数据库中,每一个表都被存放为三个以表名命名的物理文件. 1.首先肯定会有任何存储引擎都不可缺少的存放表结构定义信息的.frm文件, 2.另外还有.MYD和.MYI文件,分别存放了表的数据(.MYD)和索引数据(.MYI). 每个表都有且仅有这样三个文件做为MyISAM存储类型的表的存储,也就是说不管这个表有多少个索引,都是存放在同一个.MYI文件中. MyISAM支持以下三种类型的索引: 1.B-Tree索引 B-Tree索引,顾名思义,就是所有的索引节点都按照ba

(转)MYSQL 的分区 、分表、集群

转发:https://www.cnblogs.com/myvic/p/7711498.html MYSQL 的分区 .分表.集群 1.分区 mysql数据库中的数据是以文件的形势存在磁盘上的,默认放在/mysql/data下面(可以通过my.cnf中的datadir来查看),一张表主要对应着三个文件,一个是frm存放表结构的,一个是myd存放表数据的, 一个是myi存表索引的.如果一张表的数据量太大的话,那么myd,myi就会变的很大,查找数据就会变的很慢,这个时候我们可以利用mysql的分区功

Mysql第八天 分区与分表

分区表 主要提供例如以下的特性,或者适合如此场景: 数据量非常大, 或者仅仅有表中最后的部分有热点数据.其它均为历史数据 分区表数据更easy维护,能够对独立的分区删除等操作 分区表的数据能够分布在不同的物理设备上.从而高效地利用多个硬件设备. 能够避免一些特殊瓶颈.比方InnoDB的单个索引的相互排斥訪问 能够备份和恢复独立的分区 创建分区表 通常有这么几种分法.由于主键或者是唯一约束键必须有一部分包括在分区键中,所以一般要不无主键,要不就依照自增主键的id进行范围分区,要不就把分区字段和主键