資料庫數據分區
『壹』 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的映射關系