数据库 之 Mysql的表分区

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了数据库 之 Mysql的表分区相关的知识,希望对你有一定的参考价值。

把表分区,但是还在同一台服务器上,

分区是将数据分成多个位置上,分成多张表,实际是一张逻辑表(是虚表),被分成了多张表,但是管理的时候可以按照管理一张表的时候管理。

分区在逻辑上是同一张表,分表的话,每一张表是独立的

以下是三种常见的分区方法:

可以按range(范围)切分,如1--10万行或者时间范围

按hash值切分:取模

按list(列表)来切分:如华东片区或者华北片区

分区相关选项查看如下,分区要是主键或者是主键的组成部分

MariaDB [(none)]> help create table;中的选项partition_options就是分区的选项,partition_definition为分区的选项

例子

例一:根据范围(值大小)分区

以下语句表示一张students表创建成三个分区

一般从最小的数值开始定义,这里有个默认的内建变量maxvalue,为该表的最大值

MariaDB [sunny]> create table testpartition (id int,name varchar(100),age tinyint unsigned not null,gender enum('F','M')) partition by range(age)(partition youngman values less than (40),partition middleman values less than (60),partition oldman values less than maxvalue);

用desc查看表的结构为一张表

MariaDB [sunny]> desc testpartition;

在shell命令执行

[[email protected] mysql]#cd /var/lib/mysql/sunny

可以看到对于表testpartition有三个单独的表空间,即三个testpartition.*ibd的文件,但是表结构只有一个,即testpartition.frm 

对shell命令下,生成一组随机值,插入testpartition表里

定义gender数组

[[email protected] sunny]#gender=('F' 'M')

定义数组

插入1000行数据,注意外部使用双引号,sql语句内使用单引号

[[email protected] sunny]#for i in {1..1000};do mysql -uroot -pPass1234 -e "insert into sunny.testpartition values ($i,'stud$i',$[$RANDOM%80+18],'${gender[$RANDOM%2]}');";done;

此时,在sunny.testpartition生成1000条记录

通过这个例子,我们可以得出结论是,虽然我们通过范围进行了表切分,但是我们是对同一张表进行操作。但是这1000条记录是被分割到不同的表空间里进行存储

验证,如下命令,可以看到 testpartition#P#middleman.ibd,testpartition#P#oldman.ibd和testpartition#P#youngman.ibd已经有大小

[[email protected] sunny]#ll /var/lib/mysql/sunny -h

例二:根据id值hash后进行分区

注意,要指定分区数量,如以下partitions 5表示对5进行取模,即分成5个区,注意hash字段的类型,字符类型如char或者varchar不能被hash,因为需要填充多余的类型,这样的字段不能被hash

MariaDB [sunny]> create table hashpartition (id int,name varchar(100) not null,age tinyint unsigned,gender enum ('F','M')) partition by hash(id) partitions 5;

在路径/var/lib/mysql/sunny下生成5个表空间

 hashpartition#P#p0.ibd -- hashpartition#P#p4.ibd 

例三:根据列表划分

假设表listpartition有一个字段majorid,有九个值,为1--9,根据majorid进行列表分区

MariaDB [sunny]> create table listpartition (id int,name varchar(100) not null,age tinyint unsigned,gender enum ('F','M'),majorid tinyint unsigned not null) partition by list(majorid) (partition p0 values in (1,4,7),partition p1 values in (2,5,8),partition p2 values in (3,6,9));

那么majorid 为1,4,7三个值的数据会被分配到listpartition#P#p0.ibd里

majorid 为2,5,8三个值的数据会被分配到listpartition#P#p1.ibd里

majorid 为3,6,9三个值的数据会被分配到listpartition#P#p2.ibd里

到此,表分区介绍完成。


如果表分区还不能解决性能的问题,建议考虑分表或者是分库

分库的原因

服务器面临大量写操作而无法负载,解决方案如下

1.分库:如用户信息放在一个库上,购物信息放在另一个库上

2.分库不能解决的话,就通过路由设备,将大量的写请求分散到后端的服务器上,将同一个用户的信息都发到同一服务器上,可以使得同一用户快速查看到所有的订单。

节点级的的冗余:每一个主机后端有多个从服务器,用来分散读操作,降低压力,因此,每一个主服务器就是一个集群。当主服务器异常时,后端的从服务器直接选举出新的主服务器

数据级的冗余:当用户请求到来时,每一个节点上做数据存放的槽,如每个节点做四个槽,每一个槽就是数据存放单位,每一个槽都有一个id,当用户请求过来时,对槽进行取模,将命中槽的请求发往对应的槽。注意,这里可以对槽进行备份,每一个槽都有副本进行冗余,副本可以放在另一个服务器上空闲的槽位上,当任何一个服务器异常,也不会影响数据,对槽取模可以保证数据读取的均衡请求。每个槽上的数据称为数据片。分片可以实现分散写操作。分片的架构中,前端的路由设备很关键,在分片级别做冗余,每一个分片的副本可以提供读操作。但是分片技术比较复杂。正常情况下,一个站点通常有三层:内容,业务,数据层。随着业务规模的增加,迭代增加,修改架构。

分表的原因

分表将大表分解成若干个实例的表,每一个表是独立可用。

当一张的数据达到几百万时,你查询一次所花的时间会变多,如果有联合查询的话,我想有可能会死在那儿了。分表的目的就在于此,减小数据库的负担,缩短查询时间。

根据个人经验,mysql执行一个sql的过程如下:

1,接收到sql;2,把sql放到排队队列中 ;3,执行sql;4,返回执行结果。在这个执行过程中最花时间在什么地方呢?第一,是排队等待的时间,第二,sql的执行时间。其实这二个是一回事,等待的同时,肯定有sql在执行。所以我们要缩短sql的执行时间。

mysql中有一种机制是表锁定和行锁定,为什么要出现这种机制,是为了保证数据的完整性,我举个例子来说吧,如果有二个sql都要修改同一张表的同一条数据,这个时候怎么办呢,是不是二个sql都可以同时修改这条数据呢?很显然mysql对这种情况的处理是,一种是表锁定(myisam存储引擎),一个是行锁定(innodb存储引擎)。表锁定表示你们都不能对这张表进行操作,必须等我对表操作完才行。行锁定也一样,别的sql必须等我对这条数据操作完了,才能对这条数据进行操作。如果数据太多,一次执行的时间太长,等待的时间就越长,这也是我们为什么要分表的原因。

过于表分区,分表,分库的区别,建议查看博客:https://www.cnblogs.com/langtianya/p/4997768.html

更多关于表分区的内容,建议查看博客:http://blog.51yip.com/mysql/949.html


以上是关于数据库 之 Mysql的表分区的主要内容,如果未能解决你的问题,请参考以下文章

MySql之分区分表

MySQL的表分区

MySQL 已经存在大量数据的表做分区

MySQL:将大表拆分为分区或单独的表?

MySQL的表分区详解

MySQL的表分区