變動普通表baby_user_change_log爲分區表html
1、 表列描述node
mysql> desc baby_user_change_log ;mysql
+--------------+------------------+------+-----+---------+----------------+sql
| Field | Type | Null | Key | Default | Extra |數據庫
+--------------+------------------+------+-----+---------+----------------+服務器
| id | int(11) unsigned | NO | PRI | NULL | auto_increment |app
| account_id | int(11) unsigned | NO | MUL | NULL | |ide
| app_id | int(11) | YES | | NULL | |函數
| operate | varchar(20) | YES | | NULL | |優化
| old_data | varchar(2000) | YES | | NULL | |
| new_data | varchar(2000) | YES | | NULL | |
| change_data | varchar(2000) | YES | | NULL | |
| operate_time | int(11) | YES | | NULL | |
+--------------+------------------+------+-----+---------+----------------+
2、 表結構特徵
CREATE TABLE `baby_user_change_log` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增id',
`account_id` int(11) unsigned NOT NULL COMMENT 'account_id',
`app_id` int(11) DEFAULT NULL COMMENT '平臺ID',
`operate` varchar(20) DEFAULT NULL COMMENT '操做類型',
`old_data` varchar(2000) DEFAULT NULL COMMENT '修改以前的數據',
`new_data` varchar(2000) DEFAULT NULL COMMENT '修改以後的數據',
`change_data` varchar(2000) DEFAULT NULL COMMENT '被修改的數據',
`operate_time` int(11) DEFAULT NULL COMMENT '時間',
PRIMARY KEY (`id`),
KEY `idx_account_id` (`account_id`)
)ENGINE=MyISAM AUTO_INCREMENT=18543058 DEFAULT CHARSET=utf8;
3、適合的分區方案
1)表總數據記錄條數:
mysql> select count(*) from baby_user_change_log;
+----------+
| count(*) |
+----------+
| 18552945 |
+----------+
2)其中app_id 列具備按照RANGE分區的特徵
mysql> select distinct(app_id) from baby_user_change_log;
+--------+
| app_id |
+--------+
| 7 |
| 5 |
| 3 |
| 1 |
+--------+
3)具體的分區表結構SQL
CREATE TABLE `baby_user_change_log_partition` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增id',
`account_id` int(11) unsigned NOT NULL COMMENT 'account_id',
`app_id` int(11) DEFAULT NULL COMMENT '平臺ID',
`operate` varchar(20) DEFAULT NULL COMMENT '操做類型',
`old_data` varchar(2000) DEFAULT NULL COMMENT '修改以前的數據',
`new_data` varchar(2000) DEFAULT NULL COMMENT '修改以後的數據',
`change_data` varchar(2000) DEFAULT NULL COMMENT '被修改的數據',
`operate_time` int(11) DEFAULT NULL COMMENT '時間',
PRIMARY KEY (`id`,`app_id`),
KEY `idx_account_id` (`account_id`)
)ENGINE=MyISAM AUTO_INCREMENT=0 DEFAULT CHARSET=utf8
PARTITION BY RANGE (app_id) (
PARTITION p0 VALUES LESS THAN (1),
PARTITION p1 VALUES LESS THAN (3),
PARTITION p2 VALUES LESS THAN (5),
PARTITION p3 VALUES LESS THAN (7),
PARTITION p4 VALUES LESS THAN MAXVALUE
);
4)插入數據
insert into baby_user_change_log_partition select* from baby_user_change_log;
5)驗證結果
mysql> explain partitions select * from baby_user_change_log_partition where app_id=1;
+----+-------------+-----------------------------------------+------------+------+---------------+------------+---------+-------+-------+-------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-----------------------------------------+------------+------+---------------+------------+---------+-------+-------+-------+
| 1 | SIMPLE | baby_user_change_log_partition | p1 | ref | idx_app_id | idx_app_id | 4 | const | 25739 | |
+----+-------------+-----------------------------------------+------------+------+---------------+------------+---------+-------+-------+-------+
1 row in set (0.00 sec)
mysql> explain partitions select * from baby_user_change_log_partition where app_id=7;
+----+-------------+-----------------------------------------+------------+------+---------------+------------+---------+-------+------+-------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-----------------------------------------+------------+------+---------------+------------+---------+-------+------+-------+
| 1 | SIMPLE | baby_user_change_log_partition | p4 | ref | idx_app_id | idx_app_id | 4 | const | 276 | |
+----+-------------+-----------------------------------------+------------+------+---------------+------------+---------+-------+------+-------+
1 row in set (0.00 sec)
mysql> explain partitions select * from baby_user_change_log_partition;
+----+-------------+-----------------------------------------+----------------+------+---------------+------+---------+------+-------+-------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-----------------------------------------+----------------+------+---------------+------+---------+------+-------+-------+
| 1 | SIMPLE | baby_user_change_log_partition | p0,p1,p2,p3,p4 | ALL | NULL | NULL | NULL | NULL | 56269 | |
+----+-------------+-----------------------------------------+----------------+------+---------------+------+---------+------+-------+-------+
1 row in set (0.00 sec)
4、 分區表的原理及優缺點
1)分區表是什麼?分區表是由多個相關的底層表實現,這些底層表也是由句柄對象表示,因此咱們也能夠直接訪問各個分區,
存儲引擎管理分區的各個底層表和管理普通表同樣(全部的底層表都必須使用相同的存儲引擎),分區表的索引只是在各個
底層表上各自加上一個相同的索引,從存儲引擎的角度來看,底層表和一個普通表沒有任何不一樣,存儲引擎也無須知道這是
一個普通表仍是一個分區表的一部分。
2)在分區表上的操做按照下面的操做邏輯進行:
1.select查詢:
當查詢一個分區表的時候,分區層先打開並鎖住全部的底層表,優化器判斷是否能夠過濾部分分區,
而後再調用對應的存儲引擎接口訪問各個分區的數據
2.insert操做:
當寫入一條記錄時,分區層打開並鎖住全部的底層表,而後肯定哪一個分區接受這條記錄,再將記錄寫入對應的底層表
3.delete操做:
當刪除一條記錄時,分區層先打開並鎖住全部的底層表,而後肯定數據對應的分區,最後對相應底層表進行刪除操做
4.update操做:
當更新一條數據時,分區層先打開並鎖住全部的底層表,mysql先肯定須要更新的記錄在哪一個分區,而後取出數據並更新,
再判斷更新後的數據應該放在哪一個分區,而後對底層表進行寫入操做,並對原數據所在的底層表進行刪除操做
3)雖然每一個操做都會打開並鎖住全部的底層表,但這並非說分區表在處理過程當中是鎖住全表的,若是存儲引擎可以本身實現行級鎖,
如:innodb,則會在分區層釋放對應的表鎖,這個加鎖和解鎖過程與普通Innodb上的查詢相似。
4)分區表適用的場景
1.表很是大以致於沒法所有都放在內存中,或者只在表的最後部分有熱點數據,其餘都是歷史數據
2.分區表的數據更容易維護,如:想批量刪除大量數據可使用清除整個分區的方式。另外,
還能夠對一個獨立分區進行優化、檢查、修復等操做
3.分區表的數據能夠分佈在不一樣的物理設備上,從而高效地利用多個硬件設備
4.可使用分區表來避免某些特殊的瓶頸,如:innodb的單個索引的互斥訪問,ext3文件系統的inode鎖競爭等
5.若是須要,還能夠備份和恢復獨立的分區,這在很是大的數據集的場景下效果很是好
6.優化查詢,在where字句中包含分區列時,能夠只使用必要的分區來提升查詢效率,
同時在涉及sum()和count()這類聚合函數的查詢時,能夠在每一個分區上面並行處理,
最終只須要彙總全部分區獲得的結果。
5)分區表的限制
1.一個表最多隻能有1024個分區,包含子分區(mysql5.6以後支持8192個分區)
2.在mysql5.1中分區表達式必須是整數,或者是返回整數的表達式,
在5.5以後某些場景能夠直接使用字符串列和日期類型列來進行分區
使用varchar字符串類型列時,通常仍是字符串的日期做爲分區。
3.若是分區字段中有主鍵或者惟一索引列,那麼全部主鍵列和惟一索引列都必須包含進來,
若是表中有主鍵或惟一索引,那麼分區鍵必須是主鍵或惟一索引
4.分區表中沒法使用外鍵約束
5.mysql數據庫支持的分區類型爲水平分區,並不支持垂直分區,
所以mysql數據庫的分區中索引是局部分區索引,一個分區中既存放了數據又存放了索引,
而全局分區是指的數據庫放在各個分區中,可是全部的數據的索引放在另一個對象中
6.目前mysql不支持空間類型和臨時表類型進行分區。不支持全文索引
5、分區表的分區類型
1)分區表根據數據類型的特徵適用不一樣的分區類型主要的類型有:
1.RANGE分區:基於屬於一個給定連續區間的列值,把多行分配給分區。
2.LIST分區:相似於按RANGE分區,區別在於LIST分區是基於列值匹配一個離散值集合中的某個值來進行選擇。
3.HASH分區:基於用戶定義的表達式的返回值來進行選擇的分區,該表達式使用將要插入到表中的這些行的列值進行計算。
這個函數能夠包含MySQL 中有效的、產生非負整數值的任何表達式。
4.KEY分區:相似於按HASH分區,區別在於KEY分區只支持計算一列或多列,且MySQL服務器提供其自身的哈希函數。
必須有一列或多列包含整數值。
分區表官方文檔的解釋與說明:
http://dev.mysql.com/doc/refman/5.5/en/partitioning.html