MySQL5.5的分區表

變更普通表baby_user_change_log爲分區表




一、 表列描述

     mysql> desc baby_user_change_log ;

     +--------------+------------------+------+-----+---------+----------------+

     | Field        | Type             | Null | Key | Default | Extra          |

     +--------------+------------------+------+-----+---------+----------------+

     | id           | int(11) unsigned | NO   | PRI | NULL    | auto_increment |

     | account_id   | int(11) unsigned | NO   | MUL | NULL    |                |

     | 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    |                |

     +--------------+------------------+------+-----+---------+----------------+


二、 表結構特徵


      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;


三、適合的分區方案


      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)



四、 分區表的原理及優缺點



     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不支持空間類型和臨時表類型進行分區。不支持全文索引

     


五、分區表的分區類型

     

    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

     


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章