数据库数据分区
‘壹’ Mysql分表和分区的区别,分库和分表区别
分表和分区的区别:
一、什么是mysql分表,分区
分表:从表面意思上看呢,就是把一张表分成N多个小表,具体请看:mysql分表的3种方法
分区:分区呢就是把一张表的数据分成N多个区块,这些区块可以在同一个磁盘上,也可以在不同的磁盘上,具体请参考mysql分区功能详细介绍,以及实例
二、mysql分表和分区有什么区别呢
1、实现方式上
①mysql的分表是真正的分表,一张表分成很多表后,每一个小表都是完正的一张表,都对应三个文件,一个.MYD数据文件,.MYI索引文件,.frm表结构文件。
[root@BlackGhosttest]#ls|grepuser
alluser.MRG
alluser.frm
user1.MYD
user1.MYI
user1.frm
user2.MYD
user2.MYI
user2.frm
简单说明一下,上面的分表呢是利用了merge存储引擎(分表的一种),alluser是总表,下面有二个分表,user1,user2。他们二个都是独立的表,取数据的时候,我们可以通过总表来取。这里总表是没有.MYD,.MYI这二个文件的,也就是说,总表他不是一张表,没有数据,数据都放在分表里面。我们来看看.MRG到底是什么东西
[root@BlackGhosttest]#catalluser.MRG|more
user1
user2
#INSERT_METHOD=LAST
从上面我们可以看出,alluser.MRG里面就存了一些分表的关系,以及插入数据的方式。可以把总表理解成一个外壳,或者是联接池。
②分区不一样,一张大表进行分区后,他还是一张表,不会变成二张表,但是他存放数据的区块变多了。
[root@BlackGhosttest]#ls|grepaa
aa#P#p1.MYD
aa#P#p1.MYI
aa#P#p3.MYD
aa#P#p3.MYI
aa.frm
aa.par
从上面我们可以看出,aa这张表,分为二个区,p1和p3,本来是三个区,被我删了一个区。我们都知道一张表对应三个文件.MYD,.MYI,.frm。分 区呢根据一定的规则把数据文件和索引文件进行了分割,还多出了一个.par文件,打开.par文件后你可以看出他记录了,这张表的分区信息,根分表中的.MRG有点像。分区后,还是一张,而不是多张表。
如orderid,userid,ordertime,.....
ordertime<2015-01-01 #p0
ordertime<2015-04-01 #p1
ordertime<2015-07-01 #p2
ordertime<2015-10-01 #p3
ordertime<2016-01-01 #p4
按照时间分区。大部分只查询最近的订单数据,那么大部分只访问一个分区,比整个表小多了,数据库可以更加好的缓存,性能也提高了。这个是数据库分的,应用程序透明,无需修改。
2,数据处理上
①、分表后,数据都是存放在分表里,总表只是一个外壳,存取数据发生在一个一个的分表里面。看下面的例子:
select * from alluser where id='12'表面上看,是对表alluser进行操作的,其实不是的。是对alluser里面的分表进行了操作。
②、分区呢,不存在分表的概念,分区只不过把存放数据的文件分成了许多小块,分区后的表呢,还是一张表。数据处理还是由自己来完成。
3、提高性能上
①、分表后,单表的并发能力提高了,磁盘I/O性能也提高了。并发能力为什么提高了呢,因为查寻一次所花的时间变短了,如果出现高并发的话,总表可以根据不同 的查询,将并发压力分到不同的小表里面。磁盘I/O性能怎么搞高了呢,本来一个非常大的.MYD文件现在也分摊到各个小表的.MYD中去了。
②、mysql提出了分区的概念,我觉得就想突破磁盘I/O瓶颈,想提高磁盘的读写能力,来增加mysql性能。
在这一点上,分区和分表的测重点不同,分表重点是存取数据时,如何提高mysql并发能力上;而分区呢,如何突破磁盘的读写能力,从而达到提高mysql性能的目的。
4、实现的难易度上
①、分表的方法有很多,用merge来分表,是最简单的一种方式。这种方式根分区难易度差不多,并且对程序代码来说可以做到透明的。如果是用其他分表方式就比分区麻烦了。
②、分区实现是比较简单的,建立分区表,根建平常的表没什么区别,并且对开代码端来说是透明的。
三、mysql分表和分区有什么联系呢
1、都能提高mysql的性高,在高并发状态下都有一个良好的表面。
2、分表和分区不矛盾,可以相互配合的,对于那些大访问量,并且表数据比较多的表,我们可以采取分表和分区结合的方式(如果merge这种分表方式,不能和分区配合的话,可以用其他的分表试),访问量不大,但是表数据很多的表,我们可以采取分区的方式等。
分库分表区别:
1、什么是分库分表?
从字面上简单理解,就是把原本存储于一个库的数据分块存储到多个库上,把原本存储于一个表的数据分块存储到多个表上。
2、为什么要分库分表?
数据库中的数据量不一定是可控的,在未进行分库分表的情况下,随着时间和业务的发展,库中的表会越来越多,表中的数据量也会越来越大,相应地,数据操作,增删改查的开销也会越来越大;另外,一台服务器的资源(CPU、磁盘、内存、IO等)是有限的,最终数据库所能承载的数据量、数据处理能力都将遭遇瓶颈,。
3、分库分表的实施策略。
如果你的单机性能很低了,那可以尝试分库。分库,业务透明,在物理实现上分成多个服务器,不同的分库在不同服务器上。分区可以把表分到不同的硬盘上,但不能分配到不同服务器上。一台机器的性能是有限制的,用分库可以解决单台服务器性能不够,或者成本过高问题。
当分区之后,表还是很大,处理不过来,这时候可以用分库。
orderid,userid,ordertime,.....
userid%4=0,用分库1
userid%4=1,用分库2
userid%4=2, 用分库3
userid%4=3,用分库4
上面这个就是一个简单的分库路由,根据userid选择分库,即不同的服务器
分库分表有垂直切分和水平切分两种。
3.1、何谓垂直切分,即将表按照功能模块、关系密切程度划分出来,部署到不同的库上。例如,我们会建立定义数据库workDB、商品数据库payDB、用户数据库userDB、日志数据库logDB等,分别用于存储项目数据定义表、商品定义表、用户数据表、日志数据表等。
如userid,name,addr一个表,为了防止表过大,分成2个表。
userid,name
userid,addr
3.2、何谓水平切分,当一个表中的数据量过大时,我们可以把该表的数据按照某种规则,例如userID散列、按性别、按省,进行划分,然后存储到多个结构相同的表,和不同的库上。
例如,我们的userDB中的用户数据表中,每一个表的数据量都很大,就可以把userDB切分为结构相同的多个userDB:part0DB、part1DB等,再将userDB上的用户数据表userTable,切分为很多userTable:userTable0、userTable1等,然后将这些表按照一定的规则存储到多个userDB上。
3.3、应该使用哪一种方式来实施数据库分库分表,这要看数据库中数据量的瓶颈所在,并综合项目的业务类型进行考虑。
如果数据库是因为表太多而造成海量数据,并且项目的各项业务逻辑划分清晰、低耦合,那么规则简单明了、容易实施的垂直切分必是首选。
而如果数据库中的表并不多,但单表的数据量很大、或数据热度很高,这种情况之下就应该选择水平切分,水平切分比垂直切分要复杂一些,它将原本逻辑上属于一体的数据进行了物理分割,除了在分割时要对分割的粒度做好评估,考虑数据平均和负载平均,后期也将对项目人员及应用程序产生额外的数据管理负担。
在现实项目中,往往是这两种情况兼而有之,这就需要做出权衡,甚至既需要垂直切分,又需要水平切分。我们的游戏项目便综合使用了垂直与水平切分,我们首先对数据库进行垂直切分,然后,再针对一部分表,通常是用户数据表,进行水平切分。
4 分库分表存在的问题。
4.1 事务问题。
在执行分库分表之后,由于数据存储到了不同的库上,数据库事务管理出现了困难。如果依赖数据库本身的分布式事务管理功能去执行事务,将付出高昂的性能代价;如果由应用程序去协助控制,形成程序逻辑上的事务,又会造成编程方面的负担。
4.2 跨库跨表的join问题。
在执行了分库分表之后,难以避免会将原本逻辑关联性很强的数据划分到不同的表、不同的库上,这时,表的关联操作将受到限制,我们无法join位于不同分库的表,也无法join分表粒度不同的表,结果原本一次查询能够完成的业务,可能需要多次查询才能完成。
4.3 额外的数据管理负担和数据运算压力。
额外的数据管理负担,最显而易见的就是数据的定位问题和数据的增删改查的重复执行问题,这些都可以通过应用程序解决,但必然引起额外的逻辑运算,例如,对于一个记录用户成绩的用户数据表userTable,业务要求查出成绩最好的100位,在进行分表之前,只需一个order by语句就可以搞定,但是在进行分表之后,将需要n个order by语句,分别查出每一个分表的前100名用户数据,然后再对这些数据进行合并计算,才能得出结果。
‘贰’ 数据库为什么要分区分表
基本思想之什么是分库分表?
从字面上简单理解,就是把原本存储于一个库的数据分块存储到多个库上,把原本存储于一个表的数据分块存储到多个表上。
2 基本思想之为什么要分库分表?
数据库中的数据量不一定是可控的,在未进行分库分表的情况下,随着时间和业务的发展,库中的表会越来越多,表中的数据量也会越来越大,相应地,数据操作,增删改查的开销也会越来越大;另外,由于无法进行分布式式部署,而一台服务器的资源(CPU、磁盘、内存、IO等)是有限的,最终数据库所能承载的数据量、数据处理能力都将遭遇瓶颈。
‘叁’ 璋堣皥镐庝箞瀹炵幇Oracle鏁版嵁搴揿垎鍖鸿〃
Oracle鏁版嵁搴揿垎鍖烘槸浣滀负Oracle鏁版嵁搴撴ц兘浼桦寲镄勪竴绉嶉吨瑕佺殑镓嬫靛拰鏂规硶锛屽仛镓嫔ご镄勯”鐩浠ュ墠锛屽彧镵嗗惉杩囧垎鍖虹殑澶у悕锛屾劅瑙夌壒绁炵桡纴鐪嬭
Oracle鏁版嵁搴揿垎鍖烘槸浣滀负Oracle鏁版嵁搴撴ц兘浼桦寲镄勪竴绉嶉吨瑕佺殑镓嬫靛拰鏂规硶锛屽仛镓嫔ご镄勯”鐩浠ュ墠锛屽彧镵嗗惉杩囧垎鍖虹殑澶у悕锛屾劅瑙夌壒绁炵桡纴鐪嬭佹煇镆愰珮镓嫔湪璁ㄨ轰细涓婂じ澶稿叾璋堟椂锛岀湡鏄楠傝嚜宸卞﹁压涓岖簿锛屾渶杩戜綔GPS鏂归溃镄勯”鐩锛屽勭悊镄勬暟鎹閲忚揪鍒颁简鍑犲崄GB锛屼负浜嗘弧瓒崇郴缁熺殑瀹炴椂镐ц佹眰锛屽繀椤绘彁楂樻暟鎹镄勬煡璇㈡晥鐜囷纴杩欐牱灏卞繀椤婚氲繃鍒嗗尯锛屼互瑙g噧鐪変箣镐ワ紒
鍏堣磋村垎鍖虹殑濂藉勫惂锛
1) 澧炲己鍙鐢ㄦэ细濡傛灉琛ㄧ殑镆愪釜鍒嗗尯鍑虹幇鏁呴㱩锛岃〃鍦ㄥ叾浠栧垎鍖虹殑鏁版嵁浠岖劧鍙鐢锛
2) 缁存姢鏂逛究锛氩傛灉琛ㄧ殑镆愪釜鍒嗗尯鍑虹幇鏁呴㱩锛岄渶瑕佷慨澶嶆暟鎹锛屽彧淇澶嶈ュ垎鍖哄嵆鍙锛
3) 鍧囱I/O锛氩彲浠ユ妸涓嶅悓镄勫垎鍖烘椠灏勫埌纾佺洏浠ュ钩琛I/O锛屾敼锽勬暣涓绯荤粺镐ц兘锛
4) 鏀瑰杽镆ヨ㈡ц兘锛氩瑰垎鍖哄硅薄镄勬煡璇㈠彲浠ヤ粎鎼灭储镊宸卞叧蹇幂殑鍒嗗尯锛屾彁楂樻绱㈤熷害銆
Oracle鏁版嵁搴撴彁渚涘硅〃鎴栫储寮旷殑鍒嗗尯鏂规硶链変笁绉嶏细
眉 锣冨洿鍒嗗尯
眉 Hash鍒嗗尯锛堟暎鍒楀垎鍖猴级
眉 澶嶅悎鍒嗗尯
涓銆佽寖锲村垎鍖鸿︾粏璇存槑
锣冨洿鍒嗗尯灏辨槸瀵规暟鎹琛ㄤ腑镄勬煇涓鍊肩殑锣冨洿杩涜屽垎鍖猴纴镙规嵁镆愪釜鍊肩殑锣冨洿锛屽喅瀹氩皢璇ユ暟鎹瀛桦偍鍦ㄥ摢涓鍒嗗尯涓娿傚傛牴鎹搴忓彿鍒嗗尯锛屾牴鎹镞堕棿绛夋潵杩涜屽垎鍖恒傛牴鎹搴忓彿锛屾瘆濡傚皬浜2000000镄勬斁鍦╬art01, 2000000~4000000镄勬斁鍦╬art02銆伞
create table AAA
(
id number primary key,
indate date not null
)
partition by range(indate)
(
partition part_01 values less than(to_date(-01-01','yyyy-mm-dd')) tablespace space01,
partition part_02 values less than(to_date(-01-01','yyyy-mm-dd')) tablespace space02,
partition part_03 values less than(maxvalue) tablespace space03
);
space01 space02 space03涓哄缓绔嬬殑涓変釜琛ㄧ┖闂达纴鐩稿綋浜庢妸寤虹珛镄勪竴涓澶х殑琛ㄥ垎鍦ㄤ简3涓涓嶅悓镄勮〃绌洪棿镄勫垎鍖轰笂浜嗐
浜屻丠ash鍒嗗尯锛堟暎鍒楀垎鍖猴级璇︾粏璇存槑
鏁e垪鍒嗗尯涓洪氲繃鎸囧畾鍒嗗尯缂栧彿𨱒ュ潎鍖鍒嗗竷鏁版嵁镄勪竴绉嶅垎鍖虹被鍨嬶纴锲犱负阃氲繃鍦↖/O璁惧囦笂杩涜屾暎鍒楀垎鍖猴纴浣垮缑杩欎簺鍒嗗尯澶у皬涓镊淬备篃灏辨槸鍙锻藉悕鍒嗗尯钖岖О锛岃繖镙峰潎鍖杩涜屾暟鎹鍒嗗竷銆
涓夈佸嶅悎鍒嗗尯璇︾粏璇存槑
链夋椂鍊欐垜浠闇瑕佹牴鎹锣冨洿鍒嗗尯钖庯纴姣忎釜鍒嗗尯鍐呯殑鏁版嵁鍐嶆暎鍒楀湴鍒嗗竷鍦ㄥ嚑涓琛ㄧ┖闂翠腑锛岃繖镙锋垜浠灏辫佷娇鐢ㄥ嶅悎鍒嗗尯銆傚嶅悎鍒嗗尯鏄鍏堜娇鐢ㄨ寖锲村垎鍖猴纴铹跺悗鍦ㄦ疮涓鍒嗗尯鍐呭啀浣跨敤鏁e垪鍒嗗尯镄勪竴绉嶅垎鍖烘柟娉曘
partition by range(indate)subpartition by hash(id)
subpartitions 3 store in (space01, space02, space03)
(
partition part_01 values less than(to_date(钬2006-01-01钬,钬檡yyy-mm-dd钬)),
partition part_02 values less than(to_date(钬2010-01-01钬,钬檡yyy-mm-dd钬)),
partition part_03 values less than(maxvalue)
);
锲涖佸垎鍖鸿〃镎崭綔
1銆佹彃鍏ヨ板綍锛歩nsert into AAA values(1 ,sysdate);
2銆佹煡璇㈠垎鍖鸿〃璁板綍锛歴elect * from AAA partition(part_01);
3銆佹洿鏂板垎鍖鸿〃镄勮板綍锛歶pdate AAA partition(part_01) t set indate=钬欌檞here id=1; 浣嗘槸褰撴洿鏂扮殑镞跺欐寚瀹氢简鍒嗗尯锛岃屾牴鎹镆ヨ㈢殑璁板綍涓嶅湪璇ュ垎鍖轰腑镞讹纴灏嗕笉浼氭洿鏂版暟鎹
4銆佸垹闄ゅ垎鍖鸿〃璁板綍锛歞elete from AAA partition(part_02) t where id=4; 濡傛灉鎸囧畾浜嗗垎鍖猴纴钥屾浔浠朵腑镄勬暟鎹鍙堜笉鍦ㄨュ垎鍖轰腑镞讹纴灏嗕笉浼氩垹闄や换浣曟暟鎹銆
5銆佸炲姞涓涓鍒嗗尯锛歛lter table AAA add partition part_04 values less than(to_date(钬2012-01-01钬,钬檡yyy-mm-dd钬)) tablespace dinya_spa ce03; 澧炲姞涓涓鍒嗗尯镄勬椂鍊欙纴锛屽炲姞镄勫垎鍖虹殑𨱒′欢蹇呴’澶т簬鐜版湁鍒嗗尯镄勬渶澶у硷纴钖﹀垯绯荤粺灏嗘彁绀篛RA-14074 partition bound must collate higher than that of the last partition 阌栾銆
6銆佸悎骞朵竴涓鍒嗗尯锛歛lter table AAA merge partitions part_01,part_02 into partition part_02; ,濡傛灉鍦ㄥ悎骞剁殑镞跺欐妸钖埚苟钖庣殑鍒嗗尯瀹氢负part_01镄勬椂鍊欙纴绯荤粺灏嗘彁绀篛RA-14275 cannot reuse lower-bound partition as resulting partition 阌栾銆
7銆佸垹闄ゅ垎鍖猴细alter table AAA drop partition part_01; 鍒犻櫎鍒嗗尯琛ㄧ殑涓涓鍒嗗尯钖庯纴镆ヨ㈣ヨ〃镄勬暟鎹镞舵樉绀猴纴璇ュ垎鍖轰腑镄勬暟鎹宸插叏閮ㄤ涪澶憋纴镓浠ユ墽琛屽垹闄ゅ垎鍖哄姩浣沧椂瑕佹厧閲嶏纴纭淇濆厛澶囦唤鏁版嵁钖庡啀镓ц岋纴鎴栧皢鍒嗗尯钖埚苟銆
浜斻佸缓绔嬬储寮
鍒嗗尯琛ㄥ拰涓鑸琛ㄤ竴镙峰彲浠ュ缓绔嬬储寮曪纴鍒嗗尯琛ㄥ彲浠ュ垱寤哄眬閮ㄧ储寮曞拰鍏ㄥ眬绱㈠紩銆傚綋鍒嗗尯涓鍑虹幇璁稿氢簨锷″苟涓旇佷缭璇佹墍链夊垎鍖轰腑镄勬暟鎹璁板綍镄勫敮涓镐ф椂閲囩敤鍏ㄥ眬绱㈠紩銆
1. 灞閮ㄧ储寮曞垎鍖虹殑寤虹珛锛歝reate index idx_t on AAA(id)
local
(
partition idx_1 tablespace space01,
partition idx_2 tablespace space02,
partition idx_3 tablespace space03
);
2. 鍏ㄥ眬绱㈠紩寤虹珛镞秅lobal 瀛愬彞鍏佽告寚瀹氱储寮旷殑锣冨洿鍊硷纴杩欎釜锣冨洿鍊间负绱㈠紩瀛楁电殑锣冨洿鍊硷细create index idx_t on AAA(id)
global partition by range(id)
(
partition idx_1 values less than (1000) tablespace space01,
partition idx_2 values less than (10000) tablespace space02,
partition idx_3 values less than (maxvalue) tablespace space03
);
褰撶劧涔熷彲浠ヤ笉鎸囧畾绱㈠紩鍒嗗尯钖岖洿鎺ュ规暣涓琛ㄥ缓绔嬬储寮: create index idx_t on AAA(id);
‘肆’ mysql表分区使用及详细介绍
一、分区概念
分区是将一个表分成多个区块进行操作和保存,从而降低每次操作的数据,提高性能。而对于应用来说则是透明的,从逻辑上看只有一张表,但在物理上这个表可能是由多个物理分区组成的,每个分区都是独立的对象,可以进行独立处理。
二、分区作用
1.可以逻辑数据分割,分割数据能够有多个不同的物理文件路径。
2.可以存储更多的数据,突破系统单个文件最大限制。
3.提升性能,提高每个分区的读写速度,提高分区范围查询的速度。
4.可以通过删除相关分区来快速删除数据
5.通过跨多个磁盘来分散数据查询,从而提高磁盘I/O的性能。
6.涉及到例如SUM()、COUNT()这样聚合函数的查询,可以很容易的进行并行处理。
7.可以备份和恢复独立的分区,这对大数据量很有好处。
三、分区能支持的引擎
MySQL支持大部分引擎创建分区,入MyISAM、InnoDB等;不支持MERGE和CSV等来创建分区。同一个分区表中的所有分区必须是同一个存储引擎。值得注意的是,在MySQL8版本中,MyISAM表引擎不支持分区。
四、确认MySQL支持分区
从MySQL5.1开始引入分区功能,可以如下方式查看是否支持:
老版本用:SHOW VARIABLES LIKE '%partition%'
新版本用:show plugins;
五、分区类型
1. RANGE分区:基于属于一个给定连续区间的列值,把多行分配给分区。
例如,可以将一个表通过年份划分成两个分区,2001 -2010年、2011-2020。
2. LIST分区:类似于RANGE分区,LIST是列值匹配一个离散值集合中的某个值来进行选择。
比如 根据字段 把值为1、3、5的放到一起,2、4、6的另外放到一起 等等...
3. HASH分区:基于用户定义的表达式的返回值来进行选择分区,该表达式使用将要插入到表中的这些行的列值来进行计算,这个函数必须产生非负整数值。
通过HASH运算来进行分区,分布的比较均匀
4. KEY分区:类似于按HASH分区,由MySQL服务器提供其自身的哈希函数。
按照KEY进行分区类似于按照HASH分区
六、分区创建注意事项
1. 如果表中存在primary key 或者 unique key 时,分区的列必须是paimary key或者unique key的一个组成部分,也就是说,分区函数的列只能从pk或者uk这些key中取子集
2. 如果表中不存在任何的paimary key或者unique key,则可以指定任何一个列作为分区列
3. 5.5版本前的RANGE、LIST、HASH分区要求分区键必须是int;MySQL5.5及以上,支持非整形的RANGE和LIST分区,即:range columns 和 list columns (可以用字符串来进行分区)。
七、分区命名
1. 分区的名字基本上遵循其他MySQL 标识符应当遵循的原则,例如用于表和数据库名字的标识符。应当注意的是, 分区的名字是不区分大小写的 。
2. 无论使用何种类型的分区,分区总是在创建时就自动的顺序编号,且从0开始记录。
八、 创建分区
1. RANGE分区:
CREATE TABLE `test01` (
`dayid` int(11) DEFAULT NULL,
`mac` varchar(32) NOT NULL DEFAULT '',
`dtype` varchar(50) NOT NULL DEFAULT ''
) ENGINE=InnoDB DEFAULT CHARSET=utf8
/*!50100 PARTITION BY LIST (dayid)
(PARTITION p20171205 VALUES IN (20171205) ENGINE = InnoDB,
PARTITION p20171204 VALUES IN (20171204) ENGINE = InnoDB,
PARTITION p20171206 VALUES IN (20171206) ENGINE = InnoDB,
PARTITION p20171207 VALUES IN (20171207) ENGINE = InnoDB) */
解读:以上为 uuid小于5时放到p0分区下,uuid大于5且小于10放到p1分区下,uuid大于10且小于15放到p2分区下,uuid大于15 一直到最大值的存在p3分区下
2. LIST分区:
CREATE TABLE tbl_test (
uuid INT NOT NULL,
title VARCHAR(20)
)
)
PARTITION BY List (uuid) (
PARTITION p0 VALUES in (1,2,3,5),
PARTITION p1 VALUES in (7,9,10),
PARTITION p2 VALUES in (11,15)
)
);
解读:以上为uuid 等于1/2/3/5时放到p0分区,7/9/10放到p1分区,11/15放到p2分区。当时用insert into时 如果uuid的值不存在p0/p1/p2分区时,则会插入失败而报错。
3. HASH分区:
HASH分区主要用来确保数据在预先确定数目的分区中平均分布。在RANGE分区和LIST分区中必须明确指定一个指定的列值或列值集合以指定应该保存在哪个分区中。而在HASH分区中,MySQL会自动完成这些工作,要做的只是基于将要被哈希的列值指定一个表达式,以及指定被分区的表将要被分割成的分区数量,如:
CREATE TABLE tbl_test (
uuid INT NOT NULL,
title VARCHAR(20)
))
PARTITION BY HASH (uuid) (
PARTITIONS 3
));
解读:MySQL自动创建3个分区,在执行insert into时,根据插入的uuid通过算法来自动分配区间。
注意:
(1) 由于每次插入、更新、删除一行,这个表达式都要计算一次,这意味着非常复杂的表达式可能会引起性能问题,尤其是在执行同时影响大量行的运算(例如批量插入)的时候。
(2) 最有效率的哈希函数是只对单个表列进行计算,并且它的值随列值进行一致的增大或减小,因为这考虑了在分区范围上的“修剪”。也就是说,表达式值和它所基于的列的值变化越接近,就越能有效地使用该表达式来进行HASH分区。
3.1:线性HASH分区
线性HASH分区在“PARTITION BY”子句中添加“LINEAR”关键字。
线性HASH分区的有点在于增加、删除、合并和拆分分区将变得更加快捷,有利于处理含有及其大量数据的表。它的缺点在于各个分区间数据的分布不大可能均衡。
4. KEY分区
类似于HASH分区,HASH分区允许用户自定义的表达式,而KEY分区则不允许使用用户自定义的表达式;HASH分区只支持整数分区,KEY分区支持除了blob和text类型之外的其他数据类型分区。
与HASH分区不同,创建KEY分区表的时候,可以不指定分区键,默认会选择使用主键或唯一键作为分区键,没有主键或唯一键,就必须指定分区键。
CREATE TABLE tbl_test (
uuid INT NOT NULL,
title VARCHAR(20)
))
PARTITION BY LINEAR Key (uuid)
PARTITIONS 3;
解读:根据分区键来进行分区
5. 子分区
子分区是分区表中,每个分区的再次分割,适合保存非常大量的数据。
CREATE TABLE tbl_test (
registerTime Date
))
PARTITION BY GANGE(YEAR(registerTime))
SUBPARTITION BY HASH (TO_DAYS(registerTime))
SUBPARTITIONS 2
(
PARTITION p0 VALUES LESS THAN (2017),
PARTITION p1 VALUES LESS THAN (2020),
PARTITION p2 VALUES LESS THAN MAXVALUE
);
解读:主分区使用RANGE按照年来进行分区,有3个RANGE分区。这3个分区中又被进一步分成了2个子分区,实际上,整个表被分成了3 * 2 = 6个分区。每个子分区按照天进行HASH分区。小于2017的放在一起,2017-2020的放在一起,大于2020的放在一起。
注意:
(1) 在MySQL5.1中,对于已经通过RANGE或LIST分区了的表在进行子分区是可能的。子分区既可以使用HASH分区,也可以使用KEY分区。这也被称为复合分区。
(2) 每个分区必须有相同数量的子分区。
(3) 如果在一个分区表上的任何分区上使用SUBPARTITION来明确定义任何子分区,那么就必须定义所有的子分区。
(4) 每个SUBPARTITION子句必须包含(至少)子分区的一个名字。
(5) 在每个子分区内,子分区的名字必须是惟一的,目前在整个表中,也要保持唯一。例如:
PARTITION BY RANGE(YEAR(registerTime))
SUBPARTITION BY HASH(TO_DAYS(registerTime))
(
PARTITION p0 VALUES LESS THAN (2017) (
SUBPARTITION s0,
SUBPARTITION s1
),
PARTITION p1 VALUES LESS THAN (2020) (
SUBPARTITION s2,
SUBPARTITION s3
),
PARTITION p2 VALUES LESS THAN MAXVALUE (
SUBPARTITION s4,
SUBPARTITION s5
)
)
子分区可以用于特别大的表,可以在多个磁盘间分配数据和索引。例如:
SUBPARTITION s0
DATA DIRECTORY = '/disk0/data'
INDEX DIRECTORY = '/disk0/idx'
,
,
SUBPARTITION s1
DATA DIRECTORY = '/disk1/data'
INDEX DIRECTORY = '/disk1/idx'
九、MySQL分区处理NULL值的方式
MySQL中的分区禁止空值NULL上没有进行处理,无论它是一个列值还是一个用户定义表达式的值,一般而言,在这种情况下MySQL把NULL视为0。如果你希望回避这种做法,你应该在设计表时声明列“NOT NULL”。
十、分区管理概述
可以对分区进行添加、删除、重新定义、合并或拆分等管理操作。
① RANGE和LIST分区的管理
1. 删除分区语句如:alter table tbl_test drop partition p0;
注意:
(1) 当删除了一个分区,也同时删除了该分区中所有的数据。
(2) 可以通过show create table tbl_test;来查看新的创建表的语句。
(3) 如果是LIST分区的话,删除的数据不能新增进来,因为这些行的列值包含在已经删除了的分区的值列表中。
2. 添加分区语句如:alter table tbl_test add partition(partition p3 values less than(50));
注意:
(1) 对于RANGE分区的表,只可以添加新的分区到分区列表的最高端。
(2) 对于LIST分区的表,不能添加已经包含在现有分区值列表中的任意值。
3. 如果希望能不丢失数据的条件下重新定义分区,可以使用如下语句:
ALTER TABLE tbl_name REORGANIZE PARTITION partition_list INTO(partition_definitions)
(1) 拆分分区如:
ALTER TABLE tbl_name REORGANIZE PARTITION partition_list INTO(partition s0 values less than(5),partition s1 values less than(10));
或者如:
ALTER TABLE tbl_name REORGANIZE PARTITION p0 INTO(partition s0 values in(1,2,3), partition s1 values in(4,5));
(2) 合并分区如:ALTER TABLE tbl_name REORGANIZE PARTITION s0,s1 INTO(partition p0 values in(1,2,3,4,5));
4. 删除所有分区,但保留数据,形式:ALTER TABLE tbl_name remove partitioning;
② HASH和KEY分区的管理
1. 减少分区数量语句如:ALTER TABLE tbl_name COALESCE PARTITION 2;
2. 添加分区数量语句如:ALTER TABLE tbl_name add PARTITION partitions 2;
③ 其他分区管理语句
1. 重建分区 :类似于先删除保存在分区中的所有记录,然后重新插入它们,可用于整理分区碎片。如:ALTER table tbl_name REBUILD PARTITION p2,p3;
2. 优化分区 :如果从分区中删除了大量的行,或者对一个带有可变长度的行(也就是说,有VARCHAR,BLOB或TEXT类型的列)做了许多修改,可以使用 ALTER TABLE tbl_name OPTIMIZE PARTITION来收回没有使用的空间,并整理分区数据文件的碎片。如:ALTER TABLE tbl_name OPTIMIZE PARTITION p2,p3;
3. 分析分区 :读取并保存分区的键分布,如:ALTER TABLE tbl_name ANALYZE PARTITION p2,p3;
4. 检查分区 :检查分区中的数据或索引是否已经被破坏,如:ALTER TABLE tbl_name CHECK PARTITION p2,p3;
5. 修补分区 :修补被破坏的分区,如:ALTER TABLE tbl_name REPAIR PARTITION p2,p3;
十、查看分区信息
1. 查看分区信息:select * from information_schema.partitions where table_schema='arch1' and table_name = 'tbl_test' G;
2. 查看分区上的数据:select * from tbl_test partition(p0);
3. 查看MySQL会操作的分区:explain partitions select * from tbl_test where uuid = 2;
十一、 局限性
1. 最大分区数目不能超过1024,一般建议对单表的分区数不要超过50个。
2. 如果含有唯一索引或者主键,则分区列必须包含在所有的唯一索引或者主键在内。
3. 不支持外键。
4. 不支持全文索引,对分区表的分区键创建索引,那么这个索引也将被分区。
5. 按日期进行分区很合适,因为很多日期函数可以用。但是对字符串来说合适的分区函数不太多。
6. 只有RANGE和LIST分区能进行子分区,HASH和KEY分区不能进行子分区。
7. 临时表不能被分区。
8. 分区表对于单条记录的查询没有优势。
9. 要注意选择分区的成本,没插入一行数据都需要按照表达式筛选插入的分区。
10. 分区字段尽量不要可以为null
‘伍’ 数据库分区和分表的区别
分区、分表、分库的详细理解
一、什么是分区、分表、分库
分区
就是把一张表的数据分成N个区块,在逻辑上看最终只是一张表,但底层是由N个物理区块组成的
分表
就是把一张表按一定的规则分解成N个具有独立存储空间的实体表。系统读写时需要根据定义好的规则得到对应的字表明,然后操作它。
分库
一旦分表,一个库中的表会越来越多
将整个数据库比作图书馆,一张表就是一本书。当要在一本书中查找某项内容时,如果不分章节,查找的效率将会下降。而同理,在数据库中就是分区。
二、常用的单机数据库的瓶颈
问题描述
单个表数据量越大,读写锁,插入操作重新建立索引效率越低。
单个库数据量太大(一个数据库数据量到就是极限)
单个数据库服务器压力过大
读写速度遇到瓶颈(并发量几百)
三、分区
什么时候考虑使用分区?
一张表的查询速度已经慢到影响使用的时候。
sql经过优化
数据量大
表中的数据是分段的
对数据的操作往往只涉及一部分数据,而不是所有的数据
分区解决的问题
主要可以提升查询效率
分区的实现方式(简单)
mysql5 开始支持分区功能
四、分表
什么时候考虑分表?
一张表的查询速度已经慢到影响使用的时候。
sql经过优化
数据量大
当频繁插入或者联合查询时,速度变慢
分表解决的问题
分表后,单表的并发能力提高了,磁盘I/O性能也提高了,写操作效率提高了
查询一次的时间短了
数据分布在不同的文件,磁盘I/O性能提高
读写锁影响的数据量变小
插入数据库需要重新建立索引的数据减少
分表的实现方式(复杂)
需要业务系统配合迁移升级,工作量较大
分区和分表的区别与联系
分区和分表的目的都是减少数据库的负担,提高表的增删改查效率。
分区只是一张表中的数据的存储位置发生改变,分表是将一张表分成多张表。
当访问量大,且表数据比较大时,两种方式可以互相配合使用。
当访问量不大,但表数据比较多时,可以只进行分区。
常见分区分表的规则策略(类似)
Range(范围)
Hash(哈希)
按照时间拆分
Hash之后按照分表个数取模
在认证库中保存数据库配置,就是建立一个DB,这个DB单独保存user_id到DB的映射关系