close

Table Partition很常在大表格上使用,

本文紀錄幾種常見的Partition方式與維護辦法.

一般使用partition時,不僅僅拆檔案,

還會有將各檔案存放不同裝置的情況.

所以也說明如何指定檔案位置.

 

事前檢查

伺服器是否支援Partition,

SHOW PLUGINS;  

+-----------------------+----------+-----------------------+---------+---------+
| Name                          | Status   | Type                           | Library | License |
+-----------------------+----------+-----------------------+---------+---------+

| partition                     | ACTIVE   | STORAGE ENGINE     | NULL    | GPL     |
+-----------------------+----------+-----------------------+---------+---------+
 

是否開啟innodb一表一檔,沒有的話,惠存到統一的ibdata內,這樣分表的目的大打折扣.

SHOW VARIABLES Like 'innodb_file_per_table';

+-----------------------+-------+
| Variable_name         | Value |
+-----------------------+-------+
| innodb_file_per_table | ON    |
+-----------------------+-------+
 

Partition 種類 -> 分表Key,必須存在所有的uniquer key和primary key內.
(沒有PK與UIX的表也可以做partition,只是在新增PK與UIX時,分表key必須在內)

Range

CREATE TABLE IF NOT EXISTS `rptable` (
 
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
 
`op_dt` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
 
`op_type` int(10) unsigned NOT NULL,
 
`comment` varchar(50) NOT NULL,
  PRIMARY KEY (
`id`, `op_dt`)
) ENGINE=
InnoDB DEFAULT CHARSET=latin1
partition by range (UNIX_TIMESTAMP(`op_dt`))
(
    PARTITION
start VALUES LESS THAN (0),
    PARTITION
from20170612 VALUES LESS THAN (UNIX_TIMESTAMP('2017-06-19 00:00:00')),
    PARTITION
from20170619 VALUES LESS THAN (UNIX_TIMESTAMP('2017-06-26 00:00:00')),
    PARTITION
from20170626 VALUES LESS THAN (UNIX_TIMESTAMP('2017-07-03 00:00:00')),
    PARTITION
future VALUES LESS THAN MAXVALUE
);

List

CREATE TABLE IF NOT EXISTS `lptable` (
 
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
 
`op_dt` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
 
`op_type` int(10) unsigned NOT NULL,
 
`comment` varchar(50) NOT NULL,
  PRIMARY KEY (
`id`, `op_type`)
) ENGINE=
InnoDB DEFAULT CHARSET=latin1
partition by list (`op_type`)
(
    PARTITION
OPS VALUES IN (0),
    PARTITION
OPI VALUES IN (1),
    PARTITION
OPU VALUES IN (2),
    PARTITION
OPD VALUES IN (3)
-- default 要10.2版以上才提供
--    ,PARTITION Other DEFAULT
);

Hash

CREATE TABLE IF NOT EXISTS `hptable` (
 
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
 
`op_dt` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
 
`op_type` int(10) unsigned NOT NULL,
 
`comment` varchar(50) NOT NULL,
  PRIMARY KEY (
`id`)
) ENGINE=
InnoDB DEFAULT CHARSET=latin1
partition by HASH (`id`)
PARTITIONS
7;

Key -> 與HASH差別,在Key使用系統函式;Hash使用自定義

CREATE TABLE IF NOT EXISTS `kptable` (
 
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
 
`op_dt` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
 
`op_type` int(10) unsigned NOT NULL,
 
`comment` varchar(50) NOT NULL,
  PRIMARY KEY (
`id`)
) ENGINE=
InnoDB DEFAULT CHARSET=latin1
partition by Key (`id`)
PARTITIONS
7;

Subpartition -> 僅可使用KeyHash作為子分表的方法類型,參考 Create Table : Partition

使用key method作為sub key

CREATE TABLE IF NOT EXISTS `subptable` (
 
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
 
`op_dt` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
 
`op_type` int(10) unsigned NOT NULL,
 
`comment` varchar(50) NOT NULL,
  PRIMARY KEY (
`id`, `op_dt`)
) ENGINE=
InnoDB DEFAULT CHARSET=latin1
partition by range (UNIX_TIMESTAMP(`op_dt`))
subpartition by key (`id`)
subpartitions 2
(
    PARTITION
from20170612 VALUES LESS THAN (UNIX_TIMESTAMP('2017-06-19 00:00:00')),

    PARTITION future VALUES LESS THAN MAXVALUE
);

或者使用hash method作為sub key

CREATE TABLE IF NOT EXISTS `subptable` (
 
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
 
`op_dt` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
 
`op_type` int(10) unsigned NOT NULL,
 
`comment` varchar(50) NOT NULL,
  PRIMARY KEY (
`id`, `op_dt`)
) ENGINE=
InnoDB DEFAULT CHARSET=latin1
partition by range (UNIX_TIMESTAMP(`op_dt`))
subpartition by hash (`id`)
subpartitions 2
(
    PARTITION
from20170612 VALUES LESS THAN (UNIX_TIMESTAMP('2017-06-19 00:00:00')),

    PARTITION future VALUES LESS THAN MAXVALUE
);

指定檔案與路徑

PARTITION p_name VALUES { IN | LESS THAN } (condition) DATA DIRECTORY = 'data_path' INDEX DIRECTORY = 'ix_path'

 

Partition 操作

新增 - 若表格最後一個partition為maxvalue,則不可加入新的partition

ALTER TABLE rptable ADD PARTITION (PARTITION from20170703 VALUES LESS THAN (UNIX_TIMESTAMP('2017-07-10 00:00:00')));

刪除

ALTER TABLE rptable DROP PARTITION from20170612;

拆分

ALTER TABLE rptable REORGANIZE PARTITION future
INTO (
    PARTITION
from20170703 VALUES LESS THAN (UNIX_TIMESTAMP('2017-07-10 00:00:00')),
    PARTITION
future VALUES LESS THAN MAXVALUE
)

合併 - 必須全部重構或者對最後的partitions整合,

ALTER TABLE rptable REORGANIZE PARTITION from20170619,from20170626 INTO (
    PARTITION
from20170626 VALUES LESS THAN (UNIX_TIMESTAMP('2017-07-03 00:00:00'))
);

出錯 => Error Code: 1520
Reorganize of range partitions cannot change total ranges except for last partition where it can extend the range

ALTER TABLE rptable REORGANIZE PARTITION from20170703,future INTO (
    PARTITION
future VALUES LESS THAN MAXVALUE
);

成功

新增SP與Event,自動化新增即將使用的Partiton. 以下為SP範例

DELIMITER $$

CREATE PROCEDURE `SP_auto_add_partition`()
BEGIN
    DECLARE
p_name VARCHAR(50);
    SET
p_name := CONCAT('from', REPLACE(DATE(DATE_ADD(NOW(), INTERVAL 7 DAY)),'-', ''));
    
    SET
@run_sql := CONCAT('ALTER TABLE `rptable` REORGANIZE PARTITION future INTO ( PARTITION ', p_name);
    SET
@run_sql := CONCAT(@run_sql, ' VALUES LESS THAN (UNIX_TIMESTAMP(''', DATE(DATE_ADD(NOW(), INTERVAL 14 DAY)), ' 00:00'')), ');
    SET
@run_sql := CONCAT(@run_sql, 'PARTITION future VALUES LESS THAN MAXVALUE )');
    
    PREPARE stmt FROM
@run_sql;
    EXECUTE
stmt;
    DEALLOCATE PREPARE
stmt;
    END
$$

DELIMITER ;

 

Partition 維護

Analyze

Alter Table tbl_name Analyze Partition p_name;

Rebuild

Alter Table tbl_name Rebuild Partition p_name;

Optimize - 若engine為InnoDB,無法對單一partition執行,會對整個表執行analyze和rebuild.

Alter Table tbl_name Optimize Partition p_name;

Repair

Alter Table tbl_name Repair Partition p_name;

Check

Alter Table tbl_name Check Partition p_name;

 

正常情況下會進行Optimize或者是 Rebuild + Analyze的日常維護.

 

參考

Mariadb Partition官網

What's MySQL partition

MySQL 資料表分區(partition)  (頗多語法在MariaDB 10.X 並不適用)

arrow
arrow
    創作者介紹
    創作者 abcg5 的頭像
    abcg5

    Aaron Yang

    abcg5 發表在 痞客邦 留言(0) 人氣()