【摘要】隨著mysql越來越流行,mysql裡面的儲存的資料也越來越大。在日常的工作中,我們會遇到一張表裡面儲存了上億甚至過十億的記錄。這些表裡面儲存了大量的歷史記錄。
對於這些歷史資料的清理是乙個非常頭疼事情,由於所有的資料都乙個普通的表裡。所以只能是啟用乙個或多個帶where條件的delete語句去刪除(一般where條件是時間)。這對資料庫的造成了很大壓力。即使我們把這些刪除了,但底層的資料檔案並沒有變小。面對這類問題,最有效的方法就是在使用分割槽表。最常見的分割槽方法就是按照時間進行分割槽。分割槽乙個最大的優點就是可以非常高效的進行歷史資料的清理。本文主要是介紹下mysql的分割槽表:
目前mysql支援範圍分割槽(range),列表分割槽(list),雜湊分割槽(hash)以及key分割槽四種。下面我們逐一介紹每種分割槽:
基於屬於乙個給定連續區間的列值,把多行分配給分割槽。最常見的是基於時間欄位. 基於分割槽的列最好是整型,如果日期型的可以使用函式轉換為整型。本例中使用to_days函式
p11是乙個預設分割槽,所有大於20171211的記錄都會在這個分割槽。maxvalue是乙個無窮大的值。p11是乙個可選分割槽。如果在定義表的沒有指定的這個分割槽,當我們插入大於20171211的資料的時候,會收到乙個錯誤。
我們在執行查詢的時候,必須帶上分割槽字段。這樣可以使用分割槽剪裁功能
注意執行計畫中的partitions的內容,只查詢了p7,p8,p9,p10三個分割槽,由此來看,使用to_days函式確實可以實現分割槽裁剪。
上面是基於datetime的,如果是timestamp型別,我們遇到上面問題呢?
事實上,mysql提供了一種基於unix_timestamp函式的range分割槽方案,而且,只能使用unix_timestamp函式,如果使用其它函式,譬如to_days,會報如下錯誤:「error 1486 (hy000): constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed」。
而且官方文件中也提到「any other expressions involving timestamp values are not permitted. (see bug #42849.)」。
下面來測試一下基於unix_timestamp函式的range分割槽方案,看其能否實現分割槽裁剪。
針對timestamp的分割槽方案
創表語句如下:
插入資料並檢視上述查詢的執行計畫
同樣也能實現分割槽裁剪。在5.7版本之前,對於data和datetime型別的列,如果要實現分割槽裁剪,只能使用year() 和to_days()函式,在5.7版本中,又新增了to_seconds()函式。
list分割槽
list分割槽和range分割槽類似,區別在於list是列舉值列表的集合,range是連續的區間值的集合。二者在語法方面非常的相似。同樣建議list分割槽列是非null列,否則插入null值如果列舉列表裡面不存在null值會插入失敗,這點和其它的分割槽不一樣,range分割槽會將其作為最小分割槽值儲存,hash\key分為會將其轉換成0儲存,主要list分割槽只支援整形,非整形字段需要通過函式轉換成整形.
hash 分割槽
我們在實際工作中經常遇到像會員表的這種表。並沒有明顯可以分割槽的特徵字段。但表資料有非常龐大。為了把這類的資料進行分割槽打散mysql 提供了hash分割槽。基於給定的分割槽個數,將資料分配到不同的分割槽,hash分割槽只能針對整數進行hash,對於非整形的字段只能通過表示式將其轉換成整數。表示式可以是mysql中任意有效的函式或者表示式,對於非整形的hash往表插入資料的過程中會多一步表示式的計算操作,所以不建議使用複雜的表示式這樣會影響效能。
hash分割槽表的基本語句如下:
注意:hash分割槽可以不用指定partitions子句,如上文中的partitions 4,則預設分割槽數為1。
不允許只寫partitions,而不指定分割槽數。
同range分割槽和list分割槽一樣,partition by hash (expr)子句中的expr返回的必須是整數值。
hash分割槽的底層實現其實是基於mod函式。譬如,對於下表
如果你要插入乙個col3為「2017-09-15」的記錄,則分割槽的選擇是根據以下值決定的:
mod(year(『2017-09-01』),4)
= mod(2017,4)
= 1linear hash分割槽
linear hash分割槽是hash分割槽的一種特殊型別,與hash分割槽是基於mod函式不同的是,它基於的是另外一種演算法。
格式如下:
說明:它的優點是在資料量大的場景,譬如tb級,增加、刪除、合併和拆分分割槽會更快,缺點是,相對於hash分割槽,它資料分布不均勻的概率更大。
key分割槽其實跟hash分割槽差不多,不同點如下:
key分割槽允許多列,而hash分割槽只允許一列。
如果在有主鍵或者唯一鍵的情況下,key中分割槽列可不指定,預設為主鍵或者唯一鍵,如果沒有,則必須顯性指定列。
key分割槽物件必須為列,而不能是基於列的表示式。
key分割槽和hash分割槽的演算法不一樣,partition by hash (expr),mod取值的物件是expr返回的值,而partition by key (column_list),基於的是列的md5值。
格式如下:
mysql分割槽中如果存在主鍵或唯一鍵,則分割槽列必須包含在其中。
對於原生的range分割槽,list分割槽,hash分割槽,分割槽物件返回的只能是整數值。
分割槽字段不能為null,要不然怎麼確定分割槽範圍呢,所以盡量not null
MySQL分割槽表
分割槽表是一種粗粒度,簡易的索引策略,適用於大資料的過濾場景.最適合的場景是,沒有合適的索引時,對其中幾個分割槽表進行全表掃瞄.或者只有乙個分割槽表和索引是熱點,而且這個分割槽和索引能夠全部儲存在記憶體中.限制單錶分割槽數不要超過150個,並且注意某些導致無法做分割槽過濾的細節,分割槽表對於單條記錄...
mysql分割槽表
對使用者來說,分割槽表是乙個獨立的邏輯表,但是底層由多個物理子表組成。實現分割槽的 實際上是對一組底層表的控制代碼物件的封裝。mysql在建立表時使用partition by子句定義每個分割槽存放的資料。在執行查詢的時候,優化器會根據分割槽定義過濾那些沒有我們需要資料的分割槽,這樣查詢就無須掃瞄所有...
mysql分割槽表 MySQL分割槽表的正確使用方法
mysql分割槽表概述 我們經常遇到一張表裡面儲存了上億甚至過十億的記錄,這些表裡面儲存了大量的歷史記錄。對於這些歷史資料的清理是乙個非常頭疼事情,由於所有的資料都乙個普通的表裡。所以只能是啟用乙個或多個帶where條件的delete語句去刪除 一般where條件是時間 這對資料庫的造成了很大壓力。...