MySQL的分表和分区介绍

本文涉及的产品
云数据库 RDS MySQL Serverless,0.5-2RCU 50GB
简介:

    在日常开发或维护中经常会遇到大表的情况,所谓的大表是指存储了百万级乃至千万级条记录的表。这样的表过于庞大,导致数据库在查询和插入的时候耗时太长,性能低下,如果涉及联合查询的情况,性能会更加糟糕。分表和表分区的目的就是减少数据库的负担,提高数据库的效率,通常点来讲就是提高表的增删改查效率。

一、什么是分表:

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


1、根据分表技术对海量数据的优化方式目前有2种方法:

    1、垂直分割:把一个数据量很大的表,根据某个字段的属性或使用频繁程度分类拆分为多个表,或者把一个业务系统的库分到不同的实例上。

wKioL1hQ7jmDPCHCAANG5mJz12g690.png-wh_50

    2、水平分割:根据一列或者多列的值把数据行放到多个独立的表里,水平分表方式可以通过多个低配置主机整合起来,实现高性能。

wKiom1hQ7kqDBxVRAALNDOLRIqc744.png-wh_50

    3、两者的优缺点:

    水平优点:拆分规则抽象好,JION操作基本可以数据库做,不存在单表大数据、高并发的性能瓶颈,应用端改造较少,提高系统的稳定性和负载能力


    缺点:分片事务一致性难以解决,在MyCAT2.0之前MySQL5.7之前,还是数据弱XA。数据多次扩展难度维护量大,夸库JOIN性能差


    垂直优点:拆分后业务清晰,拆分规则明确,系统之间整合或者拓展容易,数据库维护简单

    缺点:部分业务无法使用JOIN,只能通过接口方式解决,提供系统能够复杂度,受每种业务不同的限制存在性能瓶颈,不容易数据扩展跟性能提高。

    事务处理复杂,垂直切分后按照业务的分类将表分散到不同的库,会导致有些业务表过于庞大,存在单库读写与存储瓶颈。



二、什么是分区

    分区就是把一张表的数据分成N多个区域,分区后,表面上还是一张表,但数据散列到多个位置根据数据量的大小,结合实际业务

1、分区方式有:

    a、range分区:主要用于时间列分区、值范围,行数据基于一个给定连续分区的列值放入分区。如销售类的表,可以根据年来分区存放销售记录

    b、list分区:面向离散的值,分区要指定的值,当插入指定的数据到指定分区表去,如指定某些值在特定分区里。

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

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

三、分区实例:

创建redundant格式

      如果表中存在主键或是唯一索引时,分区列必须是唯一索引的一个组成部分
唯一索引     
 create table t11(
      col1 int not null,
      col2 date not null,
      col3 int not null,
      col4 int not null,
      unique key (col1,col2))
      partition by hash(col1)
      partitions 4;
 哈希     
create table t121(
      col1 int not null,
      col2 date not null,
      col3 int not null,
      col4 int not null,
      unique key (col1,col2))
      partition by hash(year(col2))
      partitions 4;
主键
create table t31(
      col1 int not null,
      col2 date not null,
      col3 int not null,
      col4 int not null,
      primary key (col1,col2))
      partition by hash(col1)
      partitions 8;
主键和索引同时存在:
create table t41(
      col1 int not null,
      col2 date not null,
      col3 int not null,
      col4 int not null,
      unique key(col4),
      primary key (col1))
      partition by hash(col1)
      partitions 5;

      唯一索引可以允许是null值,分区列只要是唯一索引的一个组成部分,不需要整个唯一索引列都是分区列
create table t223332(
col1 int null,
col2 date null,
col3 int null,
col4 int null)
partition by hash(col3)
partitions 4;
    没有主键或唯一索引,可以指定任何一个列为分区列
create table t223332(
col1 int null,
col2 date null,
col3 int null,
col4 int null,
key(col4))
partition by hash(col3)
partitions 4;
    rang 分区:主要用于时间列分区,如销售类的表,可以根据年来分区存放销售记录
    定义:行数据基于一个给定连续分区的列值放入分区,
       id 是主键
    create table t3(
    id int)engine=innodb
    partition by range(id)(
    partition p0 values less than (10),
    partition p1 values less than (20)
 );
    查看数据文件
    t3.frm t.par
    insert into t select 9;
    insert into t select 10;
    insert into t select 15;
    查看分区状态
   use information_schema
    select * from PARITIONS where table_schema=''test and table_name='t3'\G;
    partition_method代表分区类型    
  当不满足分区条件的时候报错
  table has no partition for value 40
 alter table t add partition(partition p2 values less than maxalue);  
  主要用于时间列分区,如销售类的表,可以根据年来分区存放销售记录(year(date))取年的时间
    create table sales(
    money int not null,date datetime)engine=innodb
    partition by range (year(date))(
    partition p2008 values less than (2009),
     partition p2009 values less than (2010),
       partition p2010 values less than (2011)
       );
       insert into sales select 100,'2008-01-01'; 
      insert into sales select 100.'2008-02-01'; 
      insert into sales select 100.'2008-01-02'; 
      insert into sales select 100,'2009-03-01'; 
      insert into sales select 100,'2010-01-01'; 
     
 list 分区:面向离散的值,分区要指定的值,当插入指定的数据到指定分区表去,
    create table t_list (a int,b int)engine=innodb
    partition by list(b)(partition p0 values in(1,3,5,7,9),
    partition p1 values in (0,2,4,6,8));
    
      insert into  t4 select 1, 3;
      insert into  t4 select 1, 5;
      insert into  t4 select 1, 8;
      insert into  t4 select 1, 6;
      table has no partition for values10
      值得注意的是,LIST分区没有类似如“VALUES LESS THAN MAXVALUE”这样的包含其他值在内的定义。将要匹配的任何值都必须在值列表中找到。
    LIST分区除了能和RANGE分区结合起来生成一个复合的子分区,与HASH和KEY分区结合起来生成复合的子分区也是可能的。
      
      
  注意:innodb myisam区别
  在用insert插入多行数据的过程中遇到分区为定义的值,myisam、innodb存储引擎的处理完全不同,
  myisam 一条不成功,之前的成功值,会进入表中
  innodb只要一条不成功,所有都不成功
create table t(a int,b int)engine=myisam partition by list(b)(partition p0 values in (1,3,5,7,9),partition p1 values in (0,2,4,6,8));
insert into t values (1,2),(2,4),(6,19),(5,3);
insert into t values (1,2),(2,4),(6,19),(5,3);
ERROR 1526 (HY000): Table has no partition for value 19
select * from t;
+------+------+
| a    | b    |
+------+------+
|    1 |    2 |
|    2 |    4 |
+------+------+
2 rows in set (0.00 sec)

create table tt(a int,b int)engine=innodb partition by list(b)(partition p0 values in (1,3,5,7,9),partition p1 values in (0,2,4,6,8));
insert into tt values (1,2),(2,4),(6,19),(5,3);
insert into tt values (1,2),(2,4),(6,19),(5,3);
ERROR 1526 (HY000): Table has no partition for value 19
 select * from tt;
Empty set (0.00 sec)
      hash 分区:根据用户的表达式的返回值来进行分区,返回值不能是负数
      要在create table 语句上添加一个partition by hash(expr)句子,其中expr是一个返回一个整数的表达式,它可以仅仅是数字段类型为mysql整型的列名字
      后面在添加一个partitions num子句,num是一个非负数
      create table t_hash(a int,b date)engine=innodb
      partition by hash(YEAR(b))
      partitions 4;
      insert into t_hash select 1,'2010-04-01';
     
      create table tt_hash(a int,b date)engine=innodb
      partition by hash (a)
      partitions 4;

      
      #######################################
      columns分区
      区别于其他分区,分区条件必须是整型,如果不是整型也应该需要通过函数将其转化为整型 columns分时是rang list分区的进化
      支持整型类型
      日期类型date datetime其余的日期类型不予支持
      字符串类型 char varcha binary  varbinary ,blok和text类型的不予支持
      create table tt_column_range(a int,b int)engine=innodb partition by range columns(a,b)(
      partition p0 values less than (0,10),
      partition p1 values less than (10,20),
      partition p2 values less than (20,30),
      partition p3 values less than (30,40),
      partition p4 values less than (40,50)
      );
      
      
     子分区:MYSQL数据库允许在rang和list的分区上再进行hask或者key子分区,
     create table ts(a int,b date)engine=innodb
     partition by range(year(b))
     subpartition by hash(to_days(b))
     subpartitions 3(
     partition p0 values less than (2013),     
       partition p0 values less than (2014),
       partition p1 values less than (2015)
  partition p2 values less than maxvalue);
 

create table ts(a int,b date
partition by range(year(b))
subpartition by hash(to_days(b))(
partition p0 values less than(2014)(
subpartition s0,
subpartition s1)

partition p1 values less than (2015)(
subpartition s2,
subpartition s3
)
partition p2 values less than maxvalue(
subpartition s4
subpartition s5
)
)
      
      
      
每个子分区必须包含分区的名字。  
子分区的名字唯一的。


分区中null值
create table t3(
    id int)engine=innodb
    partition by range(id)(
    partition p0 values less than (10),
    partition p1 values less than (20);
 );
 null值 放最左边的。

总结:了解基础的分表的原则、方法,实际还需要根据业务结合,达到业务架构最优。

                            如有不妥,欢迎指正!


本文转自 DBAspace 51CTO博客,原文链接:http://blog.51cto.com/dbaspace/1882681


相关实践学习
基于CentOS快速搭建LAMP环境
本教程介绍如何搭建LAMP环境,其中LAMP分别代表Linux、Apache、MySQL和PHP。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助     相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
2月前
|
关系型数据库 MySQL 中间件
|
6月前
|
存储 关系型数据库 MySQL
【mysql】MySQL 分区快速入门
【mysql】MySQL 分区快速入门
62 0
|
22天前
|
缓存 关系型数据库 MySQL
MySQL查询优化:提速查询效率的13大秘籍(合理使用索引合并、优化配置参数、使用分区优化性能、避免不必要的排序和group by操作)(下)
MySQL查询优化:提速查询效率的13大秘籍(合理使用索引合并、优化配置参数、使用分区优化性能、避免不必要的排序和group by操作)(下)
|
2月前
|
存储 关系型数据库 MySQL
MySQL分区的优缺点
数据库中分区是将表或索引的数据划分成更小、更可管理的部分的一种技术。这些部分被称为分区,每个分区可以独立地进行维护和管理。
50 0
|
3月前
|
NoSQL 算法 关系型数据库
redis与mysql的数据一致性问题( 网络分区)
redis与mysql的数据一致性问题( 网络分区)
23 0
|
8月前
|
关系型数据库 MySQL 大数据
MySQL分区与分表:优化性能与提升可扩展性
本文深入探讨了MySQL数据库中的分区与分表策略,通过详细的代码示例,解释了分区的概念与用途、不同的分区类型以及创建分区表的步骤。同时,文章还介绍了分表的概念、策略和实际操作方法,以代码演示展示了如何创建分表、插入数据以及查询数据。分区和分表作为优化数据库性能和提升可扩展性的关键手段,通过本文的阐述,读者将能够深入了解如何根据数据特点选择合适的分区方式,以及如何灵活地处理大量数据,提高查询和维护效率。这些技术将为数据库设计和优化提供有力支持,确保在大数据场景下能够高效地管理和查询数据。
317 0
|
4月前
|
SQL 算法 关系型数据库
mysql集群分区
mysql集群分区
17 0
|
7月前
|
关系型数据库 MySQL Java
Mysql集群部署实现主从复制读写分离分表分库 2
Mysql集群部署实现主从复制读写分离分表分库
45 0
|
7月前
|
存储 关系型数据库 MySQL
Mysql集群部署实现主从复制读写分离分表分库 1
Mysql集群部署实现主从复制读写分离分表分库
74 0
|
7月前
|
存储 关系型数据库 MySQL
Mysql分表分库背景知识(2)
Mysql分表分库背景知识(2)
56 0