欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

MySQL分區(qū)表的具體使用

 更新時間:2025年06月11日 11:36:17   作者:V1ncent-CC  
MySQL分區(qū)表通過規(guī)則將數(shù)據(jù)分至不同物理存儲,提升管理與查詢效率,本文主要介紹了MySQL分區(qū)表的具體使用,具有一定的參考價值,感興趣的可以了解一下

通常情況下,同一張表的數(shù)據(jù)在物理層面都是存放在一起的。隨著業(yè)務增長,當同一張表的數(shù)據(jù)量過大時,會帶來管理上的不便。而分區(qū)特性可以將一張表從物理層面根據(jù)一定的規(guī)則將數(shù)據(jù)劃分為多個分區(qū),多個分區(qū)可以單獨管理,甚至存放在不同的磁盤/文件系統(tǒng)上,提升效率。

分區(qū)表的優(yōu)點:

  • 數(shù)據(jù)可以跨磁盤/文件系統(tǒng)存儲,適合存儲大量數(shù)據(jù)。
  • 數(shù)據(jù)的管理非常方便,以分區(qū)為單位操作數(shù)據(jù),不會影響其他分區(qū)的正常運行。
  • 數(shù)據(jù)查詢上在某些條件可以利用分區(qū)裁剪(partition pruning)特性,將搜索范圍快速定位到特性分區(qū),提升查詢性能。

對于應用來說,表依然是一個邏輯整體,但數(shù)據(jù)庫可以針對不同的數(shù)據(jù)分區(qū)獨立執(zhí)行管理操作,不影響其他分區(qū)的運行。而數(shù)據(jù)劃分的規(guī)則即稱為分區(qū)函數(shù),數(shù)據(jù)寫入表時,會根據(jù)運算結(jié)果決定寫入哪個分區(qū)。

MySQL的分區(qū)插件與存儲引擎運行在不同的層,因此大部分存儲引擎都可以利用MySQL的分區(qū)特性,只有少數(shù)存儲引擎(merge,CSV,federated)不支持分區(qū)特性。若某張表使用的分區(qū)特性,則所有的分區(qū)都需要使用相同的存儲引擎,且分區(qū)特性會同時應用到數(shù)據(jù)和索引上。

一、分區(qū)的類型

1. Range partition(范圍分區(qū))

Range partition是按照分區(qū)表達式的運算結(jié)果,判斷結(jié)果落在某個范圍內(nèi),從而將數(shù)據(jù)存儲在對應的分區(qū)。各個分區(qū)定義之間需要連續(xù)且不能重疊,范圍分區(qū)通過partition by range子句定義,而分區(qū)的范圍通過values less than子句劃分。

例:定義一個員工表,根據(jù)員工ID分區(qū),1~10號員工一個分區(qū),11~20號員工一個分區(qū),依次類推,共建立4個分區(qū):

create table employees (
    id int not null primary key,
    first_name varchar(30),
    last_name varchar(30))
    partition by range(id)(
    partition p0 values less than (11),
    partition p1 values less than (21),
    partition p2 values less than (31),
    partition p3 values less than (41)
    );

現(xiàn)在隨便插入幾條數(shù)據(jù):

insert into employees values(1,'Vincent','Chen');
insert into employees values(6,'Victor','Chen');
insert into employees values(11,'Grace','Li');
insert into employees values(16,'San','Zhang');
commit;

分區(qū)查詢:

如果在查詢時候明確的知道數(shù)據(jù)所在的分區(qū),我們可以直接指定分區(qū):

select * from employees partition(p0);  -- 查詢p0分區(qū)
select * from employees partition(p0,p1);  -- 查詢p0和p1分區(qū)

 分區(qū)刪除:

如果某分區(qū)數(shù)據(jù)不再需要的時候,我們可以用alter table ... drop partition來刪除指定分區(qū),例如刪除分區(qū)p1,采用drop partition的方式可以快速清除歷史數(shù)據(jù):

alter table employees drop partition p1;

 分區(qū)p1被刪除后,所有p1分區(qū)的數(shù)據(jù)都已丟失,此時原p1分區(qū)的范圍將由p2覆蓋。

分區(qū)新增:

對于range分區(qū)來說,分區(qū)新增只能在最大范圍之上增加分區(qū),因此p1分區(qū)被刪除后就無法通過新增分區(qū)的方式加回了,下例試圖對ID10~20的員工新增一個分區(qū),系統(tǒng)會返還錯誤。

alter table employees add partition (partition n1 values less than(21));

而在最大的分區(qū)范圍之上是可以的:

alter table employees add partition (partition p4 values less than(51));

 分區(qū)重組織:

如果一定要在分區(qū)之間插入新的分區(qū),則可以采用重組織的方式,將已有分區(qū)的數(shù)據(jù)重新劃分,達到創(chuàng)建新分區(qū)的效果:

 例如我要將p2劃分為2個分區(qū),分別是11~20,21~30:

alter table employees reorganize partition p2 into (
partition p1 values less than(21),
partition p2 values less than(31));

 

 此時原p2分區(qū)被拆分為了p1,p2,數(shù)據(jù)也在2個分區(qū)間重新分布,保證不會丟失。效果就像我們在中間插入了一個分區(qū)一樣。

目前定義的分區(qū)都是有上限的,如果有大于分區(qū)上限的值想插入表中,系統(tǒng)會返還錯誤,為了兼容這種情況,我們可以新增一個分區(qū),上限為maxvalue。所有大于當前上限的值都會放入這個分區(qū):

alter table employees add partition(partition pmax values less than(maxvalue));

范圍分區(qū)的條件除了直接用值,還可以用函數(shù)來定義。一個常用的場景就是按時間分區(qū),例如:在create table中使用partition by range(year(hire_date)),可以按照年份來進行分區(qū)。這種分區(qū)方式在需要定期清理過期數(shù)據(jù)的場景會非常方便。

Range columns分區(qū):

Range分區(qū)還有一個變種,叫做range columns分區(qū)。此分區(qū)方式允許使用多個column來作為分區(qū)范圍條件。但是此分區(qū)方式不能接受函數(shù),只能直接用列的名稱。但是對分區(qū)列的類型不再限制為整數(shù),可以使用string,date等類型。

使用range columns對多個列進行分區(qū):

CREATE TABLE rc2 (
    a INT,
    b INT
)
PARTITION BY RANGE COLUMNS(a,b) (
    PARTITION p0 VALUES LESS THAN (0,10),
    PARTITION p1 VALUES LESS THAN (10,20),
    PARTITION p2 VALUES LESS THAN (10,30),
    PARTITION p3 VALUES LESS THAN (MAXVALUE,MAXVALUE) );

使用range columns直接對date類型進行分區(qū):

CREATE TABLE members (
    firstname VARCHAR(25) NOT NULL,
    lastname VARCHAR(25) NOT NULL,
    username VARCHAR(16) NOT NULL,
    joined DATE NOT NULL
)
PARTITION BY RANGE COLUMNS(joined) (
    PARTITION p0 VALUES LESS THAN ('1960-01-01'),
    PARTITION p1 VALUES LESS THAN ('1970-01-01'),
    PARTITION p2 VALUES LESS THAN ('1980-01-01'),
    PARTITION p3 VALUES LESS THAN ('1990-01-01'),
    PARTITION p4 VALUES LESS THAN MAXVALUE);

Range partition和null:

對range分區(qū)來說,如果插入數(shù)據(jù)分區(qū)鍵為null,是可以成功的,數(shù)據(jù)會被放到第一個分區(qū)中。

2. List partition(列表分區(qū))

列表分區(qū)和范圍分區(qū)類似,主要區(qū)別是list partition的分區(qū)范圍是預先定義好的一系列值,而不是連續(xù)的范圍。列表分區(qū)采用partition by list和values in子句定義。

示例,創(chuàng)建一張員工表按照ID進行列表分區(qū):

CREATE TABLE employees (
    id INT NOT NULL,
    fname VARCHAR(30),
    lname VARCHAR(30)
)
PARTITION BY LIST(id) (
    PARTITION p0 VALUES IN (1,3,5,7,9),
    PARTITION p1 VALUES IN (2,4,6,8,10)
);

和range分區(qū)一樣,可以使用alter table ... add/drop partition新增/刪除分區(qū):

ALTER TABLE employees ADD PARTITION(PARTITION p2 VALUES IN (11,12,13,14,15));
ALTER TABLE employees DROP PARTITION p0;

List partition和非事務引擎:

如果插入的值在list分區(qū)范圍中不存在的話,語句會返還錯誤。如果表使用的是事務型引擎,如innodb。則這個事務會完全回滾。如果使用的是非事務引擎,若MyISAM,雖然也會報錯,但是已插入的行無法回滾。

下面新建兩張表,一張使用innodb,一張使用myisam:

CREATE TABLE employees_innodb (
    id INT NOT NULL,
    fname VARCHAR(30),
    lname VARCHAR(30)
) ENGINE=InnoDB   -- 事務型引擎
PARTITION BY LIST(id) (
    PARTITION p0 VALUES IN (1,3,5,7,9),
    PARTITION p1 VALUES IN (2,4,6,8,10));

CREATE TABLE employees_myisam (
    id INT NOT NULL,
    fname VARCHAR(30),
    lname VARCHAR(30)
) ENGINE=MyISAM   -- 非事務型引擎
PARTITION BY LIST(id) (
    PARTITION p0 VALUES IN (1,3,5,7,9),
    PARTITION p1 VALUES IN (2,4,6,8,10));
insert into employees_innodb values(1,'Vincent','Chen'),(11,'Grace','Li'),(2,'Victor','Chen');
insert into employees_myisam values(1,'Vincent','Chen'),(11,'Grace','Li'),(2,'Victor','Chen');

select * from employees_innodb;
select * from employees_myisam;

我們在中間放了一個不存在對應分區(qū)的記錄來觸發(fā)錯誤, 可以看到innodb引擎數(shù)據(jù)沒有數(shù)據(jù)插入(回滾)。但MyISAM引擎報錯前的數(shù)據(jù)已經(jīng)保留了下來,但是報錯之后的記錄未執(zhí)行插入。

如果要忽略此錯誤,可以在insert語句中使用ignore關鍵字來忽略此錯誤,只插入符合分區(qū)條件的值:

insert ignore into employees_innodb values(1,'Vincent','Chen'),(11,'Grace','Li'),(2,'Victor','Chen');
insert ignore into employees_myisam values(1,'Vincent','Chen'),(11,'Grace','Li'),(2,'Victor','Chen');

 可以看到符合條件的記錄被插入,不符合條件的自動被過濾,不返回錯誤。

List columns分區(qū):

和range分區(qū)類似,list partition也有一個變種的list columns 分區(qū),此分區(qū)類型可以使用多個列同時作為分區(qū)條件,且不再限制整數(shù)。并且可以使用string,date等數(shù)據(jù)類型作為分區(qū)條件。

list partition和null:

對于列表分區(qū)來說,必須有1個分區(qū)顯示的指定可以包含null,否則插入會失敗。

3. Hash partition(哈希分區(qū))

Hash partition主要的應用場景是將數(shù)據(jù)平均的分布在指定數(shù)量的hash分區(qū)中。在range和list分區(qū)類型中,根據(jù)分區(qū)條件的計算結(jié)果,數(shù)據(jù)可以確定存儲在哪個分區(qū),而在hash分區(qū)中,數(shù)據(jù)存儲在某個分區(qū)是由數(shù)據(jù)庫自己決定的,你只需要指定分區(qū)的數(shù)量。

要創(chuàng)建hash分區(qū),你需要使用create table的partition by hash(expr)子句,其中expr是整數(shù)類型的列或返還整數(shù)的表達式。另外還需要使用partions num來指定hash分區(qū)的數(shù)量(若忽略partitions子句則默認只創(chuàng)建1個hash分區(qū))。

例:創(chuàng)建一個具有4個hash分區(qū)的表,按照ID進行分區(qū):

CREATE TABLE employees (
    id INT NOT NULL,
    first_name VARCHAR(30),
    last_name VARCHAR(30)
)
PARTITION BY HASH(id)
PARTITIONS 4;

Hash分區(qū)的性能考慮:

對于hash分區(qū),數(shù)據(jù)庫決定將數(shù)據(jù)存儲在哪個分區(qū)是采用取余的方式進行運算的。存儲分區(qū)的編號n = mod(expr, num),其中expr是分區(qū)值,num為定義的分區(qū)數(shù)量。

例如:對于4個hash分區(qū),ID為5的記錄,會存儲在mod(5,4)=1,即1號分區(qū)中。

因此,最佳的分區(qū)鍵值的變化方式應該是線性變化,此時使用hash分區(qū)的效率最高,分布也會均勻。由于分區(qū)鍵值expr在每次insert/update/delete時都會運算,太復雜的表達式也會帶來負面的性能影響,在選擇時也需要考慮。

Liner hash partition(線性哈希分區(qū)):

以上的分區(qū)類型即普通hash分區(qū),另外還有一類變種叫做liner hash partition(線性哈希分區(qū)),線性哈希分區(qū)的區(qū)別是其使用了更復雜的計算方法來確定數(shù)據(jù)的分布:

1. 對于分區(qū)數(shù)量為num的分區(qū)表,先計算V:
   V = POWER(2, CEILING(LOG(2, num)))

2. 對于分區(qū)值與V-1進行位與運算
   N = expr & (V - 1)   -- 位與運算

3. 對于N>num的情況,再次計算
   N = N & ((v/2)-1)  

例:假設分區(qū)數(shù)量為4

1. 先根據(jù)分區(qū)數(shù)量num計算V的值,先log再power,如果分區(qū)數(shù)量如果是2的次方,則此公式計算結(jié)果不變。

V = power(2,ceilling(log(2,4)))  = power(2,ceillling(2)) = power(2,2) = 4

2. 對于ID為5的記錄:

N = 5 & (V-1) = 5 & 3 = 1

3. 第二步計算出的結(jié)果為1,N<=num,不再需要第三步計算,數(shù)據(jù)存儲在1號分區(qū)。

計算機的位計算效率是非常高的,因此Liner hash在新增/刪除/合并/分裂分區(qū)場景(需要重新計算并分布數(shù)據(jù))速度會快很多,非常適合特別大的數(shù)據(jù)存儲場景(TB級別)。

Liner hash的缺點是數(shù)據(jù)的分布可能沒有普通hash均勻。

管理hash分區(qū)數(shù)量:

Hash分區(qū)無法像range和list那樣添加和刪除分區(qū),但是你可以用alter table的coalesce partition子句來減少hash分區(qū)的數(shù)量,用add partition partitions N來增加指定數(shù)量的分區(qū)。

例:將employees的hash分區(qū)數(shù)量由4調(diào)整為3:

ALTER TABLE employees COALESCE PARTITION 1;  -- 移除一個分區(qū)

例:為employees表新增3個hash分區(qū):

ALTER TABLE employees ADD PARTITION PARTITIONS 3;  -- 新增3個hash分區(qū)

hahs partition和null:

對于hash partition和key partition,任何表達式對null運算,都會被當做返回為0.

4. Key partition(鍵值分區(qū))

Key paritition與hash分區(qū)類似,主要區(qū)別在于key partition的hash函數(shù)是由MySQL server提供的,且使用主鍵(或非空唯一鍵)作為分區(qū)列:

例如:創(chuàng)建一個2個分區(qū)的key partition table:

CREATE TABLE k1 (
    id INT NOT NULL PRIMARY KEY,
    name VARCHAR(20)
)
PARTITION BY KEY()  -- 未指定分區(qū)列,自動使用主鍵
PARTITIONS 2;
CREATE TABLE k1 (
    id INT NOT NULL,  -- 如果未定義not null,創(chuàng)建表會失敗
    name VARCHAR(20),
    UNIQUE KEY (id)
)
PARTITION BY KEY()  -- 未定義主鍵,自動使用unique key
PARTITIONS 2;

另外對于key partition,paritition key也不像其他分區(qū)類型那樣限制為整數(shù)類型,例如,可以使用字符型作為分區(qū)鍵:

CREATE TABLE tm1 (
    s1 CHAR(32) PRIMARY KEY   -- 字符型主鍵,同時作為partition key
)
PARTITION BY KEY(s1)
PARTITIONS 10;

對于key partition,由于primary key需要同時作為partition key,所以執(zhí)行alter table ... drop partition會報錯(NDB引擎表會重組織并生成隱藏的primary key,不受此限制)。

mysql> alter table k1 drop primary key;
ERROR 1488 (HY000): Field in list of fields for partition function not found in table
-- 主鍵刪除失敗

Key partition和hash partition一樣,也有l(wèi)iner key分區(qū)。

CREATE TABLE tk (
    col1 INT NOT NULL,
    col2 CHAR(5),
    col3 DATE
)
PARTITION BY LINEAR KEY (col1) -- Liner key partition
PARTITIONS 3;

Key partition數(shù)量的管理方法與hash partition相同。

二、subparitioning(子分區(qū))

subpartitioning可以在原有分區(qū)表的基礎上,對每個分區(qū)再次進行分區(qū)(子分區(qū))。子分區(qū)的分區(qū)類型可以和父分區(qū)不同,因此也叫復合分區(qū)。

下面的示例即對range partition的每個分區(qū)再次進行hash partition。父分區(qū)p0,p1,p2將各包含2個子分區(qū),因此最終分區(qū)的數(shù)量為3*2=6個

CREATE TABLE ts (id INT, purchased DATE)
    PARTITION BY RANGE( YEAR(purchased) )        -- 父分區(qū)采用range partition
    SUBPARTITION BY HASH( TO_DAYS(purchased) )   -- 子分區(qū)采用hash partition
    SUBPARTITIONS 2                              -- 子分區(qū)數(shù)量為2
    (
        PARTITION p0 VALUES LESS THAN (1990),
        PARTITION p1 VALUES LESS THAN (2000),
        PARTITION p2 VALUES LESS THAN MAXVALUE
    );

你也可以顯示的定義每個子分區(qū)的名稱,但如果采用這種方式定義,則必須顯示指定所有子分區(qū)。且子分區(qū)的數(shù)量必須相同,子分區(qū)名稱不能重復:

CREATE TABLE ts (id INT, purchased DATE)
    PARTITION BY RANGE( YEAR(purchased) )         --父分區(qū)為range partition
    SUBPARTITION BY HASH( TO_DAYS(purchased) )    --子分區(qū)為hash partition
   (
        PARTITION p0 VALUES LESS THAN (1990) (
            SUBPARTITION s0,                      -- 顯式指定子分區(qū)名稱和數(shù)量
            SUBPARTITION s1
        ),
        PARTITION p1 VALUES LESS THAN (2000) (
            SUBPARTITION s2,
            SUBPARTITION s3
        ),
        PARTITION p2 VALUES LESS THAN MAXVALUE (
            SUBPARTITION s4,
            SUBPARTITION s5
        )
    );

三、分區(qū)的基本維護

分區(qū)表的一大優(yōu)勢就是各個分區(qū)可以獨立存儲和管理。因此大部分在表級別上的管理操作都可以應該在分區(qū)上。

重建分區(qū):

重建分區(qū)功能相當于清除分區(qū)中所有記錄,然后在重新插入。對于頻繁的更新的分區(qū),可以定期使用重建的方式清除碎片。

ALTER TABLE employees REBUILD PARTITION p0, p1;  -- 重建p0,p1分區(qū)
ALTER TABLE employees REBUILD PARTITION ALL;     -- 重建所有分區(qū)

檢查分區(qū):

你可以用check table語句來檢查指定分區(qū)是否存在損壞:

ALTER TABLE employees CHECK PARTITION p1;  -- 檢查p1分區(qū)
ALTER TABLE employees CHECK PARTITION all; -- 檢查所有分區(qū)

鍵值分布統(tǒng)計:

使用alter table ... analyze partition可以統(tǒng)計指定分區(qū)的鍵值分布,已便更好的生成執(zhí)行計劃:

ALTER TABLE employees ANALYZE PARTITION p0;  -- 分析p0分區(qū)
ALTER TABLE employees ANALYZE PARTITION ALL; -- 分析所有分區(qū)

分區(qū)修復:

使用alter table ... repair partition來修復損壞的分區(qū):

ALTER TABLE employees REPAIR PARTITION p0; -- 分析p0分區(qū)
ALTER TABLE employees REPAIR PARTITION ALL; -- 修復所有分區(qū)

優(yōu)化分區(qū):

如果分區(qū)存在大量的數(shù)據(jù)更新,你可以使用optimize partition來回收空間,收集統(tǒng)計信息。其效果相當于在分區(qū)上執(zhí)執(zhí)行check partition、analyze partition 和 repair partition一樣。

ALTER TABLE employees OPTIMIZE PARTITION p0;

但是對于innodb存儲引擎來說,并不支持optimize partition操作,對單一分區(qū)執(zhí)行會導致所有的分區(qū)都重建,謹慎使用(Table does not support optimize on partitions. All partitions will be rebuilt and analyzed.)。

到此這篇關于MySQL分區(qū)表的具體使用的文章就介紹到這了,更多相關Mysql分區(qū)表 內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • MySQL數(shù)據(jù)庫wait_timeout參數(shù)詳細介紹

    MySQL數(shù)據(jù)庫wait_timeout參數(shù)詳細介紹

    這篇文章主要介紹了MySQL數(shù)據(jù)庫wait_timeout參數(shù)詳細介紹的相關資料,wait_timeout是MySQL中用于控制非交互式連接等待時間的系統(tǒng)變量,影響服務器資源管理和安全性,文中通過代碼介紹的非常詳細,需要的朋友可以參考下
    2024-12-12
  • win10上如何安裝mysql5.7.16(解壓縮版)

    win10上如何安裝mysql5.7.16(解壓縮版)

    這篇文章主要介紹了win10上如何安裝mysql5.7.16(解壓縮版)的相關資料,非常不錯,具有參考借鑒價值,需要的朋友可以參考下
    2016-12-12
  • MySQL變更緩沖區(qū)作用、主要配置及查看方法

    MySQL變更緩沖區(qū)作用、主要配置及查看方法

    變更緩沖區(qū)用來緩存對二級索引數(shù)據(jù)的修改,當數(shù)據(jù)頁沒有被回載到內(nèi)存中時,先把修改緩存起來,等到其他查詢操作發(fā)生時,數(shù)據(jù)頁被加載到內(nèi)存后,再直接修改內(nèi)存中的數(shù)據(jù)頁,從而達到減少磁盤I/0的目的,下面給大家介紹MySQL變更緩沖區(qū)及查看方法,感興趣的朋友一起看看吧
    2025-05-05
  • MySQL 兩種恢復數(shù)據(jù)的方法

    MySQL 兩種恢復數(shù)據(jù)的方法

    這篇文章主要介紹了MySQL 兩種恢復數(shù)據(jù)的方法,幫助恢復線上數(shù)據(jù),保證數(shù)據(jù)完整,感興趣的朋友可以了解下
    2020-10-10
  • Mysql數(shù)據(jù)庫的導入導出方式(各種情況)

    Mysql數(shù)據(jù)庫的導入導出方式(各種情況)

    這篇文章主要介紹了Mysql數(shù)據(jù)庫的導入導出方式(各種情況),具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-03-03
  • mysql 5.7.23 安裝配置方法圖文教程

    mysql 5.7.23 安裝配置方法圖文教程

    這篇文章主要為大家詳細介紹了mysql 5.7.23安裝配置方法圖文教程,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2018-09-09
  • mysql免安裝版的實際配置方法

    mysql免安裝版的實際配置方法

    本文主要向大家講述的是MySQL 免安裝版的實際配置方法,以及對其的相關的下載網(wǎng)址也有詳細介紹,望你會有所收獲。
    2010-08-08
  • mysql數(shù)據(jù)庫limit的四種用法小結(jié)

    mysql數(shù)據(jù)庫limit的四種用法小結(jié)

    mysql數(shù)據(jù)庫中l(wèi)imit子句可以被用于強制select語句返回指定的記錄數(shù),本文主要介紹了mysql數(shù)據(jù)庫limit的四種用法小結(jié),感興趣的可以了解一下
    2023-10-10
  • mysqldump造成Buffer Pool污染的研究

    mysqldump造成Buffer Pool污染的研究

    mysqldump造成Buffer Pool污染的研究,需要的朋友可以參考下
    2012-10-10
  • 詳解MySQL連接掛死的原因

    詳解MySQL連接掛死的原因

    本次分享的是一次關于 MySQL 高可用問題的定位過程,其中曲折頗多但問題本身卻比較有些代表性,遂將其記錄以供參考。
    2021-05-05

最新評論