查看mysql是否支持分區需要使用命令:
如果沒有看到變量:have_partition_engine的值爲YES,而是爲empty,則說明當前mysql的版本就不支持分區。mysql從5.1開始支持分區功能。但是如果你使用mysql高於5.1版本卻出現empty的結果。改用:
出現partition active證明支持分區。
MySQL 表分區策略
RANGE 分區 基於屬於一個給定連續區間的列值,把多行分配給分區。
DROP TABLE IF EXISTS `p_range`;
CREATE TABLE `p_range` (
`id` int(10) NOT NULL AUTO_INCREMENT,
`name` char(20) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=9 DEFAULT CHARSET=utf8
/*!50100 PARTITION BY RANGE (id)
(PARTITION p0 VALUES LESS THAN (8) ENGINE = MyISAM) */;
最大值
PARTITION BY RANGE (id)
(
PARTITION p0 VALUES LESS THAN (8),
PARTITION p1 VALUES LESS THAN MAXVALUE)
適用場景:
這樣就表示,所有 id 大於 7 的數據記錄存在在 p1 分區裏。
RANGE 分區在如下場合特別有用:
· 當需要刪除“舊的”數據時。如果你使用上面最近的那個例子給出的分區方案,你只需簡單地使用 “ALTER TABLE employees DROP PARTITION p0;”來刪除所有在 1991 年前就已經停止工作的僱員相對應的所有行。對於有大量行的表,這比運行一個如“DELETE FROM employees WHERE YEAR(separated) <=
1990;”這樣的一個 DELETE 查詢要有效得多。
· 想要使用一個包含有日期或時間值,或包含有從一些其他級數開始增長的值的列。
· 經常運行直接依賴於用於分割表的列的查詢。例如,當執行一個如
“SELECT COUNT(*) FROM employees WHERE YEAR(separated) = 2000 GROUP BY store_id;”這樣的查詢時,MySQL 可以很迅速地確定只有分區 p2 需要掃描,這是因爲餘下的分區不可能包含有符合該 WHERE 子句的任何記錄
LIST 分區 類似於按 RANGE 分區,區別在於 LIST 分區是基於列值匹配一個離散值集合中的某個值來進行選擇。
DROP TABLE IF EXISTS `p_list`;
CREATE TABLE `p_list` (
`id` int(10) NOT NULL AUTO_INCREMENT,
`typeid` mediumint(10) NOT NULL DEFAULT '0',
`typename` char(20) DEFAULT NULL,
PRIMARY KEY (`id`,`typeid`)
) ENGINE=MyISAM AUTO_INCREMENT=9 DEFAULT CHARSET=utf8
/*!50100 PARTITION BY LIST (typeid)
(PARTITION p0 VALUES IN (1,2,3,4) ENGINE = MyISAM, PARTITION p1 VALUES IN (5,6,7,8) ENGINE = MyISAM) */;
HASH 分區 基於用戶定義的表達式的返回值來進行選擇的分區,該表達
式使用將要插入到表中的這些行的列值進行計算。這個函數可以包含 MySQL 中有效的、產生非負整數值的任何表達式。 HASH 分區主要用來確保數據在預先確定數目的分區中平均分佈。在 RANGE 和 LIST 分區中,必須明確指定一個給定的列值或列值集合應該保存在哪個分區中;而在 HASH 分區中,MySQL 自動完成這些工作,你所要做的只是基於將要被哈希的列值指定一個列值或表達式,以及指定被分區的表將要被分割成的分區數量
DROP TABLE IF EXISTS `p_hash`;
CREATE TABLE `p_hash` (
`id` int(10) NOT NULL AUTO_INCREMENT,
`storeid` mediumint(10) NOT NULL DEFAULT '0',
`storename` char(255) DEFAULT NULL,
PRIMARY KEY (`id`,`storeid`)
) ENGINE=InnoDB AUTO_INCREMENT=11 DEFAULT CHARSET=utf8
/*!50100 PARTITION BY HASH (storeid)
PARTITIONS 4 */;
簡單點說就是數據的存入可以按 partition by hash(expr); 這裏的 expr 可以
是鍵名也可以是表達式比如 YEAR(time),如果是表達式的情況下
“但是應當記住,每當插入或更新(或者可能刪除)一行,這個表達式都要計
算一次;這意味着非常複雜的表達式可能會引起性能問題,尤其是在執行同時
影響大量行的運算(例如批量插入)的時候。 ”
在執行刪除、寫入、更新時這個表達式都會計算一次。
數據的分佈採用基於用戶函數結果的模數來確定使用哪個編號的分區。換句話,對於一個表達式“expr”,將要保存記錄的分區編號爲 N ,其中“N = MOD(expr, num)”。
比如上面的 storeid 爲 10;那麼 N=MOD(10,4) ;N 是等於 2 的,那麼這條記錄就存儲在 p2 的分區裏面。
如果插入一個表達式列值爲'2005-09-15′的記錄到表中,那麼保存該條記錄的分區確定如下:MOD(YEAR('2005-09-01′),4) = MOD(2005,4) = 1 ; 就存儲在 p1 分區裏面了。
分區注意點
1、重新分區時,如果原分區裏面存在 maxvalue 則新的分區裏面也必須包含
maxvalue 否則就錯誤。
alter table p_range2x
reorganize partition p1,p2
into (partition p0 values less than (5), partition p1 values less than maxvalue);
[Err] 1520 – Reorganize of range partitions cannot change total ranges except for last partition where it can extend the range
2、分區刪除時,數據也同樣會被刪除 alter table p_range drop partition p0;
3、如果 range 分區列表裏面沒有 maxvalue 則如有新數據大於現在分區 range 數據值那麼這個數據是無法寫入到數據庫表的。
4、修改表名不需要 刪除分區後在進行更改,修改表名後分區存儲 myd myi 對應也會自動更改。
如果希望從所有分區刪除所有的數據,但是又保留表的定義和表的分區模式,使用 TRUNCATE TABLE 命令。(請參見 13.2.9 節,“TRUNCATE 語法”)。
如果希望改變表的分區而又不丟失數據,使用“ALTER TABLE … REORGANIZE PARTITION”語句。參見下面的內容,或者在 13.1.2 節,“ALTER TABLE 語法” 中參考關於 REORGANIZE PARTITION 的信息。
5、對錶進行分區時,不論採用哪種分區方式如果表中存在主鍵那麼主鍵必須在分區列中。表分區的侷限性。
6、list 方式分區沒有類似於 range 那種 less than maxvalue 的寫法,也就是說 list 分區表的所有數據都必須在分區字段的值列表集合中。
7、在 MySQL 5.1 版中,同一個分區表的所有分區必須使用同一個存儲引擎;例如,不能對一個分區使用 MyISAM,而對另一個使用 InnoDB。
8、分區的名字是不區分大小寫的,myp1 與 MYp1 是相同的。
9、學習地址:http://www.roncoo.com/course/view/658088f6e77541f5835b61800314083e