你有一張表,儲存引擎為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個,並且注意某些導致無法做分割槽過濾的細節,分割槽表對於單條記錄...