目錄 零、主要參考網頁 一、概述 二、分區類型以及創建方式 三、分區表的管理 三、分區表的管理 四、獲取分區表信息 四、獲取分區表信息 五、分區的局限與分表 零、主要參考網頁 http://www.2cto.com/database/201503/380348.html【mysql分表和表分區詳解】 ...
目錄 零、主要參考網頁 一、概述 二、分區類型以及創建方式 三、分區表的管理 四、獲取分區表信息 五、分區的局限與分表 零、主要參考網頁 http://www.2cto.com/database/201503/380348.html【mysql分表和表分區詳解】 http://www.cnblogs.com/zemliu/archive/2013/07/21/3203511.html【MySQL分區表】 http://x125858805.iteye.com/blog/2068120【MYSQL--表分區、查看分區(轉)】 http://blog.csdn.net/tjcyjd/article/details/11194489【深入解析MySQL分區(Partition)功能】 一、概述 1、功能:主要目的是為了在特定的SQL操作中減少數據讀寫的總量以縮減sql語句的響應時間,同時對於應用來說分區完全是透明的。 2、水平分區和垂直分區:水平分區是對行進行分區;垂直分區是對列進行分區,減小每個分區中數據的寬度,使用很少。 3、分區類型:RANGE分區、LIST分區、HASH分區、KEY分區以及複合分區。 4、MySQL分區實現:邏輯上是一個獨立的表,但是底層由多個物理子表實現。 5、一個表最多只能有1024個分區。 6、查詢時只能根據列過濾分區,使用列的表達式不行;即便這個表達式就是分區函數也不行。 二、分區類型以及創建方式 0、共性 (1)如果表含有主鍵,則做分區的列必須包含在主鍵中;如果表不含有主鍵,則無所謂。 (2)分區鍵必須是INT類型,或者通過表達式返回INT類型,可以為NULL。唯一的例外是當分區類型為KEY分區的時候,可以使用其他類型的列作為分區鍵( BLOB or TEXT 列除外)。【註意,to_days函數可以將一個日期轉化為INTEGER,作為分區表達式,而且有函數將字元串轉化為日期;但是如果將字元串轉為日期,在使用to_days,則不能作為分區表達式;這個時候要考慮換列做分區,或者使用key分區】 (3)如果分區鍵所在列沒有not null約束:range分區表的null行將被保存在範圍最小的分區;list分區表的null行將被保存到list為0的分區;在按HASH和KEY分區的情況下,任何產生NULL值的表達式mysql都視同它的返回值為0。為了避免這種情況的產生,建議分區鍵設置成NOT NULL。 (4)對分區表的分區鍵創建索引,那麼這個索引也將被分區,分區表沒有全局索引一說。註意,oracle是在分區與索引時,是可以選擇全局索引還是分區索引的。 1、RANGE 分區:基於屬於一個給定連續區間的列值,把多行分配給分區。 (1)示例1:
create table emp
(
empno varchar(20) not null,
empname varchar(20),
deptno int,
birthdate date,
salary int
)
partition by range(salary)(
partition p1 values less than (1000),
partition p2 values less than (2000),
partition p3 values less than maxvalue
);
(2)示例2:(在本例中,沒有直接使用列而是使用了表達式year(birthdate);使用表達式必須有返回值)
create table emp
(
empno varchar(20) not null ,
empname varchar(20),
deptno int,
birthdate date not null,
salary int
)
partition by range(year(birthdate))(
partition p1 values less than (1980),
partition p2 values less than (1990),
partition p3 values less than maxvalue
);
(3)maxvalue只能出現在最後一個分區;如果沒有使用形如maxvalue,可能導致插入的數據不屬於任何分區,從而導致數據無法插入(如:Table has no partition for value ……)
2、LIST 分區:類似於按RANGE分區,區別在於LIST分區是基於列值匹配一個離散值集合中的某個值來進行選擇;如果插入的數據不能匹配任何分區,則插入失敗。
create table emp
(
empno varchar(20) not null ,
empname varchar(20),
deptno int,
birthdate date not null,
salary int
)
partition by list(deptno)(
partition p1 values in (10),
partition p2 values in (20),
partition p3 values in (30)
);
3、HASH分區:基於用戶定義的表達式的返回值進行選擇,該表達式使用一個或多個列值進行計算;這個表達式可以是任何產生非負整數值的表達式。
(1)目標:確保數據在預先確定數目的分區中平均分佈。不需要指定一行數據在哪個分區中(RANGE和LIST需要),MySQL自動完成;只需要指定表達式以及分區數量。hash分區和key分區,經過測試,有個奇怪的特點:當分區數量為奇數時,分佈較為平均;當分區質量為偶數時,則會出現一半分區沒有元素的現象。【網上說是質數和合數,但我測試發現,2不平均,而9/15等則較為平均,故猜測是奇數和偶數】
(2)示例
create table emp
(
empno varchar(20) not null ,
empname varchar(20),
deptno int,
birthdate date not null,
salary int
)
partition by hash(year(birthdate))
partitions 4;//4表示分成4份
4、KEY分區:類似於按HASH分區,區別在於KEY分區不能指定表達式,只能指定一列或多列;同樣需要指定分區數量。
create table emp
(
empno varchar(20) not null ,
empname varchar(20),
deptno int,
birthdate date not null,
salary int
)
partition by key(birthdate)
partitions 4;
5、複合分區:包括range-hash、range-key、list-hash、list-key
示例:range-hash
create table emp(
empno varchar(20) not null ,
empname varchar(20),
deptno int,
birthdate date not null,
salary int
) partition by range(salary)
subpartition by hash(year(birthdate))
subpartitions 3(
partition p1 values less than (2000),
partition p2 values less than maxvalue
);
三、分區表的管理
1、刪除分區:同時刪除分區內的數據;只可以用於range和list。
alter table emp drop partition p1;
alter table emp drop partition p2,p3;
2、增加分區:如果range分區中使用了maxvalue,則無法在後面增加分區,因為形如maxvalue必須是最後一個分區;可以先刪除再添加,但是如果有數據在最後一個分區,會導致數據丟失。只可以用於range和list;不會丟失數據。
alter table emp add partition (partition p3 values less than (4000));
alter table emp add partition (partition p3 values in (40));
3、分解分區:只可以用於range和list;不會丟失數據。
alter table emp reorganize partition p1 into(
partition p1 values less than (100),
partition p3 values less than (1000)
);
4、合併分區:只可以用於range和list;不會丟失數據。
alter table emp reorganize partition p1,p3 into (partition p1 values less than (1000));
5、重新定義分區表:可以用於四種分區表;不會丟失數據。
alter table emp partition by hash(salary)partitions 7;---hash
alter table emp partition by range(salary)(
partition p1 values less than (2000),
partition p2 values less than (4000)
);---range
6、刪除所有分區:可以用於四種分區表;不會丟失數據。
alter table emp remove partitioning;
7、重建分區:可以用於四種分區表;不會丟失數據。當用於hash和key分區時,可以先查詢分區名稱再重建(因為不是我們指定的),不過一般是p0,p1,p2...的形式。用於整理分區碎片,效果與先刪除保存在分區中的記錄,再將它們插入相同。
ALTER TABLE emp rebuild partition p1,p2;
8、優化分區:可以用於四種分區表;不會丟失數據。如果從分區中刪除了大量的行,或者對一個帶有可變長度的行作了許多修改,可以用來收回沒有使用的空間,並整理分區數據文件的碎片。【我的MySQL不支持:Table does not support optimize on partitions. All partitions will be rebuilt and analyzed.】
ALTER TABLE emp optimize partition p1,p2;
9、保存分區:可以用於四種分區表;不會丟失數據。讀取並保存分區的鍵分佈;保存到哪裡呢???
ALTER TABLE emp3 analyze partition p1,p2;
10、檢查分區:可以用於四種分區表;不會丟失數據。判斷數據或索引是否已經被破壞,如果破壞使用修複分區進行修複。
ALTER TABLE emp CHECK partition p1,p2;
11、修複分區:可以用於四種分區表;不會丟失數據。
ALTER TABLE emp repair partition p1,p2;
四、獲取分區表信息
1、show create table 表名
2、show table status:可以查看是不是分區表;不加表明,顯示資料庫內所有表的狀態
3、查看information_schema.partitions表
select
partition_name part,
partition_expression expr,
partition_description descr,
table_rows
from information_schema.partitions where
table_schema = schema()
and table_name='表名';
應該註意到,查詢到分區表的數據統計未必準確(有時連續查詢沒有變動的表結果都可能不同);準確與否與搜索引擎有關,比如Innodb的不准確。
4、explain partitions select語句:通過此語句來顯示掃描哪些分區,及他們是如何使用的;因此可以查看分區是否對查詢過程有優化效果。
五、分區的局限與分表
1、分區與索引
(1)作用類似
在執行查詢時,優化器會根據分區定義過濾那些沒有我們需要數據的分區,否則分區對查詢的優化就沒有什麼效果了。因此,查詢條件應該與分區列匹配。
理解分區:可以將分區當做索引的最初形態,以代價非常小的方式定位到需要的數據在哪一片“區域”。這樣也就可以理解,無論是分區還是索引,都要求查詢條件與之匹配,查詢才有優化效果。
(2)有索引為什麼還需要分區
當表數據量超大的時候,索引是有問題的。一方面,除非索引覆蓋了查詢,否則資料庫根據索引掃描的結果去資料庫中查找,如果數據量巨大,將產生大量隨機I/O,資料庫響應時間會超長。另一方面,索引也會很大。
(3)實現細節
分區表的底層由多個物理子表實現,因此分區表的索引只是在各個底層表上各自加上一個完全相同的索引;沒有全局索引一說。
(4)問題:分區列和索引列不匹配
如果分區列和索引列不匹配,那麼根據索引的條件查詢,不能夠過濾分區;就會導致需要把每個分區的索引都讀到記憶體,效率極低,儘量避免。
但是實際上,有些時候很難避免索引列與分區列不一致:比如某些表有不止一個索引。
此時,可以考慮分表。
2、分表
(1)顧名思義,當數據量過大時,將不同的數據放到不同的表中。選取用於分表的欄位和規則應該註意,這個欄位應比較常用(因為每次增刪改查都需要根據這個欄位確定使用哪個表),也儘量不要使用完全隨機數(不好根據規則確定表)。
(2)動態sql:在應用層進行判斷,選擇增刪改查所使用的表;代碼略繁瑣,且隨著新加表,需要發版。使用Hibernate的sql功能,直接用sql語句和表名進行操作;PO不與表綁定(嚴格來說不是PO)。
(3)NamingStrategy:傳入一個表名,命名策略可以輸出一個表名;但是由於輸入只有表名,因此不可能根據數據的不同動態選擇表名。命名策略一般做的事情是進行一些大小寫轉換,加前尾碼,或者在表名中加入當前時間的信息(這個在每天的表都需要單獨存,且以後不需要訪問今天的表或訪問時會帶上時間時比較有用)。
(4)hibernate shards:google提交給hibernate社區的源碼。每個分片都要有自己的配置文件,強項是分庫。
(5)Inceptor:在hibernate生成最終的sql語句之前,對sql進行一些改變。這個功能挺強大,而且將對分表的處理放在了最底層,邏輯上比較通順。但是也有一些弊端:代碼繁瑣;每個sql都會被攔截,可能會出問題;對寫sql的格式會有一定要求(這樣攔截時才容易判斷出哪些是真正需要攔截的);不直觀。