Mysql分割槽表 介紹和使用

2021-08-06 06:31:00 字數 2998 閱讀 5011

你有一張表,儲存引擎為innodb,裡面儲存的資料量達到了上億級別。

此時,因為資料量巨大,肯定不能在每次查詢的時候都掃瞄全表。

就算是使用索引(b-tree),除非使用索引覆蓋查詢,否則資料庫伺服器需要根據查詢的結果回表,查詢所有符合條件的資料,

如果資料量巨大,會產生大量的隨機io,最終使得應用程式僵死。另外,這種資料量下,索引維護的代價也非常高。

分割槽表適用於資料量非常大,並且擁有某個特定字段可以據此將資料劃分成幾塊的場景。

例如使用者購買的商品記錄表,可以依據購買時間,將全量記錄劃分為多個子分割槽。

例如,有一張儲存了3億條商品資料的表goods,出於效能考慮,我們可能會將表拆分成300個子表,每張表儲存100w條資料,此時,我們有了goods_0、goods_1….goods_299。

但這樣做的問題是:開發者需要自行按照特殊條件,對於自身要操作的表做判斷,然後自行改寫sql去操作指定的物理子表,

這樣的問題在於,將開發邏輯變得複雜化,並且**變得」醜」了。

如果你使用了某些orm框架,那麼就更煩人了,你需要改寫model定位自身table的邏輯。

分割槽表可以用一張表儲存大量資料,達到和物理分表同樣的效果,但操作起來更簡單,對於使用者來說和普通表無差別

mysql在建立表時使用partition by字句定義每個分割槽,例子如下:

create table goods (

create_date datetime not null,

........

) engine=innodb partition by range(year(create_date))(

partition p_2014 values less than (2015) engine=innodb,

partition p_2015 values less than (2016) engine=innodb,

partition p_2016 values less than (2017) engine=innodb,

partition p_others values less than maxvalue engine=innodb);

上面的建表語句中,我們建立了乙個商品表goods,其中定義了建立時間(create_date)字段,

我們使用範圍分割槽方式建立分割槽表,然後我們使用該字段的年份作為分割槽條件,

分別將時間在2023年之前的資料存放在了p_2014分割槽,

將時間在2023年之前(也就是2023年整年的資料)存放在了p_2015分割槽。

將時間在2023年之前(也就是2023年整年的資料)存放在了p_2016分割槽。

然後將2023年以及之後的資料都放在了最後乙個分割槽p_others。

分割槽表不僅可以根據字段範圍分割槽,也支援通過鍵值、雜湊和列表分割槽,不過我們最常用的就是根據範圍進行分割槽。

可以使用數學模函式進行分割槽,也可以根據時間範圍進行分割槽,

甚至我們可以自行定義乙個分割槽列,將想要落在相同分割槽的資料的該列都設為相同值。

select:

讀鎖不會影響同時發生的其他讀操作,不必擔心。

insert:

分割槽層先開啟並鎖住所有分割槽表,確定由哪個分割槽接收這條記錄,再釋放全表鎖並鎖住對應分割槽,將記錄寫入對應底層表

delete:

類似於insert

update:

分割槽層先開啟並鎖住所有底層表,然後確定要更新的資料在哪個分割槽,取出該資料並更新,再判斷更新後的資料應該

儲存到哪個分割槽,最後對新分割槽進行寫入操作,然後對老分割槽做刪除操作。

雖然每個操作都會「開啟並鎖住所有分割槽表」,但這並不表示分割槽表在處理過程中是鎖住全表的,

分割槽表的鎖機制取決於我們所選擇的儲存引擎,如果我們使用innodb構建分割槽表,

那麼會在分割槽層(通過分割槽條件定位到分割槽後)釋放表鎖,之後的鎖機制會按照innodb方式進行。

1、使得一張錶能儲存更多的資料

2、讓開發者更加專心於業務邏輯,而不是繁瑣的sql條件匹配

3、讓你在使用orm框架時,更加的簡單方便,無需修改orm框架,和操作普通表完全相同

4、對於表的維護更加方便,當你需要修改字段或者調整索引時,無需同時操作300張表

5、當某些資料不再有價值時,可以直接清空乙個分割槽,降低刪除的代價(普通的刪除需要根據where條件匹配後再回表刪除),例如刪除2023年之前的記錄,可以直接清空p_2014分割槽,因為每個分割槽在底層是單獨的子表,所以無需根據時間字段篩選

上面例子中,按照時間分割槽的方式,會帶來乙個問題:

隨著時間的增長,我們也需要新增分割槽,否則所有的資料都會落到最後的分割槽中,成為乙個大分割槽,

當然,新增乙個分割槽的代價是非常小的,完全不用太擔心,但如果你已經懶到不想改表了,可以使用

自增id取模進行hash來避免這個問題,例如建立100個分割槽,然後以id取模100的方式作為分割槽條件。

這樣做的好處是增長的資料都可以完全的均分到所有分割槽,不會造成大分割槽的存在,

但壞處是每個分割槽的資料量都會一直增長,並且在進行範圍操作時會鎖住大量分割槽。

因為需要根據分割槽列來確定資料所在分割槽,所以分割槽列必須作為查詢條件,

如果不使用分割槽列的查詢條件,那麼就無法進行分割槽過濾,mysql最終會掃瞄所有分割槽,這就和我們的初衷相違背了。

1、所有分割槽都必須使用相同的儲存引擎

2、某些儲存引擎不支援分割槽(merge、csv、federated)

3、一張表最多只能有1024個分割槽

4、分割槽表中無法對非分割槽列建立唯一索引(unique index)

5、分割槽表中無法使用外來鍵

Mysql分割槽表使用

一 什麼是分割槽表 分割槽表就是按一定規則將一張表分割成多個部分,達到和物理分表同樣的效果,但操作起來更 簡單,不同於物理分表那樣使用時還需要指定使用的資料表。對於使用者來說和操作普通表無差別。二 優勢與限制 1 優勢 2 限制 三 分割槽型別 1 range分割槽 基於乙個給定連續區間範圍,把資料...

分割槽表介紹

通常情況下,我們建立的表都是未分割槽的表,或者說,只有乙個分割槽的表,資料只能儲存在乙個檔案組 file group 中,預設情況下,表資料儲存在primary檔案組。對錶進行分割槽後,每乙個分割槽都獨立儲存在檔案組 file group 中。把錶分割槽,實際上是把邏輯上完整的表,按照特定的字段拆分...

MySQL分割槽表

分割槽表是一種粗粒度,簡易的索引策略,適用於大資料的過濾場景.最適合的場景是,沒有合適的索引時,對其中幾個分割槽表進行全表掃瞄.或者只有乙個分割槽表和索引是熱點,而且這個分割槽和索引能夠全部儲存在記憶體中.限制單錶分割槽數不要超過150個,並且注意某些導致無法做分割槽過濾的細節,分割槽表對於單條記錄...