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

转发:https://www.cnblogs.com/myvic/p/7711498.html

MYSQL 的分区 、分表、集群

1.分区

mysql数据库中的数据是以文件的形势存在磁盘上的,默认放在/mysql/data下面(可以通过my.cnf中的datadir来查看),一张表主要对应着三个文件,一个是frm存放表结构的,一个是myd存放表数据的,
一个是myi存表索引的。如果一张表的数据量太大的话,那么myd,myi就会变的很大,查找数据就会变的很慢,这个时候我们可以利用mysql的分区功能,
在物理上将这一张表对应的三个文件,分割成许多个小块,这样呢,我们查找一条数据时,就不用全部查找了,只要知道这条数据在哪一块,然后在那一块找就行了。
如果表的数据太大,可能一个磁盘放不下,这个时候,我们可以把数据分配到不同的磁盘里面去

分区的二种方式

a,横向分区

什么是横向分区呢?就是横着来分区了,举例来说明一下,假如有100W条数据,分成十份,前10W条数据放到第一个分区,第二个10W条数据放到第二个分区,依此类推。也就是把表分成了十分,根用merge来分表,有点像哦。取出一条数据的时候,这条数据包含了表结构中的所有字段,也就是说横向分区,并没有改变表的结构。

b,纵向分区

什么是纵向分区呢?就是竖来分区了,举例来说明,在设计用户表的时候,开始的时候没有考虑好,而把个人的所有信息都放到了一张表里面去,这样这个表里面就会有比较大的字段,如个人简介,而这些简介呢,也许不会有好多人去看,所以等到有人要看的时候,在去查找,分表的时候,可以把这样的大字段,分开来。

mysql提供的分区属于第一种,横向分区,并且细分成很多种方式:

1.1 MySQL5.1及以上支持分区功能

查看是否支持分区
mysql> show variables like "%part%";
+-------------------+-------+
| Variable_name     | Value |
+-------------------+-------+
| have_partitioning | YES   |
+-------------------+-------+
row in set (0.00 sec)

1.2 range 分区

这种模式允许将数据划分不同范围。例如可以将一个表通过年份划分成若干个分区

create table t_range(
     id int(11),
     money int(11) unsigned not null,
     date datetime
  )partition by range(year(date))(
  partition p2007 values less than (2008),
  partition p2008 values less than (2009),
  partition p2009 values less than (2010)
  partition p2010 values less than maxvalue  #MAXVALUE 表示最大的可能的整数值
  );

RANGE分区在如下场合特别有用:
1)、当需要删除一个分区上的“旧的”数据时,只删除分区即可。如果你使用上面最近的那个例子给出的分区方案,你只需简单地使用”ALTER TABLE employees DROP PARTITION p0;”
  来删除所有在1991年前就已经停止工作的雇员相对应的所有行。对于有大量行的表,这比运行一个如”DELETE FROM employees WHERE YEAR (separated) <= 1990;”
  这样的一个DELETE查询要有效得多。
2)、想要使用一个包含有日期或时间值,或包含有从一些其他级数开始增长的值的列。
3)、经常运行直接依赖于用于分割表的列的查询。
  例如,当执行一个如”SELECT COUNT(*) FROM employees WHERE YEAR(separated) = 2000 GROUP BY store_id;”这样的查询时,
  MySQL可以很迅速地确定只有分区p2需要扫描,这是因为余下的分区不可能包含有符合该WHERE子句的任何记录

1.3 list分区

这种模式允许系统通过预定义的列表的值来对数据进行分割。

create table t_list(
  a int(11),
  b int(11)
  )(partition by list (b)
  partition p0 values in (1,3,5,7,9),
  partition p1 values in (2,4,6,8,0)
);
LIST分区没有类似如“VALUES LESS THAN MAXVALUE”这样的包含其他值在内的定义。将要匹配的任何值都必须在值列表中找到。

1.4 hash分区

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

CREATE TABLE employees (
    id INT NOT NULL,
    fname VARCHAR(30),
    lname VARCHAR(30),
    hired DATE NOT NULL DEFAULT ‘1970-01-01‘,
    separated DATE NOT NULL DEFAULT ‘9999-12-31‘,
    job_code INT,
    store_id INT
)
PARTITION BY HASH(store_id)
PARTITIONS 4;

1.5 key分区

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

1.6 子分区

子分区是分区表中每个分区的再次分割,子分区既可以使用HASH希分区,也可以使用KEY分区。这 也被称为复合分区(composite partitioning)。

1,如果一个分区中创建了子分区,其他分区也要有子分区

2,如果创建了了分区,每个分区中的子分区数必有相同

3,同一分区内的子分区,名字不相同,不同分区内的子分区名子可以相同(5.1.50不适用

mysql> CREATE TABLE IF NOT EXISTS `sub_part` (
 ->   `news_id` int(11) NOT NULL  COMMENT ‘新闻ID‘,
 ->   `content` varchar(1000) NOT NULL DEFAULT ‘‘ COMMENT ‘新闻内容‘,
 ->   `u_id`  int(11) NOT NULL DEFAULT 0s COMMENT ‘来源IP‘,
 ->   `create_time` DATE NOT NULL DEFAULT ‘0000-00-00 00:00:00‘ COMMENT ‘时间‘
 -> ) ENGINE=INNODB  DEFAULT CHARSET=utf8
 -> PARTITION BY RANGE(YEAR(create_time))
 -> SUBPARTITION BY HASH(TO_DAYS(create_time))(
 -> PARTITION p0 VALUES LESS THAN (1990)(SUBPARTITION s0,SUBPARTITION s1,SUBPARTITION s2),
 -> PARTITION p1 VALUES LESS THAN (2000)(SUBPARTITION s3,SUBPARTITION s4,SUBPARTITION good),
 -> PARTITION p2 VALUES LESS THAN MAXVALUE(SUBPARTITION tank0,SUBPARTITION tank1,SUBPARTITION tank3)
 -> );
Query OK, 0 rows affected (0.07 sec)
分区的优点

1,分区可以分在多个磁盘,存储更大一点

2,根据查找条件,也就是where后面的条件,查找只查找相应的分区不用全部查找了

3,进行大数据搜索时可以进行并行处理。

4,跨多个磁盘来分散数据查询,来获得更大的查询吞吐量

1.7 分区管理

a.删除分区

  alter table user drop partion p4

b.新增分区

alter table user add partition(partition p4 values less than MAXVALUE);#新增range分区
alter table list_part add partition(partition p4 values in(25,26,27))   #新增list分区
alter table hash_part add partition partitions 4; # hash重新分区
alter table key_part add partition partitions 4; #key 重新分区
//子分区添加新分区,虽然我没有指定子分区,但是系统会给子分区命名的
alter table sub1_part add partition(partition p3 values less than MAXVALUE);
//range重新分区
ALTER TABLE user REORGANIZE PARTITION p0,p1,p2,p3,p4 INTO (PARTITION p0 VALUES LESS THAN MAXVALUE);
//list重新分区
 ALTER TABLE list_part REORGANIZE PARTITION p0,p1,p2,p3,p4 INTO (PARTITION p0 VALUES in (1,2,3,4,5));
 #hash和key分区不能用REORGANIZE,官方网站说的很清楚

参考文献:http://blog.csdn.net/yongchao940/article/details/55266603

       http://www.cnblogs.com/mliudong/p/3625522.html

2.分表管理

2.1 MySQL集群

利用mysql cluster ,mysql proxy,mysql replication,drdb等等

有人会问mysql集群,根分表有什么关系吗?虽然它不是实际意义上的分表,但是它启到了分表的作用,做集群的意义是什么呢?为一个数据库减轻负担,说白了就是减少sql排队队列中的sql的数量,
举个例子:有10个sql请求,如果放在一个数据库服务器的排队队列中,他要等很长时间,如果把这10个sql请求,分配到5个数据库服务器的排队队列中,一个数据库服务器的队列中只有2个,
这样等待时间是不是大大的缩短了呢?这已经很明显了。所以我把它列到了分表的范围以内;集群我们在第三部分详情说明;

优点:扩展性好,没有多个分表后的复杂操作(php代码)
缺点:单个表的数据量还是没有变,一次操作所花的时间还是那么多,硬件开销大。

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

我事先建100个这样的表,message_00,message_01,message_02..........message_98,message_99.然后根据用户的ID来判断这个用户的聊天信息放到哪张表里面,

你可以用hash的方式来获得,可以用求余的方式来获得,方法很多,各人想各人的吧。下面用hash的方法来获得表名:

<?php
function get_hash_table($table,$userid) {
 $str = crc32($userid);
 if($str<0){
 $hash = "0".substr(abs($str), 0, 1);
 }else{
 $hash = substr($str, 0, 2);
 }  

 return $table."_".$hash;
}  

echo get_hash_table(‘message‘,‘user18991‘);     //结果为message_10
echo get_hash_table(‘message‘,‘user34523‘);    //结果为message_13

优点:避免一张表出现几百万条数据,缩短了一条sql的执行时间

缺点:当一种规则确定时,打破这条规则会很麻烦,上面的例子中我用的hash算法是crc32,如果我现在不想用这个算法了,改用md5后,会使同一个用户的消息被存储到不同的表中,
   这样数据乱套了。扩展性很差。

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

merge分表,分为主表和子表,主表类似于一个壳子,逻辑上封装了子表,实际上数据都是存储在子表中的。

mysql> CREATE TABLE IF NOT EXISTS `user1` (
 ->   `id` int(11) NOT NULL AUTO_INCREMENT,
 ->   `name` varchar(50) DEFAULT NULL,
 ->   `sex` int(1) NOT NULL DEFAULT ‘0‘,
 ->   PRIMARY KEY (`id`)
 -> ) ENGINE=MyISAM  DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;
Query OK, 0 rows affected (0.05 sec)  

mysql> CREATE TABLE IF NOT EXISTS `user2` (
 ->   `id` int(11) NOT NULL AUTO_INCREMENT,
 ->   `name` varchar(50) DEFAULT NULL,
 ->   `sex` int(1) NOT NULL DEFAULT ‘0‘,
 ->   PRIMARY KEY (`id`)
 -> ) ENGINE=MyISAM  DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;
Query OK, 0 rows affected (0.01 sec)  

mysql> INSERT INTO `user1` (`name`, `sex`) VALUES(‘张映‘, 0);
Query OK, 1 row affected (0.00 sec)  

mysql> INSERT INTO `user2` (`name`, `sex`) VALUES(‘tank‘, 1);
Query OK, 1 row affected (0.00 sec)  

mysql> CREATE TABLE IF NOT EXISTS `alluser` (
 ->   `id` int(11) NOT NULL AUTO_INCREMENT,
 ->   `name` varchar(50) DEFAULT NULL,
 ->   `sex` int(1) NOT NULL DEFAULT ‘0‘,
 ->   INDEX(id)
 -> ) TYPE=MERGE UNION=(user1,user2) INSERT_METHOD=LAST AUTO_INCREMENT=1 ;
Query OK, 0 rows affected, 1 warning (0.00 sec)
创建主表的时候有个INSERT_METHOD,指明插入方式,取值可以是:0 不允许插入;FIRST 插入到UNION中的第一个表; LAST 插入到UNION中的最后一个表。
通过主表查询的时候,相当于将所有子表合在一起查询。这样并不能体现分表的优势,建议还是查询子表。

优点:扩展性好,并且程序代码改动的不是很大

缺点:这种方法的效果比第二种要差一点,查询性能不高

参考资料:http://blog.51yip.com/mysql/949.html

3.集群

MySQL Proxy就是这么一个中间层代理,简单的说,MySQL Proxy就是一个连接池,负责将前台应用的连接请求转发给后台的数据库,并且通过使用lua脚本,可以实现复杂的连接控制和过滤,从而实现读写分离和负载
平衡。对于应用来说,MySQL Proxy是完全透明的,应用则只需要连接到MySQL Proxy的监听端口即可。当然,这样proxy机器可能成为单点失效,但完全可以使用多个proxy机器做为冗余,在应用服务器的连接池配置
中配置到多 个proxy的连接参数即可。

参考资料:http://www.cnblogs.com/phpstudy2015-6/p/6706465.html

        http://blog.51yip.com/mysql/399.html

原文地址:https://www.cnblogs.com/sz-xioabai/p/11666952.html

时间: 2024-10-11 11:59:40

(转)MYSQL 的分区 、分表、集群的相关文章

MySQL订单分库分表多维度查询

转自:http://blog.itpub.net/29254281/viewspace-2086198/ MySQL订单分库分表多维度查询 MySQL分库分表,一般只能按照一个维度进行查询. 以订单表为例, 按照用户ID mod 64 分成 64个数据库.按照用户的维度查询很快,因为最终的查询落在一台服务器上.但是如果按照商户的维度查询,则代价非常高.需要查询全部64台服务器.在分页的情况下,更加恶化.比如某个商户查询第10页的数据(按照订单的创建时间).需要在每台数据库服务器上查询前100条数

MySQL DBA及Linux企业集群实战工程师

MySQL DBA及Linux企业集群实战工程师 2015,来一场随时随地的学习之旅 开启我赢职场MySQL学习之旅 不能错过的我赢之旅 任性就是想问就问 谁是你的群聊小伙伴 学习点滴我主宰 名师在线答与问 职业入门--数据库基础知识及安装MySQL MySQL课程介绍 讲师访谈 深入了解什么是数据库 MySQL从万千数据库中脱颖而出 选择学习哪个版本的MySQL 搭建学习MySQL的实验环境 提前熟悉一下MySQL环境 Linux下基于官方YUM源安装MySQL Linux下基于官方源码包包安

MySQL优化分库分表,为什么要分表,分表以后如何进行排序查询,业务如何设计?

MySQL优化分库分表,为什么要分表,分表以后如何进行排序查询,业务如何设计? 昨天面试新人的时候,遇到了这么一个问题,按照自己的想法大体聊了一些,但大多是感性的,并没有完整的了解why and how. 今天查了一些相关的资料,包括<MySQL性能调优与架构设计>.<高性能Mysql>,慢慢的整体理解,请大家指正. 之一,为什么要分表? 分表,按形式,有水平分表和主附分表.水平分表常见于按ID取模或者按日期将相同表结构的内容散列到不同的表上,主附分表常见于有对应关系的多张表,通过

分布式缓存技术redis学习系列(四)——redis高级应用(集群搭建、集群分区原理、集群操作)

本文是redis学习系列的第四篇,前面我们学习了redis的数据结构和一些高级特性,点击下面链接可回看 <详细讲解redis数据结构(内存模型)以及常用命令> <redis高级应用(主从.事务与锁.持久化)> 本文我们继续学习redis的高级特性--集群.本文主要内容包括集群搭建.集群分区原理和集群操作的学习. Redis集群简介 Redis 集群是3.0之后才引入的,在3.0之前,使用哨兵(sentinel)机制(本文将不做介绍,大家可另行查阅)来监控各个节点之间的状态.Redi

16、MySQL数据库分库分表备份脚本

MySQL数据库分库分表备份脚本 ===================学员分享分库分表========================== 脚本单双引号的区别: 单引号是强引用,强制输出是所见即所得. 双引号是解析变量 和 多个字符串.数字等连接一个字符串 条件1  ||    条件2                      或   假真   真假 条件1 && 条件2                      并   真真    假假 !条件1  && 条件2    

Mysql、MariaDB 新型主从集群配置GTID

前文谢了<Mysql.MariaDB 传统主从集群配置>,该技术已经非常成熟.从Mysql5.6和MariaDB10.0开始,有了新型的主从方案GTID,不过这两个系统到这个版本出现了分支,具体实现已经不同,配置方法也不同,下文分别讲述. MariaDB: 我用的版本还是10.1版,目前该版本还不是稳定版,但不影响测试.先部署部署好两个数据库实例,参见http://bangbangba.blog.51cto.com/3180873/1701857 直到创建好复制用户. 我们这里的由于是新创建的

数据库mysql 自动分库分表备份脚本

数据库mysql 自动分库分表备份脚本 当我们在公司中遇到数据库的备份,项目比较多,经常进行数据库和表的添加工作,那么我们 想要让系统脚本自动进行查询数据库里的库和表结构,然后进行自动的定期进行数据库和表的定期份, 那么我们该如何实现呢,大家看看以下的脚本: vi mysql_backup.sh #!/bin/sh #backup tiandao bbs edoing #coding tonye.li MYUSER=root MYPASS=meidi SOCKET=/data/3306/mysq

redis高级应用(集群搭建、集群分区原理、集群操作)

文章主目录 Redis集群简介 Redis集群搭建 Redis集群分区原理 集群操作 参考文档 本文是redis学习系列的第四篇,前面我们学习了redis的数据结构和一些高级特性,点击下面链接可回看 <详细讲解redis数据结构(内存模型)以及常用命令> <redis高级应用(主从.事务与锁.持久化)> 本文我们继续学习redis的高级特性--集群.本文主要内容包括集群搭建.集群分区原理和集群操作的学习. 回到顶部 Redis集群简介 Redis 集群是3.0之后才引入的,在3.0

MySQL单机优化---分表、分区、分库

一.分表: 水平分表:根据条件把数据分为N个表(例如:商品表中有月份列,则可以按月份进行水平分表). 使用场景:一张表中数据太多,查询效率太慢. 当需要同时查询被水平分表的多张表时: 在两条SQL语句中间加union,就能把两表数据合并展示. union:数据合并时去重. Union all:数据合并展示不去重. 垂直分表:将表的字段拆出来变成一张表,两表通过外键建立一对一关系. 使用场景:有些表记录数并不多,但是字段却很长,表占用空间很大,检索表时需要执行大量I/O,严重降低了性能. 当需要同

基于NFS共享的Mysql之HA高可用集群实现

192.168.139.8 作为NFS-Server ,192.168.139.2和192.168.13.4用来安装mysql ___________________________________________________________________________________________以下操作在192.168.139.8上操作 [[email protected] ~]# fdisk -l //首先要准备一块磁盘进行分区,用来做lv,再将此lv格式化后挂载并