012-- mysql的分区和分表

分区就是把一个数据表的文件和索引分散存储在不同的物理文件中。

mysql支持的分区类型包括Range、List、Hash、Key,其中Range比较常用:

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

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

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

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

案例:

建立一个user 表 以id进行分区 id 小于10的在user_1分区id小于20的在user_2分区

create table user(
    id int not null auto_increment,
    username varchar(10),
    primary key(id)
)engine = innodb charset=utf8
partition by range (id)(
    partition user_1 values less than (10),
    partition user_2 values less than (20)
);

建立后添加分区:

maxvalue 表示最大值   这样大于等于20的id 都出存储在user_3分区

alter table user add partition(
    partition user_3 values less than maxvalue
);

删除分区:

alter  table user drop partition user_3;

如果表使用的存储引擎是MyISAM类型,就是:

user#P#user_1.MYD,user#P#user_1.MYI和user#P#user_2.MYD,user#P#user_2.MYI

由此可见,mysql通过分区把数据保存到不同的文件里,同时索引也是分区的。相对于未分区的表来说,分区后单独的数据库文件索引文件的大小都明显降低,效率则明显的提示了。可以插入一条数据然后分析查询语句验证一下:

insert into user values(null,‘测试‘);

explain partitions select * from user where id =1;

可以看见仅仅在user_1分区执行了这条查询。

具体分区的效率是多少还需要看数据量。在分区时可以通过 DATA DIRECTORY 和   INDEX DIRECTORY 选项吧不同的分区放到不同的磁盘上进一步提高系统的I/O吞吐量。

分区类型的选择,通常使用Range类型,不过有些情况,比如主从结构中,主服务器很少使用‘select’查询,在主服务器上使用 Range类型分区通常没有太大的意义,此时使用Hash类型分区更好例如:

partition by hash(id) partitions 10;

当插入数据时,根据id吧数据平均散到各个分区上,由于文件小,效率高,更新操作变得更快。

在分区时使用的字段,通常情况下按时间字段分区,具体情况以需求而定。划分应用的方式有很多种,比如按时间或用户,哪种用的多,就选择哪种分区。如果使用主从结构可能就更加灵活,有的从服务器使用时间,有的使用用户。不过如此一来当执行查询时,程序应该负责选择真确的服务器查询,写个mysql proxy脚本应该可以透明的实现。

分区的限制:

1.主键或者唯一索引必须包含分区字段,如primary key (id,username),不过innoDB的大组建性能不好。

2.很多时候,使用分区就不要在使用主键了,否则可能影响性能。

3.只能通过int类型的字段或者返回int类型的表达式来分区,通常使用year或者to_days等函数(mysql 5.6 对限制开始放开了)。

4.每个表最多1024个分区,而且多分区会大量消耗内存。

5.分区的表不支持外键,相关的逻辑约束需要使用程序来实现。

6.分区后,可能会造成索引失效,需要验证分区可行性。

分区模式详解:

Range(范围) – 这种模式允许DBA将数据划分不同范围。例如DBA可以将一个表通过年份划分成三个分区,80年代(1980‘s)的数据,90年代(1990‘s)的数据以及任何在2000年(包括2000年)后的数据。

CREATE TABLE users (
       id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
       usersname VARCHAR(30) NOT NULL DEFAULT ‘‘,
       email VARCHAR(30) NOT NULL DEFAULT ‘‘
)
PARTITION BY RANGE (id) (
       PARTITION p0 VALUES LESS THAN (3000000),  

       PARTITION p1 VALUES LESS THAN (6000000), 

       PARTITION p2 VALUES LESS THAN (9000000),  

       PARTITION p3 VALUES LESS THAN MAXVALUE
);  

在这里,将用户表分成4个分区,以每300万条记录为界限,每个分区都有自己独立的数据、索引文件的存放目录。

还可以将这些分区所在的物理磁盘分开完全独立,可以提高磁盘IO吞吐量。

CREATE TABLE users (
       id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
       usersname VARCHAR(30) NOT NULL DEFAULT ‘‘,
       email VARCHAR(30) NOT NULL DEFAULT ‘‘
)
PARTITION BY RANGE (id) (
       PARTITION p0 VALUES LESS THAN (3000000)
       DATA DIRECTORY = ‘/data0/data‘
       INDEX DIRECTORY = ‘/data0/index‘,  

       PARTITION p1 VALUES LESS THAN (6000000)
       DATA DIRECTORY = ‘/data1/data‘
       INDEX DIRECTORY = ‘/data1/index‘,  

       PARTITION p2 VALUES LESS THAN (9000000)
       DATA DIRECTORY = ‘/data2/data‘
       INDEX DIRECTORY = ‘/data2/index‘,  

       PARTITION p3 VALUES LESS THAN MAXVALUE
       DATA DIRECTORY = ‘/data3/data‘
       INDEX DIRECTORY = ‘/data3/index‘
);  

List(预定义列表) – 这种模式允许系统通过DBA定义的列表的值所对应的行数据进行分割。例如:DBA根据用户的类型进行分区。

CREATE TABLE user (
     id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
     name VARCHAR(30) NOT NULL DEFAULT ‘‘ ,
     user_type   int not null
)
PARTITION BY LIST (user_type ) (
     PARTITION p0 VALUES IN (0,4,8,12) ,
     PARTITION p1 VALUES IN (1,5,9,13) ,
     PARTITION p2 VALUES IN (2,6,10,14),
     PARTITION p3 VALUES IN (3,7,11,15)
);     

分成4个区,同样可以将分区设置的独立的磁盘中。

Key(键值) – 上面Hash模式的一种延伸,这里的Hash Key是MySQL系统产生的。

CREATE TABLE user (
     id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
     name VARCHAR(30) NOT NULL DEFAULT ‘‘,
     email VARCHAR(30) NOT NULL DEFAULT ‘‘
)
PARTITION BY KEY (id) PARTITIONS 4 (
     PARTITION p0,
     PARTITION p1,
     PARTITION p2,
     PARTITION p3
);     

Hash(哈希) – 这中模式允许DBA通过对表的一个或多个列的Hash Key进行计算,最后通过这个Hash码不同数值对应的数据区域进行分区,。例如DBA可以建立一个对表主键进行分区的表。

CREATE TABLE user (
     id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
     username VARCHAR(30) NOT NULL DEFAULT ‘‘,
     email VARCHAR(30) NOT NULL DEFAULT ‘‘
)
PARTITION BY HASH (id) PARTITIONS 4 (
     PARTITION p0 ,
     PARTITION p1,
     PARTITION p2,
     PARTITION p3
);  

分成4个区,同样可以将分区设置的独立的磁盘中。

= 分区管理 =


删除分区

ALERT TABLE users DROP PARTITION p0;  

重建分区

RANGE 分区重建

ALTER TABLE users REORGANIZE PARTITION p0,p1 INTO (PARTITION p0 VALUES LESS THAN (6000000));  

将原来的 p0,p1 分区合并起来,放到新的 p0 分区中。

LIST 分区重建

ALTER TABLE users REORGANIZE PARTITION p0,p1 INTO (PARTITION p0 VALUES IN(0,1,4,5,8,9,12,13));  

将原来的 p0,p1 分区合并起来,放到新的 p0 分区中。

HASH/KEY 分区重建

ALTER TABLE users REORGANIZE PARTITION COALESCE PARTITION 2;  

用 REORGANIZE 方式重建分区的数量变成2,在这里数量只能减少不能增加。想要增加可以用 ADD PARTITION 方法。

新增分区

新增 RANGE 分区

alter table user add partition(partition user_3 values less than maxvalue);

新增 LIST 分区

ALTER TABLE category ADD PARTITION (PARTITION p4 VALUES IN (16,17,18,19));  

新增 HASH/KEY 分区

ALTER TABLE users ADD PARTITION PARTITIONS 8;  

将分区总数扩展到8个。

给已有的表加上分区

alter table results partition by RANGE (month(ttime))
(PARTITION p0 VALUES LESS THAN (1),
PARTITION p1 VALUES LESS THAN (2) , PARTITION p2 VALUES LESS THAN (3) ,
PARTITION p3 VALUES LESS THAN (4) , PARTITION p4 VALUES LESS THAN (5) ,
PARTITION p5 VALUES LESS THAN (6) , PARTITION p6 VALUES LESS THAN (7) ,
PARTITION p7 VALUES LESS THAN (8) , PARTITION p8 VALUES LESS THAN (9) ,
PARTITION p9 VALUES LESS THAN (10) , PARTITION p10 VALUES LESS THAN (11),
PARTITION p11 VALUES LESS THAN (12),
PARTITION P12 VALUES LESS THAN (13) );   

分表

分表和分区类似,区别是,分区是把一个逻辑表文件分成几个物理文件后进行存储,而分表则是把原先的一个表分成几个表。进行分表查询时可以通过union或者视图。

分表又分垂直分割和水平分割,其中水平分分割最为常用。水平分割通常是指切分到另外一个数据库或表中。例如对于一个会员表,按对3的模进行分割:

table = id%3

如果id%3 = 0 则将用户数据放入到user_0表中,如id%3=1就放入user_1表中,依次类推。

在这里有个问题,这个uid应该是所有会员按序增长的,可他是怎么得到的呢?使用auto_increment是不行的,这样就用到序列了。

对于一些流量统计系统,其数据量比较大,并且对过往数据的关注度不高,这时按年、月、日进行分表,将每日统计信息放到一个以日期命名的表中;或者按照增量进行分表,如每个表100万数据,超过100万就放入第二个表。还可以按Hash进行分表,但是按日期和取模余数分表最为常见,也容易扩展。

分表后可能会遇到新的问题,那就是查询,分页和统计。通用的方法是在程序中进行处理,辅助视图。

使用分表案例:

案例1:

对会员数据对5取模,放在5个表中,如何查询会员数据:

1.已知id查询会员数据,代码如下:

<?php
//查询单个会员数据
$customer_table = ‘customer‘.$id%5;
$sql = ‘select * from ‘.$customer_table.‘ where customer_id = ‘.$id;
//查询全部会员数据
$sql = ‘‘;
$tbale = [‘customer0‘,‘customer1‘,‘customer2‘,‘customer3‘,‘customer4‘];
foreach($table as $v){
$sql .=‘select * from ‘.$v.‘ union‘;
}
$sql = substr($sql,0,-5);

?>

这样就可以查询某一个会员的数据或者全部会员的数据了。同理,分页的话在这个大集合中使用limit 就可以了。但是这样做又会有一个疑问,把所有的表连起来查询和部分表没有什么区别,其实在实际的应用中,不可能查看所有的会员资料,一次查看20个然后分页。完全没有必要做union,仅查询一个表就可以了,唯一需要考虑的是在分页零界点时的衔接。其实,这个衔接是否那么重要?即使偶尔出现几条数据的差异,也不会对业务有任何的影响。

2.和其它表进行关联和1类似。

3.根据会员姓名搜索用户信息。在这种需求下,需要搜索所有的表,并对结果进行汇总。虽然这样做产生了多次的查询,但并不代表效率低。好的sql语句执行10次也比差的sql语句执行一次快。

案例2:

在一个流量监控系统中,由于网络流量巨大,统计数据很庞大,需要按天分表。先要得到任意日,周,月的数据。

1.需要任意一天的数据。直接查询当天的数据表即可。

2.需要几天的数据。分爱查询这几天的数据,然后进行汇总。

3.需要查询一周的数据。对一周的数据定期汇总到一个week表,从这个表里面查询。这个汇总过程可以由一个外部程序完成,也可以由定期的脚本完成。

4.查询一个月的数据。汇总本月所有的数据到month表,在此表查询。

5.查询5个月内的详细数据。不支持。仅支持最多3个月的详细数据。数据没3个月已归档一次。在大数据的处理中,必须做出一些牺牲。对于超出3个月的数据,仅提供统计数据,详细数据需要查看归档。90天或者180天,给数据保存设个界限,也是大部分这类系统的常规做法,超出90天的数据就不再提供数据详单了。比如,移动的通话记录最多保存半年,即180天,超过这个范围的数据不在提供查询。如果你实在需要,可能就要联系移动的工程师了。

分表前应该尽量按照实际业务来分表,参考依据就是哪些字段在查询中起到作用,那就这些字段来分表,并且需要在分表前就估算好规模,也就是先确定好规则在分表。

对于分表后的操作,依然是联合查询,视图等基本操作,或者使用merge引擎合并数据并在此表中查询。复杂一些操作需要借助存储过程来完成,借助外部工具实现对分表的管理。

对于比较庞大的数据,不论是否进行分表,都必须考虑功能和效率的平衡性,并在功能上做出让步。我们不能事事迁就用户,而应该对某些影响效率的功能做出限制。例如移动公司的180天限制、论坛禁止对老帖进行回复等。

原文地址:https://www.cnblogs.com/yxllovetm/p/10123731.html

时间: 2024-09-28 04:22:20

012-- mysql的分区和分表的相关文章

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

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

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

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

mysql的分区和分表

分区 分区就是把一个数据表的文件和索引分散存储在不同的物理文件中. mysql支持的分区类型包括Range.List.Hash.Key,其中Range比较常用: RANGE分区:基于属于一个给定连续区间的列值,把多行分配给分区. LIST分区:类似于按RANGE分区,区别在于LIST分区是基于列值匹配一个离散值集合中的某个值来进行选择. HASH分区:基于用户定义的表达式的返回值来进行选择的分区,该表达式使用将要插入到表中的这些行的列值进行计算.这个函数可以包含MySQL 中有效的.产生非负整数

mysql分区和分表

mysql分表和分区 1.mysql分表 什么是分表? 分表是将一个大表按照一定的规则分解成多张具有独立存储空间的实体表,每个表都对应三个文件,MYD数据文件,MYI索引文件,frm表结构文件.如果是Innodb存储引擎,索引文件和数据文件存放在同一个位置.这些表可以分布在同一块磁盘上,也可以在不同的机器上. app读写的时候根据事先定义好的规则得到对应的的表明,然后去操作它. 将单个数据库表进行拆分,拆分成多个数据表,然后用户访问的时候,根据一定的算法(如用hash的方式,也可以用取余的方式)

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

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

mysql分区及分表(一)

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

mysql数据库为什么要分表和分区?

一般下载的源码都带了MySQL数据库的,做个真正意义上的网站没数据库肯定不行. 数据库主要存放用户信息(注册用户名密码,分组,等级等),配置信息(管理权限配置,模板配置等),内容链接(html ,图片,声音,视频等等的路径).那mysql数据库为什么要分表和分区? 为什么要分表和分区? 我们的数据库数据越来越大,随之而来的是单个表中数据太多.以至于查询书读变慢,而且 由于表的锁机制导致应用操作也搜到严重影响,出现了数据库性能瓶颈. mysql 中有一种机制是表锁定和行锁定,是为了保证数据的完整性

Mysql分区和分表介绍

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

Mysql第八天 分区与分表

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

mysql大数据解决方案--分表分库(0)

引言 对于一个大型的互联网应用,海量数据的存储和访问成为了系统设计的瓶颈问题,对于系统的稳定性和扩展性造成了极大的问题.通过数据切分来提高网站性能,横向扩展数据层已经成为架构研发人员首选的方式. •水平切分数据库:可以降低单台机器的负载,同时最大限度的降低了宕机造成的损失: •负载均衡策略:可以降低单台机器的访问负载,降低宕机的可能性: •集群方案:解决了数据库宕机带来的单点数据库不能访问的问题: •读写分离策略:最大限度了提高了应用中读取数据的速度和并发量: 问题描述 1.单个表数据量越大,读