MySQL基本分区表
2019獨(dú)角獸企業(yè)重金招聘Python工程師標(biāo)準(zhǔn)>>>
準(zhǔn)備工作
1、查看數(shù)據(jù)庫的信息
了解當(dāng)前的Mysql數(shù)據(jù)庫的版本和平臺以及字符集等相關(guān)信息
mysql> status -------------- mysql Ver 14.14 Distrib 5.6.17, for Win64 (x86_64)Connection id: 4 Current database: Current user: root@localhost SSL: Not in use Using delimiter: ; Server version: 5.6.17-log MySQL Community Server (GPL) Protocol version: 10 Connection: localhost via TCP/IP Server characterset: utf8 Db characterset: utf8 Client characterset: gbk Conn. characterset: gbk TCP port: 3306 Uptime: 37 min 55 secThreads: 2 Questions: 35 Slow queries: 2 Opens: 294 Flush tables: 1 Open tables: 286 Queries per second avg: 0.015 --------------2、檢查是否支持分區(qū)
MySQL從5.1版本開始支持分區(qū)的功能。
? ? 注意:之前版本的MySQL有have_partitioning這個(gè)變量,可以查看是否支持分區(qū),但MySQL 5.6.1開始該變量被廢棄并經(jīng)被刪除。
mysql> select version(); +------------+ | version() | +------------+ | 5.6.17-log | +------------+ 1 row in set (0.07 sec)mysql> show variables like 'have_partitioning'; Empty set (0.00 sec)mysql> show variables like 'have_part%'; Empty set (0.00 sec)mysql> select version(); +-----------+ | version() | +-----------+ | 5.5.19 | +-----------+ 1 row in set (0.00 sec)mysql> show variables like 'have_part%'; +-------------------+-------+ | Variable_name | Value | +-------------------+-------+ | have_partitioning | YES | +-------------------+-------+ 1 row in set (0.00 sec)? ? 同樣可以查詢INFORMATION_SCHEMA.PLUGINS表來驗(yàn)證是否支持分區(qū)。
mysql> SELECT PLUGIN_NAME, PLUGIN_VERSION, PLUGIN_STATUS FROM information_schema.PLUGINS WHERE PLUGIN_TYPE = 'STORAGE ENGINE'; +--------------------+----------------+---------------+ | PLUGIN_NAME | PLUGIN_VERSION | PLUGIN_STATUS | +--------------------+----------------+---------------+ | binlog | 1.0 | ACTIVE | | CSV | 1.0 | ACTIVE | | MEMORY | 1.0 | ACTIVE | | MyISAM | 1.0 | ACTIVE | | MRG_MYISAM | 1.0 | ACTIVE | | ARCHIVE | 3.0 | ACTIVE | | BLACKHOLE | 1.0 | ACTIVE | | FEDERATED | 1.0 | DISABLED | | InnoDB | 5.6 | ACTIVE | | PERFORMANCE_SCHEMA | 0.1 | ACTIVE | | partition | 1.0 | ACTIVE | +--------------------+----------------+---------------+ 11 rows in set (0.03 sec)
? ? 如果輸出數(shù)據(jù)中無Active狀態(tài)的partition插件,那么說明該MySQL版本不支持分區(qū)(partitioning )。
分區(qū)類型
?? ?分區(qū)有利于管理非常大的表,分區(qū)鍵用于根據(jù)某個(gè)區(qū)間值(或者范圍值)、特定值列表或者HASH函數(shù)值執(zhí)行數(shù)據(jù)的聚集,讓數(shù)據(jù)根據(jù)規(guī)則分布在不同的分區(qū)中。
?? ?RANGE分區(qū):基于一個(gè)給定連續(xù)區(qū)間范圍,把數(shù)據(jù)分配到不同的分區(qū)。
?? ?LIST分區(qū):類似RANGE分區(qū),區(qū)別在LIST分區(qū)是基于枚舉出的值列表分區(qū),RANGE是基于給定的連續(xù)區(qū)間范圍分區(qū)。
?? ?HASH分區(qū):基于給定的分區(qū)個(gè)數(shù),把數(shù)據(jù)分配到不同的分區(qū)。
?? ?KEY分區(qū):類似于HASH分區(qū)。
?? ?Columns分區(qū):支持多列分區(qū)。
?? ?注意:
?? ??? ?RANGE分區(qū)、LIST分區(qū)、HASH分區(qū)都要求分區(qū)鍵必須是INT類型,或者通過表達(dá)式返回INT類型。
?? ??? ?無論是哪種MySQL分區(qū)類型,要么分區(qū)表上沒有主鍵/唯一鍵,要么分區(qū)表的主鍵/唯一鍵都必須包含分區(qū)鍵,也就是說不能使用主鍵/唯一鍵字段之外的其他字段作為分區(qū)鍵盤。
?
RANGE分區(qū)?
http://dev.mysql.com/doc/refman/5.6/en/partitioning-range.html
-- 示例分區(qū)表: CREATE TABLE t_employees_range_part (id INT NOT NULL,name VARCHAR(30),hired DATE NOT NULL DEFAULT '1970-01-01',dept_id INT NOT NULL comment '部門' ) ENGINE=INNODB DEFAULT CHARSET=utf8 COMMENT='測試RANAGE分區(qū)' PARTITION BY RANGE (dept_id) (PARTITION p1 VALUES LESS THAN (6),PARTITION p2 VALUES LESS THAN (11),PARTITION p3 VALUES LESS THAN (16),PARTITION p4 VALUES LESS THAN MAXVALUE );-- 按年范圍創(chuàng)建RANGE分區(qū)表 mysql> CREATE TABLE `t_bdmain_year_range_part` (`id` int(12) COMMENT '不能使用主鍵,不可自增',`dmain` varchar(512) DEFAULT NULL COMMENT '不可使用UNIQUE約束',`isip` int(4) DEFAULT NULL COMMENT '1:ip,2:名稱',`isImport` int(4) DEFAULT NULL COMMENT '1:人工,2:非人工',`isreopen` int(4) DEFAULT NULL COMMENT '1:封堵,2:解封',`blocktime` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '日期時(shí)間類型,不可為timestamp',`reason` varchar(200) DEFAULT NULL COMMENT '原因',`remark` varchar(200) DEFAULT NULL COMMENT '備注',`isabroad` varchar(8) DEFAULT NULL COMMENT '歸屬情況(0-國內(nèi),1-國際)',`is_ip_block` int(11) DEFAULT '0' COMMENT '是否為IP封堵(默認(rèn)為0;1表示IP)',`block_user` varchar(16) DEFAULT NULL COMMENT '人員') ENGINE=INNODB DEFAULT CHARSET=utf8 COMMENT='按年份創(chuàng)建的RANGE分區(qū)表'PARTITION BY RANGE(YEAR(blocktime)) (PARTITION p1 VALUES LESS THAN (2010),PARTITION p2 VALUES LESS THAN (2011),PARTITION p3 VALUES LESS THAN (2012),PARTITION p4 VALUES LESS THAN (2013),PARTITION p5 VALUES LESS THAN (2014),PARTITION p6 VALUES LESS THAN (2015),PARTITION p7 VALUES LESS THAN MAXVALUE); Query OK, 0 rows affected (2.70 sec)-- 對于dmain及時(shí)間列分別添加索引 alter table t_bdmain_year_range_part add index year_part_bdmain_sdmain_idx (dmain(255)); alter table t_bdmain_year_range_part add index year_part_bdmain_blktime_idx (blocktime);mysql> SELECT TABLE_NAME, TABLE_SCHEMA, PARTITION_NAME, TABLE_ROWS, AVG_ROW_LENGTH, DATA_LENGTHFROM INFORMATION_SCHEMA.PARTITIONSWHERE TABLE_SCHEMA = 'big_data' AND TABLE_NAME ='t_bdmain_year_range_part'; +--------------------------+--------------+----------------+------------+----------------+-------------+ | TABLE_NAME | TABLE_SCHEMA | PARTITION_NAME | TABLE_ROWS | AVG_ROW_LENGTH | DATA_LENGTH | +--------------------------+--------------+----------------+------------+----------------+-------------+ | t_bdmain_year_range_part | big_data | p1 | 0 | 0 | 16384 | | t_bdmain_year_range_part | big_data | p2 | 0 | 0 | 16384 | | t_bdmain_year_range_part | big_data | p3 | 0 | 0 | 16384 | | t_bdmain_year_range_part | big_data | p4 | 0 | 0 | 16384 | | t_bdmain_year_range_part | big_data | p5 | 0 | 0 | 16384 | | t_bdmain_year_range_part | big_data | p6 | 0 | 0 | 16384 | | t_bdmain_year_range_part | big_data | p7 | 0 | 0 | 16384 | +--------------------------+--------------+----------------+------------+----------------+-------------+ 7 rows in set (0.04 sec)-- 添加分區(qū)表數(shù)據(jù) insert into t_bdmain_year_range_part select * from my_sample_bdmain;-- 驗(yàn)證分區(qū)表 mysql> SELECT TABLE_NAME, TABLE_SCHEMA, PARTITION_NAME, TABLE_ROWS, AVG_ROW_LENGTH, DATA_LENGTHFROM INFORMATION_SCHEMA.PARTITIONSWHERE TABLE_SCHEMA = 'big_data' AND TABLE_NAME ='t_bdmain_year_range_part'; +--------------------------+--------------+----------------+------------+----------------+-------------+ | TABLE_NAME | TABLE_SCHEMA | PARTITION_NAME | TABLE_ROWS | AVG_ROW_LENGTH | DATA_LENGTH | +--------------------------+--------------+----------------+------------+----------------+-------------+ | t_bdmain_year_range_part | big_data | p1 | 5055 | 314 | 1589248 | | t_bdmain_year_range_part | big_data | p2 | 377145 | 112 | 42549248 | | t_bdmain_year_range_part | big_data | p3 | 1949760 | 77 | 151715840 | | t_bdmain_year_range_part | big_data | p4 | 784214 | 78 | 61440000 | | t_bdmain_year_range_part | big_data | p5 | 558226 | 104 | 58294272 | | t_bdmain_year_range_part | big_data | p6 | 1179288 | 109 | 128614400 | | t_bdmain_year_range_part | big_data | p7 | 335621 | 145 | 48840704 | +--------------------------+--------------+----------------+------------+----------------+-------------+
????分區(qū)表在磁盤上的存儲結(jié)構(gòu)為(在我本機(jī)上innodb_file_per_table=1)
????分區(qū)表于基本表查詢效率對比
????a. 普通表
-- \G后面如果有;號會有錯(cuò)誤輸出ERROR: No query specified mysql> explain select * from my_test_bdmain where dmain = 'www.19lou.com'\G *************************** 1. row ***************************id: 1select_type: SIMPLEtable: my_test_bdmaintype: ref possible_keys: sample_bdmain_sdmain_idxkey: sample_bdmain_sdmain_idxkey_len: 768ref: constrows: 3Extra: Using where 1 row in set (0.00 sec)mysql> mysql> explain select * from my_test_bdmain where blocktime >= '2013-01-01 00:00:00' and blocktime <= '2013-01-10 23:59:59'\G *************************** 1. row ***************************id: 1select_type: SIMPLEtable: my_test_bdmaintype: range possible_keys: sample_bdmain_blktime_idxkey: sample_bdmain_blktime_idxkey_len: 6ref: NULLrows: 71422Extra: Using index condition 1 row in set (0.00 sec)-- 當(dāng)blocktime的結(jié)束時(shí)間到某一特定的時(shí)刻時(shí)就會出現(xiàn)不走索引的情況 mysql> explain select * from my_test_bdmain where blocktime >= '2013-01-01 00:00:00' and blocktime <= '2013-08-31 23:59:59'\G *************************** 1. row ***************************id: 1select_type: SIMPLEtable: my_test_bdmaintype: ALL possible_keys: sample_bdmain_blktime_idxkey: NULLkey_len: NULLref: NULLrows: 5020180Extra: Using where 1 row in set (0.03 sec)? ? b. 分區(qū)表
mysql> explain select * from t_bdmain_year_range_part where dmain = 'www.19lou.com'\G *************************** 1. row ***************************id: 1select_type: SIMPLEtable: t_bdmain_year_range_parttype: ref possible_keys: year_part_bdmain_sdmain_idxkey: year_part_bdmain_sdmain_idxkey_len: 768ref: constrows: 6Extra: Using where 1 row in set (0.00 sec)mysql> explain partitions select * from t_bdmain_year_range_partwhere dmain = 'www.19lou.com'\G *************************** 1. row ***************************id: 1select_type: SIMPLEtable: t_bdmain_year_range_partpartitions: p1,p2,p3,p4,p5,p6,p7type: ref possible_keys: year_part_bdmain_sdmain_idxkey: year_part_bdmain_sdmain_idxkey_len: 768ref: constrows: 6Extra: Using where 1 row in set (0.00 sec)mysql> explain partitions select * from t_bdmain_year_range_partwhere blocktime >= '2013-01-01 00:00:00' and blocktime <= '2013-01-10 23:59:59'\G *************************** 1. row ***************************id: 1select_type: SIMPLEtable: t_bdmain_year_range_partpartitions: p5type: range possible_keys: year_part_bdmain_blktime_idxkey: year_part_bdmain_blktime_idxkey_len: 6ref: NULLrows: 68108Extra: Using where 1 row in set (0.00 sec)-- 分區(qū)全掃描,如果是從blocktime查詢的時(shí)候是從2013-2014則掃描兩個(gè)分區(qū) mysql> explain partitions select * from t_bdmain_year_range_partwhere blocktime >= '2013-01-01 00:00:00' and blocktime <= '2013-12-20 23:59:59'\G *************************** 1. row ***************************id: 1select_type: SIMPLEtable: t_bdmain_year_range_partpartitions: p5type: ALL possible_keys: year_part_bdmain_blktime_idxkey: NULLkey_len: NULLref: NULLrows: 558226Extra: Using where 1 row in set (0.83 sec)????創(chuàng)建月或天分區(qū)的分區(qū)表
-- 按月范圍創(chuàng)建的RANGE分區(qū)表 mysql> CREATE TABLE `t_bdmain_month_range_part` (`id` int(12) COMMENT '不能使用主鍵,不可自增',`dmain` varchar(512) DEFAULT NULL COMMENT '不可使用UNIQUE約束',`isip` int(4) DEFAULT NULL COMMENT '1:ip,2:名稱',`isImport` int(4) DEFAULT NULL COMMENT '1:人工,2:非人工',`isreopen` int(4) DEFAULT NULL COMMENT '1:封堵,2:解封',`blocktime` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '日期時(shí)間類型,不可為timestamp',`reason` varchar(200) DEFAULT NULL COMMENT '原因',`remark` varchar(200) DEFAULT NULL COMMENT '備注',`isabroad` varchar(8) DEFAULT NULL COMMENT '歸屬情況(0-國內(nèi),1-國際)',`is_ip_block` int(11) DEFAULT '0' COMMENT '是否為IP封堵(默認(rèn)為0;1為ip)',`block_user` varchar(16) DEFAULT NULL COMMENT '人員') ENGINE=INNODB DEFAULT CHARSET=utf8 COMMENT='按月創(chuàng)建的RANGE分區(qū)表'PARTITION BY RANGE(MONTH(blocktime)) (PARTITION p1 VALUES LESS THAN (2),PARTITION p2 VALUES LESS THAN (3),PARTITION p3 VALUES LESS THAN (4),PARTITION p4 VALUES LESS THAN (5),PARTITION p5 VALUES LESS THAN (6),PARTITION p6 VALUES LESS THAN (7),PARTITION p7 VALUES LESS THAN (8),PARTITION p8 VALUES LESS THAN (9),PARTITION p9 VALUES LESS THAN (10),PARTITION p10 VALUES LESS THAN (11),PARTITION p11 VALUES LESS THAN (12),PARTITION p12 VALUES LESS THAN MAXVALUE); Query OK, 0 rows affected (10.69 sec)mysql> -- 對于名稱及封堵時(shí)間列分別添加索引 alter table t_bdmain_month_range_part add index month_part_bdmain_sdmain_idx (dmain(255)); alter table t_bdmain_month_range_part add index month_part_bdmain_blktime_idx (blocktime);mysql> explain select * from t_bdmain_month_range_part where dmain = 'www.19lou.com'\G *************************** 1. row ***************************id: 1select_type: SIMPLEtable: t_bdmain_month_range_parttype: ref possible_keys: month_part_bdmain_sdmain_idxkey: month_part_bdmain_sdmain_idxkey_len: 768ref: constrows: 11Extra: Using where 1 row in set (0.00 sec)mysql> explain partitions select * from t_bdmain_month_range_partwhere blocktime >= '2013-01-01 00:00:00' and blocktime <= '2013-01-31 23:59:59'\G *************************** 1. row ***************************id: 1select_type: SIMPLEtable: t_bdmain_month_range_partpartitions: p1,p2,p3,p4,p5,p6,p7,p8,p9,p10,p11,p12type: range possible_keys: month_part_bdmain_blktime_idxkey: month_part_bdmain_blktime_idxkey_len: 6ref: NULLrows: 471106Extra: Using where 1 row in set (0.03 sec)mysql> explain partitions select * from t_bdmain_month_range_partwhere blocktime >= '2013-01-01 00:00:00' and blocktime <= '2013-10-31 23:59:59'\G *************************** 1. row ***************************id: 1select_type: SIMPLEtable: t_bdmain_month_range_partpartitions: p1,p2,p3,p4,p5,p6,p7,p8,p9,p10,p11,p12type: ALL possible_keys: month_part_bdmain_blktime_idxkey: NULLkey_len: NULLref: NULLrows: 5201742Extra: Using where 1 row in set (0.00 sec)-- 按日期范圍創(chuàng)建的RANGE分區(qū)表 mysql> CREATE TABLE `t_bdmain_day_range_part` (`id` int(12) COMMENT '不能使用主鍵,不可自增',`dmain` varchar(512) DEFAULT NULL COMMENT '不可使用UNIQUE約束',`isip` int(4) DEFAULT NULL COMMENT '1:ip,2:名稱',`isImport` int(4) DEFAULT NULL COMMENT '1:人工,2:非人工',`isreopen` int(4) DEFAULT NULL COMMENT '1:封堵,2:解封',`blocktime` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '日期時(shí)間類型,不可為timestamp',`reason` varchar(200) DEFAULT NULL COMMENT '原因',`remark` varchar(200) DEFAULT NULL COMMENT '備注',`isabroad` varchar(8) DEFAULT NULL COMMENT '歸屬情況(0-國內(nèi),1-國際)',`is_ip_block` int(11) DEFAULT '0' COMMENT '是否為IP封堵(默認(rèn)為0;1為ip)',`block_user` varchar(16) DEFAULT NULL COMMENT '人員') ENGINE=INNODB DEFAULT CHARSET=utf8 COMMENT='按時(shí)間范圍創(chuàng)建的RANGE分區(qū)表'PARTITION BY RANGE(TO_DAYS(blocktime)) (PARTITION p1 VALUES LESS THAN (TO_DAYS('2010-01-01 00:00:00')),PARTITION p2 VALUES LESS THAN (TO_DAYS('2011-01-01 00:00:00')),PARTITION p3 VALUES LESS THAN (TO_DAYS('2012-01-01 00:00:00')),PARTITION p4 VALUES LESS THAN (TO_DAYS('2013-01-01 00:00:00')),PARTITION p5 VALUES LESS THAN (TO_DAYS('2014-01-01 00:00:00')),PARTITION p6 VALUES LESS THAN (TO_DAYS('2015-01-01 00:00:00')),PARTITION p7 VALUES LESS THAN MAXVALUE);Query OK, 0 rows affected (3.65 sec)-- 對于名稱及封堵時(shí)間列分別添加索引 alter table t_bdmain_day_range_part add index day_part_bdmain_sdmain_idx (dmain(255)); alter table t_bdmain_day_range_part add index day_part_bdmain_blktime_idx (blocktime);mysql> explain select * from t_bdmain_day_range_part where dmain = 'www.19lou.com'\G *************************** 1. row ***************************id: 1 select_type: SIMPLEtable: t_bdmain_day_range_parttype: ref possible_keys: day_part_bdmain_sdmain_idxkey: day_part_bdmain_sdmain_idxkey_len: 768ref: constrows: 4Extra: Using where 1 row in set (0.00 sec)mysql> explain partitions select * from t_bdmain_day_range_partwhere blocktime >= '2013-01-01 00:00:00' and blocktime <= '2014-08-31 23:59:59'\G *************************** 1. row ***************************id: 1 select_type: SIMPLEtable: t_bdmain_day_range_part partitions: p1,p2type: ALL possible_keys: day_part_bdmain_blktime_idxkey: NULLkey_len: NULLref: NULLrows: 4574554Extra: Using where 1 row in set (0.13 sec)--001:blocktime timestamp -- ERROR 1486 (HY000): Constant, random or timezone-dependent expressions -- in (sub)partitioning function are not allowed -- 說明:分區(qū)函數(shù)不允許為常量、隨機(jī)數(shù)或者與時(shí)區(qū)相關(guān)聯(lián)的表達(dá)式,如RANGE(1970)、RANGE(rand())-- 002:`id` int(11) PRIMARY KEY AUTO_INCREMENT -- ERROR 1503 (HY000): A PRIMARY KEY must include all columns in the table's partitioning function -- id不能具有主鍵屬性(PRIMARY KEY AUTO_INCREMENT),分區(qū)鍵必須要包含unique約束的一部分-- 按時(shí)間范圍創(chuàng)建的RANGE分區(qū)表 mysql> CREATE TABLE `t_sdmain_time_range_part` (`id` int(11) NOT NULL DEFAULT 0 COMMENT '不能使用主鍵,不可自增',`dmain` varchar(512) COMMENT '名稱, 不可使用UNIQUE約束',`ipstr` varchar(1024) COMMENT '對應(yīng)IP',`iplocal` varchar(8) COMMENT '網(wǎng)內(nèi)網(wǎng)外(0:網(wǎng)內(nèi); 1:網(wǎng)外; 2:網(wǎng)內(nèi)+網(wǎng)外)',`ipabroad` varchar(8) COMMENT '境內(nèi)境外(0:境內(nèi); 1:境外; 2:境內(nèi)+境外)',`sendtime` datetime COMMENT '上報(bào)時(shí)間',`dmaintype` int(3) DEFAULT '1' COMMENT '0:正常;1:不良;2:違法:3其他',`dmainsource` varchar(16) COMMENT '來源(1、2、3、4、5、6)',`accpoint` varchar(70) COMMENT '網(wǎng)站類型 0為WAP;1為WWW;2為WAP+WWW',`serviceip` varchar(150) NOT NULL COMMENT '解析入庫的匯聚服務(wù)器IP地址',`sourcename` varchar(150) COMMENT '原始ZIP包名稱',`dmain_handle_flag` varchar(150) COMMENT '原始ZIP包標(biāo)識',`dmainflag` int(11) DEFAULT 4 COMMENT '1 疑似違規(guī);2 特定撥測;3 疑似釣魚',`flag` int(1) COMMENT '處理標(biāo)識(1:需處理; 2:過濾; 3:重現(xiàn); 4:處理中)',`createtime` timestamp DEFAULT CURRENT_TIMESTAMP COMMENT '創(chuàng)建時(shí)間,只能為timestamp' ) ENGINE=INNODB DEFAULT CHARSET=utf8 COMMENT='按時(shí)間創(chuàng)建的RANGE分區(qū)表'PARTITION BY RANGE(UNIX_TIMESTAMP(createtime)) (PARTITION p1 VALUES LESS THAN (UNIX_TIMESTAMP('2014-06-01 00:00:00')),PARTITION p2 VALUES LESS THAN (UNIX_TIMESTAMP('2015-01-01 00:00:00')),PARTITION p3 VALUES LESS THAN (UNIX_TIMESTAMP('2015-06-01 00:00:00')),PARTITION p4 VALUES LESS THAN (UNIX_TIMESTAMP('2016-01-01 00:00:00')),PARTITION p5 VALUES LESS THAN MAXVALUE);Query OK, 0 rows affected (3.65 sec)Any other expressions involving TIMESTAMP values are not permitted. (See Bug #42849.) -- Any other expressions involving TIMESTAMP values are not permitted. (See Bug #42849.)
??LIST分區(qū)
????List分區(qū)類似于Range分區(qū),只是Range提供了范圍,List提供以逗號分割的數(shù)值列表。
????http://dev.mysql.com/doc/refman/5.6/en/partitioning-list.html
????示例程序
CREATE TABLE employees_list_part_by_int (id INT NOT NULL,name VARCHAR(30),hired DATE NOT NULL DEFAULT '1970-01-01',dept_id INT NOT NULL comment '部門' ) ENGINE=INNODB DEFAULT CHARSET=utf8 COMMENT='測試LIST分區(qū)-基于整型' PARTITION BY LIST(dept_id) (PARTITION p1 VALUES IN (1, 2, 3, 4, 5),PARTITION p2 VALUES IN (6, 7, 8, 9 ,10),PARTITION p3 VALUES IN (11, 12, 13, 14, 15),PARTITION p5 VALUES IN (16, 17, 18, 19, 20) ); -- 說明:List分區(qū)無MaxValue的概念,必須指定所有值CREATE TABLE employees_list_part_by_varchar (id INT NOT NULL,name VARCHAR(30),hired DATE NOT NULL DEFAULT '1970-01-01',job_code VARCHAR(30) DEFAULT NULL COMMENT '職務(wù):manager,staff' ) ENGINE=INNODB DEFAULT CHARSET=utf8 COMMENT='測試LIST分區(qū)-基于VARCHAR類型' PARTITION BY LIST(job_code) (PARTITION p1 VALUES IN ('manager'),PARTITION p2 VALUES IN ('staff') ); ERROR 1697 (HY000): VALUES value for partition 'p1' must have type INT? ? MySQL 5.6 provides support for LIST COLUMNS partitioning. This is a variant of LIST partitioning that enables you to use columns of types other than integer types for partitioning columns, as well as to use multiple columns as partitioning keys.
CREATE TABLE `t_sdmain_dmainsource_list_part` (`id` int(11) NOT NULL DEFAULT 0 COMMENT '不能使用主鍵,不可自增',`dmain` varchar(512) COMMENT '名稱, 不可使用UNIQUE約束',`ipstr` varchar(1024) COMMENT '對應(yīng)IP',`iplocal` varchar(8) COMMENT '網(wǎng)內(nèi)網(wǎng)外(0:網(wǎng)內(nèi); 1:網(wǎng)外; 2:網(wǎng)內(nèi)+網(wǎng)外)',`ipabroad` varchar(8) COMMENT '境內(nèi)境外(0:境內(nèi); 1:境外; 2:境內(nèi)+境外)',`sendtime` datetime COMMENT '上報(bào)時(shí)間',`dmaintype` int(3) DEFAULT '1' COMMENT '0:正常;1:不良;2:違法:3其他',`dmainsource` int(3) COMMENT '來源(1、2、3、4、5、6)--必須為int類型',`accpoint` varchar(70) COMMENT '網(wǎng)站類型 0為WAP;1為WWW;2為WAP+WWW',`serviceip` varchar(150) NOT NULL COMMENT '解析入庫的匯聚服務(wù)器IP地址',`sourcename` varchar(150) COMMENT '原始ZIP包名稱',`dmain_handle_flag` varchar(150) COMMENT '原始ZIP包標(biāo)識',`dmainflag` int(11) DEFAULT 4 COMMENT '1 疑似違規(guī);2 特定撥測;3 疑似釣魚',`flag` int(1) COMMENT '處理標(biāo)識(1:需處理; 2:過濾; 3:重現(xiàn); 4:處理中)',`createtime` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '創(chuàng)建時(shí)間' ) ENGINE=INNODB DEFAULT CHARSET=utf8 COMMENT='根據(jù)大區(qū)類型創(chuàng)建的分區(qū)'PARTITION BY LIST(dmainsource) (PARTITION p1 VALUES IN (1),PARTITION p2 VALUES IN (2),PARTITION p3 VALUES IN (3),PARTITION p4 VALUES IN (4),PARTITION p5 VALUES IN (5),PARTITION p6 VALUES IN (6) );-- dmainsource = 1或者dmainsource in (1)或者dmainsource in ('1')均走分區(qū) mysql> explain partitions select * from t_sdmain_dmainsource_list_partwhere dmainsource = 1\G *************************** 1. row ***************************id: 1select_type: SIMPLEtable: t_sdmain_dmainsource_list_partpartitions: p1type: ALL possible_keys: NULLkey: NULLkey_len: NULLref: NULLrows: 221144Extra: Using where 1 row in set (0.00 sec)mysql> explain partitions select * from t_source_sdmain_201504 where dmainsource = 1\G *************************** 1. row ***************************id: 1select_type: SIMPLEtable: t_source_sdmain_201504partitions: NULLtype: ALL possible_keys: NULLkey: NULLkey_len: NULLref: NULLrows: 700330Extra: Using where 1 row in set (0.00 sec)?
COLUMNS分區(qū)
????包括RANGE COLUMNS 和 LIST COLUMNS兩種,分別為RANGE及LIST類型分區(qū)的變種。
??? 允許作為分區(qū)鍵數(shù)據(jù)類型如下:
?? ?整型類型
?? ??? ?支持TINYINT, SMALLINT, MEDIUMINT, INT (INTEGER), 以及BIGINT,其他數(shù)值類型不支持,如DECIMAL、FLOAT
?? ?日期類型
?? ??? ?支持DATE 和 DATETIME,不支持其他日期、時(shí)間類型
?? ?字符類型
?? ??? ?支持 CHAR, VARCHAR, BINARY, 以及 VARBINARY,不支持TEXT、 BLOB
?
????RANGE COLUMNS分區(qū):????
????????RANGE columns分區(qū)類似于range分區(qū),允許基于多列值定義分區(qū)范圍。另外,可以使用非整型類型來定義分區(qū)范圍。
?? ??? ?RANGE COLUMNS分區(qū)主要在如下方面區(qū)別于RANGE分區(qū):
?? ??? ?a、RANGE COLUMNS不接受表達(dá)式,只允許提供列名稱;
?? ??? ?b、RANGE COLUMNS可以使用一列或多列;
?? ??? ??? ?RANGE Columns分區(qū)鍵的比較是基于元組的比較,也就是基于字段組的比較。
?? ??? ?c、RANGE COLUMNS不再限定分區(qū)鍵必須為整型(integer),字符串, DATE 以及 DATETIME同樣允許使用。
?? ??? ?創(chuàng)建RANGE COLUMNS分區(qū)表的語法如下:
?
?LIST COLUMNS分區(qū):
? ? ? ? 分區(qū)鍵只能使用列名稱,而不允許使用表達(dá)式。???
? ?
HASH分區(qū)
?????http://dev.mysql.com/doc/refman/5.6/en/partitioning-hash.html
????指定分區(qū)字段,由MySQL數(shù)據(jù)庫來決定數(shù)據(jù)存儲到哪一個(gè)分區(qū)。
CREATE TABLE () PARTITION BY HASH (expr)說明:
?? ?expr表達(dá)式需要返回一個(gè)整數(shù)值(must return a nonconstant, nonrandom integer value)。
?? ?每一次的insert或update操作都會執(zhí)行expr的計(jì)算,因此負(fù)責(zé)的expr將會引發(fā)性能問題,特別是影響大量數(shù)據(jù)行的操作(如批量添加)。
最有效的hash功能是基于單個(gè)表中值固定增加或減少的列。
MySQL通過HASH函數(shù)來確認(rèn)數(shù)據(jù)應(yīng)該存儲于哪一個(gè)分區(qū),計(jì)算方式為N = MOD(expr, num)????
CREATE TABLE t1 (col1 INT, col2 CHAR(5), col3 DATE) PARTITION BY HASH( YEAR(col3) ) PARTITIONS 4;????當(dāng)向表t1的col3這一列插入值'2015-08-20'時(shí),該行數(shù)據(jù)存入哪一個(gè)分區(qū)按照如下語句確認(rèn):
MOD(YEAR('2015-08-20'),4) = MOD(2015,4) = 3????業(yè)務(wù)示例
CREATE TABLE `t_sdmain_day_hash_part` (`id` int(11) NOT NULL DEFAULT 0 COMMENT '不能使用主鍵,不可自增',`dmain` varchar(512) COMMENT '名稱, 不可使用UNIQUE約束',`ipstr` varchar(1024) COMMENT '對應(yīng)IP',`iplocal` varchar(8) COMMENT '網(wǎng)內(nèi)網(wǎng)外(0:網(wǎng)內(nèi); 1:網(wǎng)外; 2:網(wǎng)內(nèi)+網(wǎng)外)',`ipabroad` varchar(8) COMMENT '境內(nèi)境外(0:境內(nèi); 1:境外; 2:境內(nèi)+境外)',`sendtime` datetime COMMENT '上報(bào)時(shí)間',`dmaintype` int(3) DEFAULT '1' COMMENT '0:正常;1:不良;2:違法:3其他',`dmainsource` int(3) COMMENT '來源(1、2、3、4、5、6)--必須為int類型',`accpoint` varchar(70) COMMENT '網(wǎng)站類型 0為WAP;1為WWW;2為WAP+WWW',`serviceip` varchar(150) NOT NULL COMMENT '解析入庫的匯聚服務(wù)器IP地址',`sourcename` varchar(150) COMMENT '原始ZIP包名稱',`dmain_handle_flag` varchar(150) COMMENT '原始ZIP包標(biāo)識',`dmainflag` int(11) DEFAULT 4 COMMENT '1 疑似違規(guī);2 特定撥測;3 疑似釣魚',`flag` int(1) COMMENT '處理標(biāo)識(1:需處理; 2:過濾; 3:重現(xiàn); 4:處理中)',`createtime` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '創(chuàng)建時(shí)間' ) ENGINE=INNODB DEFAULT CHARSET=utf8 COMMENT='按天區(qū)表'PARTITION BY HASH(DAY(createtime))PARTITIONS 4;-- 按日期查詢 mysql> explain partitions select * from t_sdmain_day_hash_partwhere createtime = '2015-04-10 07:49:15'\G *************************** 1. row ***************************id: 1select_type: SIMPLEtable: t_sdmain_day_hash_partpartitions: p2type: ALL possible_keys: NULLkey: NULLkey_len: NULLref: NULLrows: 143910Extra: Using where 1 row in set (0.00 sec)-- HASH分區(qū)有個(gè)問題,就是where條件是指定的一個(gè)范圍的話,將會掃描所有分區(qū), -- 這就達(dá)不到使用分區(qū)表來減少掃描范圍獲得性能的提高的目的。mysql> explain partitions select * from t_sdmain_day_hash_partwhere createtime >= '2015-03-31 00:03:22' and createtime <= '2015-03-31 01:49:15'\G *************************** 1. row ***************************id: 1select_type: SIMPLEtable: t_sdmain_day_hash_partpartitions: p0,p1,p2,p3type: ALL possible_keys: NULLkey: NULLkey_len: NULLref: NULLrows: 789530Extra: Using where 1 row in set (0.00 sec)-- 以上語句就是掃描所有分區(qū).線性HASH分區(qū)
? ? MySQL同樣支持線性哈希分區(qū),采用powers-of-two algorithm來確認(rèn)數(shù)據(jù)存儲于哪一個(gè)分區(qū)中。
????對于給定的expr,分區(qū)數(shù)目num,MySQL計(jì)算數(shù)據(jù)存儲于具體哪個(gè)分區(qū)算法如下:
1、Find the next power of 2 greater than num. We call this value V; it can be calculated as:V = POWER(2, CEILING(LOG(2, num)))(Suppose that num is 13. Then LOG(2,13) is 3.7004397181411. CEILING(3.7004397181411) is 4, and V = POWER(2,4), which is 16.)2、Set N = F(column_list) & (V - 1).3、While N >= num:Set V = CEIL(V / 2)Set N = N & (V - 1)?示例如下:
CREATE TABLE my_linear_part_001 (col1 INT, col2 CHAR(5), col3 DATE) PARTITION BY LINEAR HASH( YEAR(col3) ) PARTITIONS 6;insert into my_linear_part_001(col1, col2, col3) values(1, 'hello', '2003-04-14'); insert into my_linear_part_001(col1, col2, col3) values(2, 'hello', '1998-10-19'); V = POWER(2, CEILING( LOG(2,6) )) = 8 a. 判定2003-04-14這一行數(shù)據(jù)存儲于哪個(gè)分區(qū) N = YEAR('2003-04-14') & (8 - 1)= 2003 & 7= 3(3 >= 6 is FALSE: record stored in partition #3)b. 判定1998-10-19這一行數(shù)據(jù)存儲于哪個(gè)分區(qū) N = YEAR('1998-10-19') & (8-1)= 1998 & 7= 6(6 >= 6 is TRUE: additional step required)N = 6 & CEILING(8 / 2)= 6 & 3= 2(2 >= 6 is FALSE: record stored in partition #2)? ?
KEY分區(qū)
????http://dev.mysql.com/doc/refman/5.6/en/partitioning-key.html
????Key分區(qū)類似于Hash分區(qū),只是Hash分區(qū)是基于用戶提供的expr來計(jì)算屬于哪個(gè)分區(qū),而Key分區(qū)的hash函數(shù)是由MySQL Server提供的,這些函數(shù)是基于與PASSWORD()一樣的運(yùn)算法則。
????Key分區(qū)于Hash分區(qū)區(qū)別:
????1、PARTITION BY KEY而非PARTITION BY HASH
????2、KEY只能指定零個(gè)或多個(gè)列名稱。
????KEY takes only a list of zero or more column names. Any columns used as the partitioning key must comprise part or all of the table's primary key, if the table has one. Where no column name is specified as the partitioning key, the table's primary key is used, if there is one.???
CREATE TABLE k_part_by_pk (id INT NOT NULL PRIMARY KEY,name VARCHAR(20) DEFAULT NULL ) PARTITION BY KEY() -- 采用主鍵來分區(qū) PARTITIONS 2; mysql> ALTER TABLE k_part_by_pk DROP PRIMARY KEY; ERROR 1488 (HY000): Field in list of fields for partition function not found in tableCREATE TABLE k_part_by_unique_key (id INT NOT NULL,name VARCHAR(20) DEFAULT NULL,UNIQUE KEY (name) ) PARTITION BY KEY() -- 采用UNIQUE KEY來分區(qū) PARTITIONS 2;CREATE TABLE k_part_by_unique_key_with_null (id INT,name VARCHAR(20) DEFAULT NULL,UNIQUE KEY (id) ) PARTITION BY KEY() -- UNIQUE KEY未加NOT NULL將報(bào)錯(cuò) PARTITIONS 2; ERROR 1488 (HY000): Field in list of fields for partition function not found in tableCREATE TABLE k_part_by_varchar (id INT NOT NULL,name VARCHAR(20) DEFAULT NULL ) PARTITION BY KEY(name) PARTITIONS 2;CREATE TABLE k_part_by_int_and_varchar (id INT NOT NULL,name VARCHAR(20) DEFAULT NULL ) PARTITION BY KEY(id, name) PARTITIONS 2;-- MySQL支持Linear Key形式的分區(qū)表 CREATE TABLE k_part_of_linear_key (col1 INT NOT NULL,col2 CHAR(5),col3 DATE ) PARTITION BY LINEAR KEY (col1) PARTITIONS 3;-- 業(yè)務(wù)示例 CREATE TABLE `t_sdmain_sdmain_key_part` (`id` int(11) NOT NULL DEFAULT 0 COMMENT '不能使用主鍵,不可自增',`dmain` varchar(512) COMMENT '名稱, 不可使用UNIQUE約束',`ipstr` varchar(4000) COMMENT '對應(yīng)IP',`iplocal` varchar(8) COMMENT '網(wǎng)內(nèi)網(wǎng)外(0:網(wǎng)內(nèi); 1:網(wǎng)外; 2:網(wǎng)內(nèi)+網(wǎng)外)',`ipabroad` varchar(8) COMMENT '境內(nèi)境外(0:境內(nèi); 1:境外; 2:境內(nèi)+境外)',`sendtime` datetime COMMENT '上報(bào)時(shí)間',`dmaintype` int(3) DEFAULT '1' COMMENT '0:正常;1:不良;2:違法:3其他',`dmainsource` varchar(16) COMMENT '來源(1、2、3、4、5、6)',`accpoint` varchar(70) COMMENT '網(wǎng)站類型 0為WAP;1為WWW;2為WAP+WWW',`serviceip` varchar(150) NOT NULL COMMENT '解析入庫的匯聚服務(wù)器IP地址',`sourcename` varchar(150) COMMENT '原始ZIP包名稱',`dmain_handle_flag` varchar(150) COMMENT '原始ZIP包標(biāo)識',`dmainflag` int(11) DEFAULT 4 COMMENT '1 疑似違規(guī);2 特定撥測;3 疑似釣魚',`flag` int(1) COMMENT '處理標(biāo)識(1:需處理; 2:過濾; 3:重現(xiàn); 4:處理中)',`createtime` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '創(chuàng)建時(shí)間' ) ENGINE=INNODB DEFAULT CHARSET=utf8 COMMENT='按名稱名稱分區(qū)表'PARTITION BY KEY(dmain)PARTITIONS 6;-- dmain字段的長度不能超過1023,否則報(bào)錯(cuò)如下 -- ERROR 1660 (HY000): The total length of the partitioning fields is too large -- 說明:該問題暫未解決(對于截取名稱作為分區(qū)依據(jù)同樣報(bào)錯(cuò)KEY(LEFT(dmain, 50)))。mysql> explain partitions select * from t_sdmain_sdmain_key_partwhere dmain in ('s3-us-west-2.amazonaws.com', 'aaa077.com', 'mydress.com')\G *************************** 1. row ***************************id: 1select_type: SIMPLEtable: t_sdmain_sdmain_key_partpartitions: p2,p4type: ALL possible_keys: NULLkey: NULLkey_len: NULLref: NULLrows: 516467Extra: Using where 1 row in set (0.00 sec)-- Key分區(qū)和HASH分區(qū)一樣,有范圍掃描的問題。?
轉(zhuǎn)載于:https://my.oschina.net/dolphinboy/blog/1438880
總結(jié)
以上是生活随笔為你收集整理的MySQL基本分区表的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: gdb可以查询执行文件的宏, 但是查询不
- 下一篇: 机器学习模型开发必读:开源数据库最全盘点