MySQL分區和分表


一、概念

1.為什么要分表和分區?
日常開發中我們經常會遇到大表的情況,所謂的大表是指存儲了百萬級乃至千萬級條記錄的表。這樣的表過於龐大,導致數據庫在查詢和插入的時候耗時太長,性能低下,如果涉及聯合查詢的情況,性能會更加糟糕。分表和表分區的目的就是減少數據庫的負擔,提高數據庫的效率,通常點來講就是提高表的增刪改查效率。
2.什么是分表?
分表是將一個大表按照一定的規則分解成多張具有獨立存儲空間的實體表,我們可以稱為子表,每個表都對應三個文件,MYD數據文件,.MYI索引文件,.frm表結構文件。這些子表可以分布在同一塊磁盤上,也可以在不同的機器上。app讀寫的時候根據事先定義好的規則得到對應的子表名,然后去操作它。
3.什么是分區?
分區和分表相似,都是按照規則分解表。不同在於分表將大表分解為若干個獨立的實體表,而分區是將數據分段划分在多個位置存放,可以是同一塊磁盤也可以在不同的機器。分區后,表面上還是一張表,但數據散列到多個位置了。app讀寫的時候操作的還是大表名字,db自動去組織分區的數據。
4.mysql分表和分區有什么聯系呢?
(1)都能提高mysql的性高,在高並發狀態下都有一個良好的表現。
(2)分表和分區不矛盾,可以相互配合的,對於那些大訪問量,並且表數據比較多的表,我們可以采取分表和分區結合的方式(如果merge這種分表方式,不能和分區配合的話,可以用其他的分表試),訪問量不大,但是表數據很多的表,我們可以采取分區的方式等。
(3)分表技術是比較麻煩的,需要手動去創建子表,app服務端讀寫時候需要計算子表名。采用merge好一些,但也要創建子表和配置子表間的union關系。
(4)表分區相對於分表,操作方便,不需要創建子表。

二、分區

1.分區的類型:
(1)Range:把連續區間按范圍划分
例:

create table user(
    id int(11),
    money int(11) unsigned not null,
    date datetime
)
partition by range(YEAR(date))(
    partition p2014 values less than (2015),
    partition p2015 values less than (2016),
    partition p2016 values less than (2017),
    partition p2017 values less than maxvalue
);

(2)List:把離散值分成集合,按集合划分,適合有固定取值列的表
例:

create table user(
    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)
);

(3)Hash:隨機分配,分區數固定
例:

create table user(
    a int(11),
    b datetime
)
partition by hash(YEAR(b))
partitions 4;

(4)Key:類似Hash,區別是只支持1列或多列,且mysql提供自身的Hash函數
例:

create table user(
    a int(11),
    b datetime
)
partition by key(b)
partitions 4;

2.分區管理
(1)新增分區

ALTER TABLE sale_data
ADD PARTITION (PARTITION p201710 VALUES LESS THAN (201711));

(2)刪除分區

--當刪除了一個分區,也同時刪除了該分區中所有的數據。
ALTER TABLE sale_data DROP PARTITION p201710;

(3)分區的合並
下面的SQL,將p201701 - p201709 合並為3個分區p2017Q1 - p2017Q3

ALTER TABLE sale_data
REORGANIZE PARTITION p201701,p201702,p201703,
p201704,p201705,p201706,
p201707,p201708,p201709 INTO
(
    PARTITION p2017Q1 VALUES LESS THAN (201704),
    PARTITION p2017Q2 VALUES LESS THAN (201707),
    PARTITION p2017Q3 VALUES LESS THAN (201710)
);

3.分區應該注意的事項:
(1)做分區時,要么不定義主鍵,要么把分區字段加入到主鍵中。
(2)分區字段不能為NULL,要不然怎么確定分區范圍呢,所以盡量NOT NULL

三、分表

1.垂直分表
把原來有很多列的表拆分成多個表,原則是:
(1)把常用、不常用的字段分開放
(2)把大字段獨立存放在一個表中
2.水平分表
為了解決單表數據量過大的問題,每個水平拆分表的結構完全一致。
例:
(1)按時間結構
如果業務系統對時效性較高,比如新聞發布系統的文章表,可以把數據庫設計成時間結構,按時間分有幾種結構:
(a)平板式
表類似:

article_201701
article_201702
article_201703

用年來分還是用月可自定,但用日期的話表就太多了,也沒這必要。一般建議是按月分就可以。
這種分法,其難處在於,假設我要列20條數據,結果這三張表里都有2條,那么業務上很有可能要求讀三次表。如果時間長了,有幾十張表,而每張表是0條,那不就是要讀完整個系統的表才行么?另外這個結構,要作分頁是比較難實現的。
主鍵:在這個系統中,主鍵是13位帶毫秒的時間戳,不要用自動編號,否則難以通過主鍵定位到表,也可以在查詢時帶上時間,但比較煩瑣。
(b)歸檔式
表類似:

article_old
article_new

為了解決平板式的缺點,可以采用時間歸檔式設計,可以看到這個系統只有兩張表。一張是舊文章表,一張是新文章表,新文章表放2個月的信息,每天定期把2
個月中的最早一天的文章歸入舊表中。這樣一方面可以解決性能問題,因為一般新聞發布系統讀取的都是新的內容,舊的內容讀取少;第二可以委婉地解決功能問
題,比如平板式所說的問題,在歸檔式中最多也只需要讀2張表就完成了。
歸檔式的缺點在於舊表容量還是相對比較大,如果業務允許,可對舊表中的超舊內容進行再歸檔或直接清理掉。
(2)按版塊結構
如果按照文章的所屬版塊進行拆表,比如新聞、體育版塊拆表,一方面可以使每個表數據量分離,另一方面是各版塊之間相互影響可降到最低。假如新聞版塊的數據表損壞或需要維護,並不會影響到體育版塊的正常工作,從而降低了風險。版塊結構同時常用於bbs這樣的系統。
板塊結構也有幾種分法:
(a)對應式
對於版塊數量不多,而且較為固定的形式,就直接對應就好。比如新聞版塊,可以分出新聞的目錄表,新聞的文章表等。

news_category
news_article
sports_category
sports_article

可看到每一個版塊都對應着一組相同的表結構,好處就是一目了然。在功能上,因為版塊之間還是有一些隔閡,所以需要聯合查詢的需求不多,開發上比時間結構的方式要輕松。
主鍵:依舊要考慮的,在這個系統中,主鍵是版塊+時間戳,單純的時間戳或自動編號也能用,查詢時要記得帶上版塊用於定位表。
(b)冷熱式
對應式的缺點是,如果版塊數量很大而且不確定,那要分出的表數量就太多了。舉個例子:百度貼吧,如果按一個詞條一個表設計,那得有多少張表呢?
用這樣的方式吧。

tieba_汽車
tieba_飛機
tieba_火箭
tieba_unite

這個表汽車、火箭表是屬於熱門表,定義為新建的版塊放在unite表里面,待到其超過一萬張主貼的時候才開對應表結構。因為在貼吧這種系統中,冷門版塊
肯定比熱門版塊多得多,這些冷門版塊通常只有幾張帖子,為它們開表也太浪費了;同時熱門版塊數量和訪問量等,又比冷門版塊多得多,非常有特點。
unite表還可以擴展成哈希表,利用詞條的md5編碼,可以分成n張表,我算了一下,md5前一位可分36張表,兩位即是1296張表,足夠了。

tieba_unite_ab
tieba_unite_ac

(3)按哈希結構
哈希結構通常用於博客之類的基於用戶的場合,在博客這樣的系統里有幾個特點,1是用戶數量非常多,2是每個用戶發的文章數量都較少,3是用戶發文章不定
期,4是每個用戶發得不多,但總量仍非常之大。基於這些特點,用以上所說的任何一種分表方式都不合適,一沒有固定的時效不宜用時間拆,二用戶很多,而且還
偏偏都是冷門,所以也不宜用版塊(用戶)拆。
哈希結構在上面有所提及,既然按每個用戶不好直接拆,那就把一群用戶歸進一個表好了。

blog_aa
blog_ab
blog_ac

如上所說,md5取前兩位哈希可以達到1296張表,如果覺得不夠,那就再加一位,總數可達46656張表,還不夠?
表的數量太多,要創建這些表也是挺麻煩的,可以考慮在程序里往數據庫insert之前,多執行一句判斷表存在與否並創建表的語句,很實用,消耗也並不很大。
主鍵:依舊要考慮的,在這個系統中,主鍵是用戶ID+時間戳,單純的時間戳或自動編號也能用,但查詢時要記得帶上用戶名用於定位表。
查看更多:
MySQL優化
MySQL各存儲引擎
MySQL鎖詳解
MySQL事務
MySQL索引類型


參考資料:
http://blog.csdn.net/shmnh/article/details/44055059
http://blog.csdn.net/hijiankang/article/details/9173825
http://blog.csdn.net/feihong247/article/details/8100960
http://niehan.blog.techweb.com.cn/archives/279.html


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM