MySql第二章,數據庫分區

MySql第二章,數據庫分區

一、分區概述

數據分區是一種物理數據庫的設計技術,它的目的是爲了在特定的SQL操作中減少數據讀寫的總量以縮減響應時間。

分區並不是生成新的數據表,而是將表的數據均衡分攤到不同的硬盤,實際上還是一張表。另外,分區可以做到將表的數據均衡到不同的地方,提高數據檢索的效率,降低數據庫的頻繁IO壓力值 。

1、水平分區

這種形式分區是對錶的行進行分區,通過這樣的方式不同分組裏面的物理列分割的數據集得以組合,從而進行個體分割(單分區)或集體分割(1個或多個分區)。所有在表中定義的列在每個數據集中都能找到,所以表的特性依然得以保持。

舉個簡單例子:一個包含十年發票記錄的表可以被分區爲十個不同的分區,每個分區包含的是其中一年的記錄。

:這裏具體使用的分區方式我們後面再說,可以先說一點,一定要通過某個屬性列來分割,譬如這裏使用的列就是年份。

2、垂直分區

這種分區方式一般來說是通過對錶的垂直劃分來減少目標表的寬度,使某些特定的列被劃分到特定的分區,每個分區都包含了其中的列所對應的行。

舉個簡單例子:一個包含了大text和BLOB列的表,這些text和BLOB列又不經常被訪問,這時候就要把這些不經常使用的text和BLOB了劃分到另一個分區,在保證它們數據相關性的同時還能提高訪問速度。

在數據庫供應商開始在他們的數據庫引擎中建立分區(主要是水平分區)時,DBA和建模者必須設計好表的物理分區結構,不要保存冗餘的數據(不同表中同時都包含父表中的數據)或相互聯結成一個邏輯父對象(通常是視圖)。這種做法會使水平分區的大部分功能失效,有時候也會對垂直分區產生影響。

3、分區的優點

1、數據分割,放置於不同的物理文件中

2、存儲更多的數據,突破單個文件存儲的最大限度

3、精準定位分區查詢數據,不需要全表掃描查詢,大大提高數據檢索效率

4、數據管理比較方便,比如要清理或廢棄某年的數據,就可以直接刪除該日期的分區數據即可

5、可跨磁盤分區查詢,提高磁盤的I/O性能

6、SUM()和COUNT()等聚合函數查詢,可以更容易的進行並行處理

7、可備份和恢復獨立的分區

二、分區類型

1>、range  => 連續區間的列值:如0~99、100~199

2>、list   => 類似range,離散集合:如[1,3,5,7,9]、[2,4,6,8,10]

3>、hash   => 根據哈希函數分配,用戶可自定義表達式。確保數據在預先確定數目的分區中平均分佈

4>、key    => 類似hash,但是由MySQL自身提供的函數

注:

1、若表存在 primary key 【PK】或 unique key【UK】,分區函數列只能從PK或UK中取子集。

   若無PK和UK,則可隨意指定列作爲分區列。


2、MySQL-5.5version以前分區鍵必須爲整型如int,5.5以後支持非整型


3、InnoDB支持分區。

   MyISAM mysql8以前支持,之後不再支持了。

查看數據庫是否支持分區:

5.6版本以後使用如下:

show plugins;
結果:
partition ACTIVE  即支持分區

三、分區創建

1、range分區(常用)

CREATE TABLE `shop_user_info` (
  `user_info_id` bigint(30) NOT NULL COMMENT '主鍵ID',
  `user_code` varchar(64) NOT NULL COMMENT '用戶編碼',
  `user_name` varchar(100) NOT NULL COMMENT '用戶名稱',
  `gender` int(2) DEFAULT NULL COMMENT '性別 1:女 2:男 3:保密',
  `age` int(3) DEFAULT NULL COMMENT '年齡',
  `create_time` timestamp NULL DEFAULT NULL COMMENT '信息創建時間',
  `update_time` timestamp NULL DEFAULT NULL COMMENT '信息修改時間'
)ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='電商用戶信息表'

PARTITION BY RANGE (user_info_id)(
  PARTITION P0 VALUES LESS THAN (5),
  PARTITION P1 VALUES LESS THAN (10),
  PARTITION P2 VALUES LESS THAN (15),
  PARTITION P3 VALUES LESS THAN MAXVALUE
);

分區後默認的文件存放路徑:

在這裏插入圖片描述

【自定義存放路徑後面有寫】

1.1、查看分區是否成功建立

show create table shop_user_info;

1.2、查詢分區中的數據

select * from shop_user_info partition (p0);

1.3、查看數據所在分區

explain partitions select * from shop_user_info where user_info_id=1;

2、list分區(常用)

CREATE TABLE `shop_user_info2` (
  `user_info_id` bigint(30) NOT NULL COMMENT '主鍵ID',
  `user_code` varchar(64) NOT NULL COMMENT '用戶編碼',
  `user_name` varchar(100) NOT NULL COMMENT '用戶名稱',
  `gender` int(2) DEFAULT NULL COMMENT '性別 1:女 2:男 3:保密',
  `age` int(3) DEFAULT NULL COMMENT '年齡',
  `create_time` timestamp NULL DEFAULT NULL COMMENT '信息創建時間',
  `update_time` timestamp NULL DEFAULT NULL COMMENT '信息修改時間'
)ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='電商用戶信息表'

PARTITION BY list (user_info_id)(
  PARTITION P0 VALUES in (1,3,5,7,9),
  PARTITION P1 VALUES in (2,4,6,8,10)
);

注:

因爲在上面 定義分區的時候,user_info_id設置了 1 3 5 7 9 2 4 6 8 10

所以user_info_id的值也只能在1 3 5 7 9 2 4 6 8 10中

##插入語句會操作失敗
insert into shop_user_info2 value (66,'u66','name66',2,20,'2020-03-09 12:22:33','2020-03-09 12:25:55');

3、hash分區

【只支持整數分區】

【由於range和list分區無法保證數據的平均分佈,所以有了hash分區和key分區】

CREATE TABLE `shop_user_info3` (
  `user_info_id` bigint(30) NOT NULL COMMENT '主鍵ID',
  `user_code` varchar(64) NOT NULL COMMENT '用戶編碼',
  `user_name` varchar(100) NOT NULL COMMENT '用戶名稱',
  `gender` int(2) DEFAULT NULL COMMENT '性別 1:女 2:男 3:保密',
  `age` int(3) DEFAULT NULL COMMENT '年齡',
  `create_time` timestamp NULL DEFAULT NULL COMMENT '信息創建時間',
  `update_time` timestamp NULL DEFAULT NULL COMMENT '信息修改時間'
)ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='電商用戶信息表'

PARTITION BY hash (user_info_id)
PARTITIONS 3;

##這裏數據會按  user_info_id % 3進行分配

注:

hash分區,數據的插入、更新、刪除都會根據hash表達式計算一次選擇分區,因此會有性能問題。

所以自定義表達式的時候儘量不要太複雜,最好爲單列

4、linear hash 線性分區

partition by linear hash (id)
partition 3;

注:

線性分區在插入、更新、刪除時性能會更好更快,但是數據會分佈不均,所以一般不使用

5、key分區

key分區類似hash分區,但不允許自定義表達式,默認使用mysql自身提供的函數

可以分區除了支持整數分區外,還支持除了blob、text之外的分區

partition by linear key (id)
partition 3;

四、MySQL指定分區路徑

MySQL可以針對分區表的每個分區指定各自的存儲路徑。

1、對於innodb存儲引擎的表只能指定數據路徑,因爲數據和索引是存儲在一個文件當中。

2、對於MYISAM存儲引擎可以分別指定數據文件和索引文件。

3、一般也只有RANGE、LIST分區、sub子分區纔有可能需要單獨指定各個分區的路徑,HASH和KEY分區的所有分區的路徑都是一樣。RANGE分區指定路徑和LIST分區是一樣的。 

1、MyISAM存儲引擎

CREATE TABLE th (id INT, createDate DATE)
engine='MyISAM'

PARTITION BY LIST(YEAR(createDate))
(
  PARTITION p0 VALUES IN (1995, 1999, 2003)
    DATA DIRECTORY = '/data/data'
    INDEX DIRECTORY = '/data/idx',
  PARTITION p1 VALUES IN (1996, 2000, 2004)
    DATA DIRECTORY = '/data/data'
    INDEX DIRECTORY = '/data/idx',
  PARTITION p2 VALUES IN (1997, 2001, 2005)
    DATA DIRECTORY = '/data/data'
    INDEX DIRECTORY = '/data/idx',
  PARTITION p3 VALUES IN (1998, 2002, 2006)
    DATA DIRECTORY = '/data/data'
    INDEX DIRECTORY = '/data/idx'
);

2、INNODB存儲引擎

CREATE TABLE thex (id INT, createDate DATE)
engine='InnoDB'
PARTITION BY LIST(YEAR(createDate))
(
  PARTITION p0 VALUES IN (1995, 1999, 2003)
    DATA DIRECTORY = '/data/data',
    
  PARTITION p1 VALUES IN (1996, 2000, 2004)
    DATA DIRECTORY = '/data/data',
   
  PARTITION p2 VALUES IN (1997, 2001, 2005)
    DATA DIRECTORY = '/data/data',
    
  PARTITION p3 VALUES IN (1998, 2002, 2006)
    DATA DIRECTORY = '/data/data'
  
);

五、子分區

子分區:分區表中可以對每個分區再次切割,適合保存大量的數據。

range和hash組合:

CREATE TABLE `shop_user_info4` (
  `user_info_id` bigint(30) NOT NULL COMMENT '主鍵ID',
  `user_code` varchar(64) NOT NULL COMMENT '用戶編碼',
  `user_name` varchar(100) NOT NULL COMMENT '用戶名稱',
  `gender` int(2) DEFAULT NULL COMMENT '性別 1:女 2:男 3:保密',
  `age` int(3) DEFAULT NULL COMMENT '年齡',
  `create_time` datetime NULL DEFAULT NULL COMMENT '信息創建時間',
  `update_time` datetime NULL DEFAULT NULL COMMENT '信息修改時間'
)ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='電商用戶信息表'

partition by range (YEAR(create_time))
subpartition by hash (TO_DAYS(create_time))
subpartitions 2
(
   partition p0 values less than (2015),
   partition p1 values less than (2020),
   partition p2 values less than MAXVALUE
);

①、如果創建子分區,每一個分區必須有 相同數量 的子分區

②、對於已經通過range和list分區了的表,可再進行子分區。

​ 子分區既可以用hash分區,也可用key分區====> 我們稱之爲 複合分區

③、若指定分區名稱,每一個分區和子分區的名稱必須全局唯一

partition by range (YEAR(create_time))
subpartition by hash (TO_DAYS(create_time))
(
   partition p0 values less than (2015)(
     subpartition s0,
     subpartition s1
   ),
   partition p1 values less than (2020)(
     subpartition s2,
     subpartition s3
   ),
   partition p2 values less than MAXVALUE(
     subpartition s4,
     subpartition s5
   )
);

六、分區管理

分區管理即:對分區進行 添加、刪除、重新定義、合併、拆分等操作

1、range和list分區

1.1、刪除分區–數據丟失

alter table users drop partition p0;

##數據會直接丟失
##list分區drop刪除後,對應的刪除值就不可再添加了

1.2、添加分區

alter table users add partition (partition p4 values less than (100));

##range添加分區只能往高處添加,不能刪除了p0再添加p0.
##有MAXVALUE的,先把MAXVALUE所在的分區刪除後,再添加新的.

##list分區,不能添加已存在的值

1.3、重新定義–數據不丟失

拆分p1分區

alter table users reorganize partition p1 into(
	partition s0 values less than (5),
    partition s1 values less than (10)
);

合併s0、s1分區

alter table users reorganize partition s0,s1 into(
    partition p0 less than (10)
);

1.4、刪除所有分區–保留數據

alter table users remove partitioning;

2、hash和key分區

【hash和key分區只能減少或增加分區數量,數據不會丟失】

減少分區數:

alter table users coalesce partition 1;  ##減少1個分區

添加分區數:

alter table users add partition partitions 2;  ##添加2個分區

3、重建分區

alter table users rebuild partition p2,p3;

##先刪除分區中的記錄,然後再重新插入。可用於整理分區碎片

4、分析分區

alter table users analyze partition p2,p3;

##讀取並保存分區鍵分佈

5、檢查分區

alter table users check partition p2,p3;

##檢查分區中的數據or索引是否被破壞

6、修補分區

alter table users repair partition p2,p3;

##修補被破壞的分區

7、優化分區 = 分析+檢查+修補分區

alter table users optimize partition p2,p3;

##若刪除大量行,優化後可收回沒有使用的空間,並整理分區的碎片

七、注意事項

1、MySql分區處理NULL的方式

若分區鍵有的值爲NULL,MySQL會默認將NULL視爲0做處理,但這樣數據就會分佈不均勻,
所以我們在設計表和分區時儘量將分區列聲明爲 NOT NULL

2、注意

1、最大分區數不超過1024,一般建議不超過150個

2、若有PK或UK,必須包含在分區鍵內

3、不支持外鍵

4、不支持全文索引,對分區表的分區鍵創建索引,那麼這個索引也將被分區

5、一般會按照 整數 or 日期 分區

6、只有range和list可進行子分區,hash和key不可以

7、臨時表不能被分區

8、分區表對單條記錄的查詢無優勢

9、注意分區成本(分區後數據的增刪改性能會有影響)

10、分區字段儘量不要使用NULL
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章