数据库的分区表
⑴ 浠涔堟槸鍒呜〃鍜屽垎鍖篗ysql鏁版嵁搴揿垎鍖哄拰鍒呜〃鏂规硶
1銆佷负浠涔堣佸垎琛ㄥ拰鍒嗗尯
镞ュ父寮鍙戜腑鎴戜滑缁忓父浼氶亣鍒板ぇ琛ㄧ殑𨱍呭喌锛屾墍璋撶殑澶ц〃鏄鎸囧瓨鍌ㄤ简锏句竾绾т箖镊冲崈涓囩骇𨱒¤板綍镄勮〃銆傝繖镙风殑琛ㄨ繃浜庡签澶э纴瀵艰嚧鏁版嵁搴揿湪镆ヨ㈠拰鎻掑叆镄勬椂鍊栾楁椂澶闀匡纴镐ц兘浣庝笅锛屽傛灉娑夊强镵斿悎镆ヨ㈢殑𨱍呭喌锛屾ц兘浼氭洿锷犵碂绯曘傚垎琛ㄥ拰琛ㄥ垎鍖虹殑鐩镄勫氨鏄鍑忓皯鏁版嵁搴撶殑璐熸媴锛屾彁楂樻暟鎹搴撶殑鏁堢巼锛岄氩父镣规潵璁插氨鏄鎻愰珮琛ㄧ殑澧炲垹鏀规煡鏁堢巼銆
2銆佷粈涔堟槸鍒呜〃鍜屽垎鍖
2.1 鍒呜〃
鍒呜〃鏄灏嗕竴涓澶ц〃鎸夌収涓瀹氱殑瑙勫垯鍒呜В鎴愬氩紶鍏锋湁镫绔嫔瓨鍌ㄧ┖闂寸殑瀹炰綋琛锛屾垜浠鍙浠ョО涓哄瓙琛锛屾疮涓琛ㄩ兘瀵瑰簲涓変釜鏂囦欢锛孧YD鏁版嵁鏂囦欢锛.MYI绱㈠紩鏂囦欢锛.frm琛ㄧ粨鏋勬枃浠躲傝繖浜涘瓙琛ㄥ彲浠ュ垎甯冨湪钖屼竴鍧楃佺洏涓婏纴涔熷彲浠ュ湪涓嶅悓镄勬満鍣ㄤ笂銆俛pp璇诲啓镄勬椂鍊欐牴鎹浜嫔厛瀹氢箟濂界殑瑙勫垯寰楀埌瀵瑰簲镄勫瓙琛ㄥ悕锛岀劧钖庡幓镎崭綔瀹冦
2.2 鍒嗗尯
鍒嗗尯鍜屽垎琛ㄧ浉浼硷纴閮芥槸鎸夌収瑙勫垯鍒呜В琛ㄣ备笉钖屽湪浜庡垎琛ㄥ皢澶ц〃鍒呜В涓鸿嫢骞蹭釜镫绔嬬殑瀹炰綋琛锛岃屽垎鍖烘槸灏嗘暟鎹鍒嗘靛垝鍒嗗湪澶氢釜浣岖疆瀛樻斁锛屽彲浠ユ槸钖屼竴鍧楃佺洏涔熷彲浠ュ湪涓嶅悓镄勬満鍣ㄣ傚垎鍖哄悗锛岃〃闱涓婅缮鏄涓寮犺〃锛屼絾鏁版嵁鏁e垪鍒板氢釜浣岖疆浜嗐俛pp璇诲啓镄勬椂鍊欐搷浣灭殑杩樻槸澶ц〃钖嶅瓧锛宒b镊锷ㄥ幓缁勭粐鍒嗗尯镄勬暟鎹銆
鍒嗗尯镄勪富瑕佺洰镄勬槸涓轰简鍦ㄧ壒瀹氱殑SQL镎崭綔涓鍑忓皯鏁版嵁璇诲啓镄勬婚噺浠ョ缉鍑忓搷搴旀椂闂淬
2.3 mysql鍒呜〃鍜屽垎鍖烘湁浠涔堣仈绯诲憿锛
1锛夈侀兘鑳芥彁楂榤ysql镄勬ц兘锛屽湪楂桦苟鍙戠姸镐佷笅閮芥湁涓涓镩濂界殑琛ㄧ幇銆
2锛夈佸垎琛ㄥ拰鍒嗗尯涓岖煕鐩撅纴鍙浠ョ浉浜挜厤钖堢殑锛屽逛簬闾d簺澶ц块梾閲忥纴骞朵笖琛ㄦ暟鎹姣旇缉澶氱殑琛锛屾垜浠鍙浠ラ噰鍙栧垎琛ㄥ拰鍒嗗尯缁揿悎镄勬柟寮忥纴璁块梾閲忎笉澶э纴浣嗘槸琛ㄦ暟鎹寰埚氱殑琛锛屾垜浠鍙浠ラ噰鍙栧垎鍖虹殑鏂瑰纺绛夈
3锛夈佸垎琛ㄦ妧链鏄姣旇缉楹荤储镄勶纴闇瑕佹坠锷ㄥ幓鍒涘缓瀛愯〃锛宎pp链嶅姟绔璇诲啓镞跺欓渶瑕佽$畻瀛愯〃钖嶃傞噰鐢╩erge濂戒竴浜涳纴浣嗕篃瑕佸垱寤哄瓙琛ㄥ拰閰岖疆瀛愯〃闂寸殑union鍏崇郴銆
4锛夈佽〃鍒嗗尯鐩稿逛簬鍒呜〃锛屾搷浣沧柟渚匡纴涓嶉渶瑕佸垱寤哄瓙琛ㄣ
3銆佸垎琛ㄧ殑鍑犵嶆柟寮
3.1 mysql闆嗙兢
瀹冨苟涓嶆槸鍒呜〃锛屼絾璧峰埌浜嗗拰鍒呜〃鐩稿悓镄勪綔鐢ㄣ傞泦缇ゅ彲鍒嗘媴鏁版嵁搴撶殑镎崭綔娆℃暟锛屽皢浠诲姟鍒嗘媴鍒板氩彴鏁版嵁搴扑笂銆傞泦缇ゅ彲浠ヨ诲啓鍒嗙伙纴鍑忓皯璇诲啓铡嫔姏銆备粠钥屾彁鍗囨暟鎹搴撴ц兘銆
3.2 镊瀹氢箟瑙勫垯鍒呜〃
澶ц〃鍙浠ユ寜镦т笟锷$殑瑙勫垯𨱒ュ垎瑙d负澶氢釜瀛愯〃銆傞氩父涓轰互涓嫔嚑绉岖被鍨嬶纴涔熷彲镊宸卞畾涔夎勫垯銆
Range锛堣寖锲达级_杩欑嶆ā寮忓厑璁稿皢鏁版嵁鍒掑垎涓嶅悓锣冨洿銆备緥濡傚彲浠ュ皢涓涓琛ㄩ氲繃骞翠唤鍒掑垎鎴愯嫢骞蹭釜鍒嗗尯銆
Hash锛埚搱甯岋级_杩欎腑妯″纺鍏佽搁氲繃瀵硅〃镄勪竴涓鎴栧氢釜鍒楃殑Hash Key杩涜岃$畻锛屾渶钖庨氲繃杩欎釜Hash镰佷笉钖屾暟鍊煎瑰簲镄勬暟鎹鍖哄烟杩涜屽垎鍖恒备緥濡傚彲浠ュ缓绔嬩竴涓瀵硅〃涓婚敭杩涜屽垎鍖虹殑琛ㄣ
Key锛堥敭鍊硷级_涓婇溃Hash妯″纺镄勪竴绉嶅欢浼革纴杩欓噷镄凥ash Key鏄疢ySQL绯荤粺浜х敓镄勚
List锛堥勫畾涔夊垪琛锛埙杩欑嶆ā寮忓厑璁哥郴缁熼氲繃棰勫畾涔夌殑鍒楄〃镄勫兼潵瀵规暟鎹杩涜屽垎鍓层
Composite锛埚嶅悎妯″纺锛埙浠ヤ笂妯″纺镄勭粍钖堜娇鐢
鍒呜〃瑙勫垯涓庡垎鍖鸿勫垯涓镙凤纴鍦ㄥ垎鍖烘ā鍧楄︾粏浠嬬粛銆
涓嬮溃浠Range绠鍗曚粙缁崭笅濡备綍鍒呜〃锛堟寜镦у勾浠借〃锛夈
锅囱捐〃缁撴瀯链4涓瀛楁碉细镊澧瀒d锛屽揿悕锛屽瓨娆鹃噾棰濓纴瀛樻炬棩链
鎶婂瓨娆炬棩链熶綔涓鸿勫垯鍒呜〃锛屽垎鍒鍒涘缓鍑犱釜琛
2011骞达细account_2011
2012骞达细account_2012
??
2015骞达细account_2015
app鍦ㄨ诲啓镄勬椂鍊欐牴鎹镞ユ湡𨱒ユ煡镓惧瑰簲镄勮〃钖嶏纴闇瑕佹坠锷ㄦ潵鍒ゅ畾銆
3.3 鍒╃敤merge瀛桦偍寮曟搸𨱒ュ疄鐜板垎琛
merge鍒呜〃锛屽垎涓轰富琛ㄥ拰瀛愯〃锛屼富琛ㄧ被浼间簬涓涓澹冲瓙锛岄昏緫涓婂皝瑁呬简瀛愯〃锛屽疄闄呬笂鏁版嵁閮芥槸瀛桦偍鍦ㄥ瓙琛ㄤ腑镄勚
鎴戜滑鍙浠ラ氲繃涓昏〃鎻掑叆鍜屾煡璇㈡暟鎹锛屽傛灉娓呮氩垎琛ㄨ勫緥锛屼篃鍙浠ョ洿鎺ユ搷浣滃瓙琛ㄣ
瀛愯〃2011骞
CREATE TABLE `account_2011` (
`id` int(11) NOT NULL AUTO_INCREMENT ,
`name` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL ,
`money` float NOT NULL ,
`tradeDate` datetime NOT NULL
PRIMARY KEY (`id`)
)
ENGINE=MyISAM
DEFAULT CHARACTER SET=utf8 COLLATE=utf8_general_ci
AUTO_INCREMENT=2
CHECKSUM=0
ROW_FORMAT=DYNAMIC
DELAY_KEY_WRITE=0
;
瀛愯〃2012骞
CREATE TABLE `account_2012` (
`id` int(11) NOT NULL AUTO_INCREMENT ,
`name` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL ,
`money` float NOT NULL ,
`tradeDate` datetime NOT NULL
PRIMARY KEY (`id`)
)
ENGINE=MyISAM
DEFAULT CHARACTER SET=utf8 COLLATE=utf8_general_ci
AUTO_INCREMENT=2
CHECKSUM=0
ROW_FORMAT=DYNAMIC
DELAY_KEY_WRITE=0
;
涓昏〃锛屾墍链夊勾
CREATE TABLE `account_all` (
`id` int(11) NOT NULL AUTO_INCREMENT ,
`name` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL ,
`money` float NOT NULL ,
`tradeDate` datetime NOT NULL
PRIMARY KEY (`id`)
)
ENGINE=MRG_MYISAM
DEFAULT CHARACTER SET=utf8 COLLATE=utf8_general_ci
UNION=(`account_2011`,`account_2012`)
INSERT_METHOD=LAST
ROW_FORMAT=DYNAMIC
;
鍒涘缓涓昏〃镄勬椂鍊欐湁涓狪NSERT_METHOD锛屾寚鏄庢彃鍏ユ柟寮忥纴鍙栧煎彲浠ユ槸锛0 涓嶅厑璁告彃鍏ワ绂FIRST 鎻掑叆鍒癠NION涓镄勭涓涓琛锛 LAST 鎻掑叆鍒癠NION涓镄勬渶钖庝竴涓琛ㄣ
阃氲繃涓昏〃镆ヨ㈢殑镞跺欙纴鐩稿綋浜庡皢镓链夊瓙琛ㄥ悎鍦ㄤ竴璧锋煡璇銆傝繖镙峰苟涓嶈兘浣撶幇鍒呜〃镄勪紭锷匡纴寤鸿杩樻槸镆ヨ㈠瓙琛ㄣ
4銆佸垎鍖虹殑鍑犵嶆柟寮
4.1 Range
create table 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
);
4.2 List
create table 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)
);
4.3 Hash
create table hash(
a int(11),
b datetime
)partition by hash (YEAR(b)
partitions 4;
4.4 key
create table t_key(
a int(11),
b datetime)
partition by key (b)
partitions 4;
4.5 鍒嗗尯绠$悊
4.5.1 鏂板炲垎鍖
ALTER TABLE sale_data
ADD PARTITION (PARTITION p201010 VALUES LESS THAN (201011));
4.5.2 鍒犻櫎鍒嗗尯
褰揿垹闄や简涓涓鍒嗗尯锛屼篃钖屾椂鍒犻櫎浜呜ュ垎鍖轰腑镓链夌殑鏁版嵁銆
ALTER TABLE sale_data DROP PARTITION p201010;
4.5.3 钖埚苟鍒嗗尯
涓嬮溃镄凷QL锛屽皢p201001 - p201009 钖埚苟涓3涓鍒嗗尯p2010Q1 - p2010Q3
ALTER TABLE sale_data
REORGANIZE PARTITION p201001,p201002,p201003,
p201004,p201005,p201006,
p201007,p201008,p201009 INTO
(
PARTITION p2010Q1 VALUES LESS THAN (201004),
PARTITION p2010Q2 VALUES LESS THAN (201007),
PARTITION p2010Q3 VALUES LESS THAN (201010)
);
⑵ 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名用户数据,然后再对这些数据进行合并计算,才能得出结果。
⑶ oracle分区表的分区有几种类型
oracle分区表的分区有四种类型:范围分区、散列分区、列表分区和复合分区。
特点如下:
1、范围分区
就是根据数据库表中某一字段的值的范围来划分分区。
数据中有空值,Oracle机制会自动将其规划到maxvalue的分区中。
2、散列分区
根据字段的hash值进行均匀分布,尽可能地实现各分区所散列的数据相等。
散列分区即为哈希分区,Oracle采用哈希码技术分区,具体分区如何由Oracle说的算,也可能我下一次搜索就不是这个数据了。
3、列表分区
列表分区明确指定了根据某字段的某个具体值进行分区,而不是像范围分区那样根据字段的值范围来划分的。
4、复合分区
根据范围分区后,每个分区内的数据再散列地分布在几个表空间中,这样我们就要使用复合分区。复合分区是先使用范围分区,然后在每个分区同再使用散列分区的一种分区方法。
比如将part_date的记录按时间分区,然后每个分区中的数据分三个子分区,将数据散列地存储在三个指定的表空间中。
(3)数据库的分区表扩展阅读:
分区的恢复方法:
如果数据库运行在archive 模式下,那么一旦数据库损坏则可以通过冷备份(热备份)和归档备份将数据库恢复到断点状态。
数据库控制文件恢复(假设所有控制文件均被破坏):
数据库基于文件系统: 利用操作系统的tar、cp等命令即可。
数据库基于裸设备:dd if=$ORACLE_BASE/con.bak of=/dev/rdrd/drd1 seek=12
⑷ 璋堣皥镐庝箞瀹炵幇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);
⑸ sqlserver中分表和分库有什么区别
MS SQL Server:分区表、分区索引 详解
1. 分区表简介
使用分区表的主要目的,是为了改善大型表以及具有各种访问模式的表的可伸缩性和可管理性。
大型表:数据量巨大的表。
访问模式:因目的不同,需访问的不同的数据行集,每种目的的访问可以称之为一种访问模式。
分区一方面可以将数据分为更小、更易管理的部分,为提高性能起到一定的作用;另一方面,对于如果具有多个CPU的系统,分区可以是对表的操作通过并行的方式进行,这对于提升性能是非常有帮助的。
注意:只能在 SQL Server Enterprise Edition 中创建分区函数。只有 SQL Server Enterprise Edition 支持分区。
2. 创建分区表或分区索引的步骤
可以分为以下步骤:
1. 确定分区列和分区数
2. 确定是否使用多个文件组
3. 创建分区函数
4. 创建分区架构(Schema)
5. 创建分区表
6. 创建分区索引
下面详细描述的创建分区表、分区索引的步骤。
2.1. 确定分区列和分区数
在开始做分区操作之前,首先要确定待分区表的访问模式,该模式决定了什么列适合做分区键。例如,对于销售数据,一般会先根据日期把数据范围限定在一个范围内,然后在这个基础上做进一步的查询,这样,就可以把日期作为分区列。
确定了分区列之后,需要进一步确定分区数,亦即分区表中需要包含多少数据,每个分区的数据应该限定在哪个范围。
2.2. 确定是否使用多个文件组
为了有助于优化性能和维护,应该使用文件组分离数据。一般情况下,如果经常对分区的整个数据集操作,则文件组数最好与分区数相同,并且这些文件组通常应该位于不同的磁盘上,再配合多个CPU,则SQL Server 可以并行处理多个分区,从而大大缩短处理大量复杂报表和分析的总体时间。
2.3. 创建分区函数
分区函数用于定义分区的边界条件,创建分区函数的语法如下:
CREATE PARTITION FUNCTION partition_function_name ( input_parameter_type )
AS RANGE [ LEFT | RIGHT ]
FOR VALUES ( [ boundary_value [ ,...n ] ] )
[ ; ]
参数说明:
partition_function_name
是分区函数的名称。分区函数名称在数据库内必须唯一,并且符合标识符的规则。
input_parameter_type
是用于分区的列的数据类型。当用作分区列时,除 text、ntext、image、xml、timestamp、varchar(max)、nvarchar(max)、varbinary(max)、别名数据类型或 CLR 用户定义数据类型外,所有数据类型均有效。
实际列(也称为分区列)是在 CREATE TABLE 或 CREATE INDEX 语句中指定的。
boundary_value
为使用 partition_function_name 的已分区表或索引的每个分区指定边界值。如果 boundary_value 为空,则分区函数使用 partition_function_name 将整个表或索引映射到单个分区。只能使用 CREATE TABLE 或 CREATE INDEX 语句中指定的一个分区列。
boundary_value 是可以引用变量的常量表达式。这包括用户定义类型变量,或函数以及用户定义函数。它不能引用 Transact-SQL 表达式。boundary_value 必须与 input_parameter_type 中提供的数据类型相匹配或者可隐式转换为该数据类型,并且如果该值的大小和小数位数与 input_parameter_type 中相应的值的大小和小数位数不匹配,则在隐式转换过程中该值不能被截断。
注意:
如果 boundary_value 包含 datetime 或 smalldatetime 文字值,则为这些文字值在计算时假设 us_english 是会话语言。不推荐使用此行为。要确保分区函数定义对于所有会话语言都具有预期的行为,建议使用对于所有语言设置都以相同方式进行解释的常量,例如 yyyymmdd 格式;或者将文字值显式转换为特定样式。有关详细信息,请参阅编写国际化 Transact-SQL 语句。若要确定服务器的语言会话,请运行 SELECT @@LANGUAGE。
...n
指定 boundary_value 提供的值的数目,不能超过 999。所创建的分区数等于 n + 1。不必按顺序列出各值。如果值未按顺序列出,则 Microsoft SQL Server 2005 数据库引擎将对它们进行排序,创建函数并返回一个警告,说明未按顺序提供值。如果 n 包括任何重复的值,则数据库引擎将返回错误。
LEFT | RIGHT
指定当间隔值由 数据库引擎 按升序从左到右排序时,boundary_value [ ,...n ] 属于每个边界值间隔的哪一侧(左侧还是右侧)。如果未指定,则默认值为 LEFT。
创建分区函数示例:
CREATE PARTITION FUNCTION PF_Left(int)
AS RANGE LEFT
FOR VALUES(10, 20)
GO
CREATE PARTITION FUNCTION PF_Right(int)
AS RANGE LEFT
FOR VALUES(10, 20)
GO
PF_Left 和 PF_Right 分区函数的区分:
分区函数 分区1 分区2 分区3
PF_Left <= 10 > 10 and <= 20 > 20
PF_Right < 10 >= 10 and < 20 >= 20
2.4. 创建分区架构(Schema)
创建分区函数后,必须将其与分区架构(Schema)相关联,以便将分区定向至特定的文件组。定义分区架构师,即使多个分区位于同一个文件组中,也必须为每个分区指定一个文件组。
创建分区架构的语法如下:
GOCREATE PARTITION SCHEME partition_scheme_name
AS PARTITION partition_function_name
[ ALL ] TO ( { file_group_name | [ PRIMARY ] } [ ,...n ] )
[ ; ]
参数:
partition_scheme_name
分区方案的名称。分区方案名称在数据库中必须是唯一的,并且符合标识符规则。
partition_function_name
使用分区方案的分区函数的名称。分区函数所创建的分区将映射到在分区方案中指定的文件组。partition_function_name 必须已经存在于数据库中。
ALL
指定所有分区都映射到在 file_group_name 中提供的文件组,或映射到主文件组(如果指定了 [PRIMARY]。如果指定了 ALL,则只能指定一个 file_group_name。
file_group_name | [ PRIMARY ] [ ,...n]
指定用来持有由 partition_function_name 指定的分区的文件组的名称。file_group_name 必须已经存在于数据库中。
如果指定了 [PRIMARY],则分区将存储于主文件组中。如果指定了 ALL,则只能指定一个 file_group_name。分区分配到文件组的顺序是从分区 1 开始,按文件组在 [,...n] 中列出的顺序进行分配。在 [,...n] 中,可以多次指定同一个 file_group_name。如果 n 不足以拥有在 partition_function_name 中指定的分区数,则 CREATE PARTITION SCHEME 将失败,并返回错误。
如果 partition_function_name 生成的分区数少于文件组数,则第一个未分配的文件组将标记为 NEXT USED,并且出现显示命名 NEXT USED 文件组的信息。如果指定了 ALL,则单独的 file_group_name 将为该 partition_function_name 保持它的 NEXT USED 属性。如果在 ALTER PARTITION FUNCTION 语句中创建了一个分区,则 NEXT USED 文件组将再接收一个分区。若要再创建一个未分配的文件组来拥有新的分区,请使用 ALTER PARTITION SCHEME。
在 file_group_name[ 1,...n] 中指定主文件组时,必须像在 [PRIMARY] 中那样分隔 PRIMARY,因为它是关键字。
创建分区架构示例:
CREATE PARTITION FUNCTION myRangePF1 (int)
AS RANGE LEFT FOR VALUES (1, 100, 1000);
GO
CREATE PARTITION SCHEME myRangePS1
AS PARTITION myRangePF1
TO (test1fg, test2fg, test3fg, test4fg);
GO
2.5. 创建分区表
定义了分区函数(逻辑结构)和分区架构(物理结构)后,既可以创建分区表来利用它们。分区表定义应使用的分区架构,而分区架构又定义其使用的分区函数。要将这三者结合起来,必须指定应用于分区函数的列 。范围分区始终只映射到表中的一列。
CREATE TABLE 语法如下:
CREATE TABLE
[ database_name . [ schema_name ] . | schema_name . ] table_name
( { <column_definition> | <computed_column_definition> }
[ <table_constraint> ] [ ,...n ] )
[ ON { partition_scheme_name ( partition_column_name ) | filegroup
| "default" } ]
[ { TEXTIMAGE_ON { filegroup | "default" } ]
[ ; ]
示例如下:
CREATE TABLE myRangePT1
(
ID int not null,
AGE int,
PRIMARY KEY (ID)
) ON myRangePS1(myRangePF1)
GO
2.6. 创建分区索引
索引对于提高查询性能非常有效,因此,一般应该考虑应该考虑为分区表建立索引,为分区表建立索引与为普通表建立索引的语法一直,但是,其行为与普通索引有所差异。
默认情况下,分区表中创建的索引使用与分区表相同分区架构和分区列,这样,索引将于表对齐。将表与其索引对齐,可以使管理工作更容易进行,对于滑动窗口方案尤其如此。若要启动分区切换,表的所有索引都必须对齐。
在创建索引时,也可以指定不同的分区方案(Schema)或单独的文件组(FileGroup)来存储索引,这样SQL Server 不会将索引与表对齐。
在已分区的表上创建索引(分区索引)时,应该注意以下事项:
唯一索引
建立唯一索引(聚集或者非聚集)时,分区列必须出现在索引列中。此限制将使SQL Server只调查单个分区,并确保表中宠物的新键值。如果分区依据列不可能包含在唯一键中,则必须使用DML触发器,而不是强制实现唯一性。
非唯一索引
对非唯一的聚集索引进行分区时,如果未在聚集键中明确指定分区依据列,默认情况下SQL Server 将在聚集索引列中添加分区依据列。
对非唯一的非聚集索引进行分区时,默认情况下SQL Server 将分区依据列添加为索引的包含性列,以确保索引与基表对齐,若果索引中已经存在分区依据列,SQL Server 将不会像索引中添加分区依据列。
3. 分区操作
分区适用于可以缩放的大型表,所以随着时间和环境的变化,就会产生对分区的拆分、合并、移动的需求。
3.1. 拆分与合并分区
通过拆分或合并边界值更改分区函数。通过执行 ALTER PARTITION FUNCTION,可以将使用分区函数的任何表或索引的某个分区拆分为两个分区,也可以将两个分区合并为一个分区。
注意:多个表或索引可以使用同一分区函数。ALTER PARTITION FUNCTION 在单个事务中影响所有这些表或索引。
ALTER PARTITION FUNCTION 语法如下:
ALTER PARTITION FUNCTION partition_function_name()
{
SPLIT RANGE ( boundary_value )
| MERGE RANGE ( boundary_value )
} [ ; ]
参数说明:
partition_function_name
要修改的分区函数的名称。
SPLIT RANGE ( boundary_value )
在分区函数中添加一个分区。boundary_value 确定新分区的范围,因此它必须不同于分区函数的现有边界范围。根据 boundary_value,Microsoft SQL Server 2005 数据库引擎将某个现有范围拆分为两个范围。在这两个范围中,新 boundary_value 所在的范围被视为是新分区。
重要提示:
文件组必须处于联机状态,并且必须由使用此分区函数的分区方案标记为 NEXT USED,以保存新分区。在 CREATE PARTITION SCHEME 语句中,将把文件组分配给分区。如果 CREATE PARTITION SCHEME 语句分配了多余的文件组(在 CREATE PARTITION FUNCTION 语句中创建的分区数少于用于保存它们的文件组),则存在未分配的文件组,分区方案将把其中的某个文件组标记为 NEXT USED。该文件组将保存新的分区。如果分区方案未将任何文件组标记为 NEXT USED,则必须使用 ALTER PARTITION SCHEME 添加一个文件组或指定一个现有文件组来保存新分区。可以指定已保存分区的文件组来保存附加分区。由于一个分区函数可以参与多个分区方案,因此所有使用分区函数(您向其中添加了分区)的分区方案都必须拥有一个 NEXT USED 文件组。否则,ALTER PARTITION FUNCTION 将失败并出现错误,该错误显示缺少 NEXT USED 文件组的一个或多个分区方案。
MERGE [ RANGE ( boundary_value) ]
删除一个分区并将该分区中存在的所有值都合并到剩余的某个分区中。RANGE (boundary_value) 必须是一个现有边界值,已删除分区中的值将合并到该值中。如果最初保存 boundary_value 的文件组没有被剩余分区使用,也没有使用 NEXT USED 属性进行标记,则将从分区方案中删除该文件组。合并的分区驻留在最初不保存 boundary_value 的文件组中。boundary_value 是一个可以引用变量(包括用户定义类型变量)或函数(包括用户定义函数)的常量表达式。它无法引用 Transact-SQL 表达式。boundary_value 必须匹配或可以隐式转换为其对应列的数据类型,并且当值的大小和小数位数不匹配其对应 input_parameter_type 时,将无法在隐式转换过程中被截断。
⑹ 数据库分区和分表的区别
分区、分表、分库的详细理解
一、什么是分区、分表、分库
分区
就是把一张表的数据分成N个区块,在逻辑上看最终只是一张表,但底层是由N个物理区块组成的
分表
就是把一张表按一定的规则分解成N个具有独立存储空间的实体表。系统读写时需要根据定义好的规则得到对应的字表明,然后操作它。
分库
一旦分表,一个库中的表会越来越多
将整个数据库比作图书馆,一张表就是一本书。当要在一本书中查找某项内容时,如果不分章节,查找的效率将会下降。而同理,在数据库中就是分区。
二、常用的单机数据库的瓶颈
问题描述
单个表数据量越大,读写锁,插入操作重新建立索引效率越低。
单个库数据量太大(一个数据库数据量到就是极限)
单个数据库服务器压力过大
读写速度遇到瓶颈(并发量几百)
三、分区
什么时候考虑使用分区?
一张表的查询速度已经慢到影响使用的时候。
sql经过优化
数据量大
表中的数据是分段的
对数据的操作往往只涉及一部分数据,而不是所有的数据
分区解决的问题
主要可以提升查询效率
分区的实现方式(简单)
mysql5 开始支持分区功能
四、分表
什么时候考虑分表?
一张表的查询速度已经慢到影响使用的时候。
sql经过优化
数据量大
当频繁插入或者联合查询时,速度变慢
分表解决的问题
分表后,单表的并发能力提高了,磁盘I/O性能也提高了,写操作效率提高了
查询一次的时间短了
数据分布在不同的文件,磁盘I/O性能提高
读写锁影响的数据量变小
插入数据库需要重新建立索引的数据减少
分表的实现方式(复杂)
需要业务系统配合迁移升级,工作量较大
分区和分表的区别与联系
分区和分表的目的都是减少数据库的负担,提高表的增删改查效率。
分区只是一张表中的数据的存储位置发生改变,分表是将一张表分成多张表。
当访问量大,且表数据比较大时,两种方式可以互相配合使用。
当访问量不大,但表数据比较多时,可以只进行分区。
常见分区分表的规则策略(类似)
Range(范围)
Hash(哈希)
按照时间拆分
Hash之后按照分表个数取模
在认证库中保存数据库配置,就是建立一个DB,这个DB单独保存user_id到DB的映射关系
⑺ 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