50.3. Partitioning

50.3. Partitioning

大家好,又见面了,我是全栈君。

	
mysql> SHOW VARIABLES LIKE '%partition%';

+-------------------+-------+
| Variable_name     | Value |
+-------------------+-------+
| have_partitioning | YES   |
+-------------------+-------+
1 row in set (0.00 sec)
	
	

50.3.1. RANGE

18.5.1. Partitioning Keys, Primary Keys, and Unique Keys
This section discusses the relationship of partitioning keys with primary keys and unique keys. The rule governing this relationship can be expressed as follows: All columns used in the partitioning expression for a partitioned table must be part of every unique key that the table may have.

In other words, every unique key on the table must use every column in the table's partitioning expression. (This also includes the table's primary key, since it is by definition a unique key. This particular case is discussed later in this section.) For example, each of the following table creation statements is invalid:


SQL code:
mysql> create table tx (
    ->     id int not null ,
    ->     info_time date,
    ->     primary key(id,info_time)
    -> )
    -> PARTITION BY RANGE(info_time div 100)
    -> (
    ->     PARTITION p_2008_11 VALUES LESS THAN (200812),
    ->     PARTITION p_2008_12 VALUES LESS THAN (200901),
    ->     PARTITION p_2009_01 VALUES LESS THAN (200902),
    ->     PARTITION p_2009_02 VALUES LESS THAN (200903),
    ->     PARTITION p_2009_03 VALUES LESS THAN (200904),
    ->     PARTITION p_2009_04 VALUES LESS THAN (200905),
    ->     PARTITION p_catch_all VALUES LESS THAN MAXVALUE
    -> );
Query OK, 0 rows affected (0.17 sec)

mysql>
		
		
CREATE TABLE t1 (
    year_col  INT,
    some_data INT
)
PARTITION BY RANGE (year_col) (
    PARTITION p0 VALUES LESS THAN (1991),
    PARTITION p1 VALUES LESS THAN (1995),
    PARTITION p2 VALUES LESS THAN (1999),
    PARTITION p3 VALUES LESS THAN (2002),
    PARTITION p4 VALUES LESS THAN (2006),
    PARTITION p5 VALUES LESS THAN MAXVALUE
);
		
		

e.g.2

				
CREATE TABLE rc (
    a INT NOT NULL,
    b INT NOT NULL
)
PARTITION BY RANGE COLUMNS(a,b) (
    PARTITION p0 VALUES LESS THAN (10,5),
    PARTITION p1 VALUES LESS THAN (20,10),
    PARTITION p2 VALUES LESS THAN (MAXVALUE,15),
    PARTITION p3 VALUES LESS THAN (MAXVALUE,MAXVALUE)
);
				
		
		
CREATE TABLE part_tab
(
	c1 int default NULL,
	c2 varchar(30) default NULL,
	c3 date default NULL

) engine=myisam
PARTITION BY RANGE (year(c3)) (
      PARTITION p0 VALUES LESS THAN (2000) ,
      PARTITION p1 VALUES LESS THAN (2001) ,
      PARTITION p2 VALUES LESS THAN (2002) ,
      PARTITION p3 VALUES LESS THAN (2003) ,
      PARTITION p4 VALUES LESS THAN (2004) ,
      PARTITION p12 VALUES LESS THAN (2012),
      PARTITION p13 VALUES LESS THAN MAXVALUE
);
		
		

50.3.2. LIST

				
CREATE TABLE client_firms (
    id   INT,
    name VARCHAR(35)
)
PARTITION BY LIST (id) (
    PARTITION r0 VALUES IN (1, 5, 9, 13, 17, 21),
    PARTITION r1 VALUES IN (2, 6, 10, 14, 18, 22),
    PARTITION r2 VALUES IN (3, 7, 11, 15, 19, 23),
    PARTITION r3 VALUES IN (4, 8, 12, 16, 20, 24)
);
				
		

				
CREATE TABLE lc (
    a INT NULL,
    b INT NULL
)
PARTITION BY LIST COLUMNS(a,b) (
    PARTITION p0 VALUES IN( (0,0), (NULL,NULL) ),
    PARTITION p1 VALUES IN( (0,1), (0,2), (0,3), (1,1), (1,2) ),
    PARTITION p2 VALUES IN( (1,0), (2,0), (2,1), (3,0), (3,1) ),
    PARTITION p3 VALUES IN( (1,3), (2,2), (2,3), (3,2), (3,3) )
);
				
		

				
CREATE TABLE th (id INT, name VARCHAR(30), adate DATE)
PARTITION BY LIST(YEAR(adate))
(
  PARTITION p1999 VALUES IN (1995, 1999, 2003)
    DATA DIRECTORY = '/var/appdata/95/data'
    INDEX DIRECTORY = '/var/appdata/95/idx',
  PARTITION p2000 VALUES IN (1996, 2000, 2004)
    DATA DIRECTORY = '/var/appdata/96/data'
    INDEX DIRECTORY = '/var/appdata/96/idx',
  PARTITION p2001 VALUES IN (1997, 2001, 2005)
    DATA DIRECTORY = '/var/appdata/97/data'
    INDEX DIRECTORY = '/var/appdata/97/idx',
  PARTITION p2000 VALUES IN (1998, 2002, 2006)
    DATA DIRECTORY = '/var/appdata/98/data'
    INDEX DIRECTORY = '/var/appdata/98/idx'
);
				
		

50.3.3. HASH

		
CREATE TABLE `test` (
  `userid` int(10) unsigned NOT NULL auto_increment,
  `username` int(10) unsigned NOT NULL DEFAULT '0',
  `password` int(10) unsigned NOT NULL DEFAULT '0',

  primary key (`userid`),
  KEY `userid` (`username`)
) ENGINE=InnoDB
PARTITION BY HASH(userid)
PARTITIONS 8;
		
		

使用HASH (year(created)) 替代 RANGE(year(created))

		
CREATE TABLE stuff (
	id INT AUTO_INCREMENT,
	name varchar(50),
	password varchar(50),
	created DATE,
	PRIMARY KEY (id, created)
)
PARTITION BY RANGE(year(created)) (
	PARTITION p0 VALUES LESS THAN (2010),
	PARTITION p1 VALUES LESS THAN (2012),
	PARTITION p2 VALUES LESS THAN MAXVALUE
);

更好的方法

CREATE TABLE stuff (
	id INT AUTO_INCREMENT,
	name varchar(50),
	password varchar(50),
	created DATE,
	PRIMARY KEY (id, created)
)
PARTITION BY HASH (year(created)) PARTITIONS 10;

我们演示一下

mysql> CREATE TABLE stuff (
    -> id INT AUTO_INCREMENT,
    -> name varchar(50),
    -> password varchar(50),
    -> created DATE,
    -> PRIMARY KEY (id, created)
    -> )
    -> PARTITION BY HASH (year(created)) PARTITIONS 10;
Query OK, 0 rows affected (0.08 sec)


mysql> insert into stuff (name,password,created) values('neo','test','2010-10-1');
Query OK, 1 row affected (0.06 sec)

mysql> insert into stuff (name,password,created) values('neo1','test','2012-2-1');
Query OK, 1 row affected (0.00 sec)

mysql> insert into stuff (name,password,created) values('neo2','test','2012-3-5');
Query OK, 1 row affected (0.00 sec)

mysql> insert into stuff (name,password,created) values('neo4','test','2011-1-5');
Query OK, 1 row affected (0.00 sec)

mysql> SELECT
    ->   partition_name part,
    ->   partition_expression expr,
    ->   partition_description descr,
    ->   table_rows
    -> FROM
    ->   INFORMATION_SCHEMA.partitions
    -> WHERE
    ->   TABLE_SCHEMA = schema()
    ->   AND TABLE_NAME='stuff';
+------+---------------+-------+------------+
| part | expr          | descr | table_rows |
+------+---------------+-------+------------+
| p0   | year(created) | NULL  |          1 |
| p1   | year(created) | NULL  |          1 |
| p2   | year(created) | NULL  |          2 |
| p3   | year(created) | NULL  |          0 |
| p4   | year(created) | NULL  |          0 |
| p5   | year(created) | NULL  |          0 |
| p6   | year(created) | NULL  |          0 |
| p7   | year(created) | NULL  |          0 |
| p8   | year(created) | NULL  |          0 |
| p9   | year(created) | NULL  |          0 |
+------+---------------+-------+------------+
10 rows in set (0.02 sec)

mysql> EXPLAIN PARTITIONS SELECT * FROM stuff WHERE created='2011-01-05'\G
*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: stuff
   partitions: p1
         type: system
possible_keys: NULL
          key: NULL
      key_len: NULL
          ref: NULL
         rows: 1
        Extra:
1 row in set (0.08 sec)

mysql> EXPLAIN PARTITIONS SELECT * FROM stuff WHERE created='2012-03-05'\G
*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: stuff
   partitions: p2
         type: ALL
possible_keys: NULL
          key: NULL
      key_len: NULL
          ref: NULL
         rows: 2
        Extra: Using where
1 row in set (0.00 sec)

		
		

50.3.3.1. LINEAR HASH

CREATE TABLE employees (
    id INT NOT NULL,
    fname VARCHAR(30),
    lname VARCHAR(30),
    hired DATE NOT NULL DEFAULT '1970-01-01',
    separated DATE NOT NULL DEFAULT '9999-12-31',
    job_code INT,
    store_id INT
)
PARTITION BY LINEAR HASH( YEAR(hired) )
PARTITIONS 4;
			

50.3.4. KEY分区

按照KEY进行分区类似于按照HASH分区,除了HASH分区使用的用户定义的表达式,而KEY分区的 哈希函数是由MySQL 服务器提供。MySQL 簇(Cluster)使用函数MD5()来实现KEY分区;

CREATE TABLE tk (
    col1 INT NOT NULL,
    col2 CHAR(5),
    col3 DATE
)
PARTITION BY LINEAR KEY (col1)
PARTITIONS 3;
		

50.3.5. Subpartitioning

CREATE TABLE ts (id INT, purchased DATE)
    PARTITION BY RANGE( YEAR(purchased) )
    SUBPARTITION BY HASH( TO_DAYS(purchased) )
    SUBPARTITIONS 2 (
        PARTITION p0 VALUES LESS THAN (1990),
        PARTITION p1 VALUES LESS THAN (2000),
        PARTITION p2 VALUES LESS THAN MAXVALUE
    );

CREATE TABLE ts1 (id INT, purchased DATE)
    PARTITION BY RANGE( YEAR(purchased) )
    SUBPARTITION BY HASH( MONTH(purchased) )
    SUBPARTITIONS 2 (
        PARTITION p0 VALUES LESS THAN (1990),
        PARTITION p1 VALUES LESS THAN (2000),
        PARTITION p2 VALUES LESS THAN MAXVALUE
    );
		

50.3.6. 分区管理

50.3.6.1. 新增分区

mysql 5.5+

为已经存在表添加分区

ALTER TABLE tbl_name  ADD PARTITION PARTITIONS 6;
			

新增 RANGE分区

ALTER TABLE category ADD PARTITION (PARTITION p4 VALUES IN (100,200,300,400)
                    DATA DIRECTORY = '/data/category'
                    INDEX DIRECTORY = '/data/category');
			

新增 LIST分区

			
CREATE TABLE expenses (
  expense_date DATE NOT NULL,
  category VARCHAR(30),
  amount DECIMAL (10,3)
);

ALTER TABLE expenses
PARTITION BY LIST COLUMNS (category)
(
  PARTITION p01 VALUES IN ( 'lodging', 'food'),
  PARTITION p02 VALUES IN ( 'flights', 'ground transportation'),
  PARTITION p03 VALUES IN ( 'leisure', 'customer entertainment'),
  PARTITION p04 VALUES IN ( 'communications'),
  PARTITION p05 VALUES IN ( 'fees')
);
			
			

新增 HASH分区

CREATE TABLE t1 (
    id INT,
    year_col INT
);

ALTER TABLE t1
    PARTITION BY HASH(id)
    PARTITIONS 8;
			
			
/* 在MySQL 5.1中*/
CREATE TABLE t2
(
  dt DATE
)
PARTITION BY RANGE (TO_DAYS(dt))
(
  PARTITION p01 VALUES LESS THAN (TO_DAYS('2007-01-01')),
  PARTITION p02 VALUES LESS THAN (TO_DAYS('2008-01-01')),
  PARTITION p03 VALUES LESS THAN (TO_DAYS('2009-01-01')),
  PARTITION p04 VALUES LESS THAN (MAXVALUE));

SHOW CREATE TABLE t2 \G
*************************** 1. row ***************************
       Table: t2
Create Table: CREATE TABLE `t2` (
  `dt` date DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
/*!50100 PARTITION BY RANGE (TO_DAYS(dt))
(PARTITION p01 VALUES LESS THAN (733042) ENGINE = MyISAM,
 PARTITION p02 VALUES LESS THAN (733407) ENGINE = MyISAM,
 PARTITION p03 VALUES LESS THAN (733773) ENGINE = MyISAM,
 PARTITION p04 VALUES LESS THAN MAXVALUE ENGINE = MyISAM) */



 /*在MySQL 5.5中*/
CREATE TABLE t2
(
  dt DATE
)
PARTITION BY RANGE COLUMNS (dt)
(
  PARTITION p01 VALUES LESS THAN ('2007-01-01'),
  PARTITION p02 VALUES LESS THAN ('2008-01-01'),
  PARTITION p03 VALUES LESS THAN ('2009-01-01'),
  PARTITION p04 VALUES LESS THAN (MAXVALUE));

SHOW CREATE TABLE t2 \G
*************************** 1. row ***************************
       Table: t2
Create Table: CREATE TABLE `t2` (
  `dt` date DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
/*!50500 PARTITION BY RANGE  COLUMNS(dt)
(PARTITION p01 VALUES LESS THAN ('2007-01-01') ENGINE = MyISAM,
 PARTITION p02 VALUES LESS THAN ('2008-01-01') ENGINE = MyISAM,
 PARTITION p03 VALUES LESS THAN ('2009-01-01') ENGINE = MyISAM,
 PARTITION p04 VALUES LESS THAN (MAXVALUE) ENGINE = MyISAM) */
			
			

50.3.6.2. 删除分区

删除分区 p0

ALERT TABLE users DROP PARTITION p0;
			

50.3.6.3. 重建分区

使用 REORGANIZE 重建分区。

RANGE 分区重建
ALTER TABLE users REORGANIZE PARTITION p0,p1 INTO (PARTITION p0 VALUES LESS THAN (6000000));

将原来的 p0,p1 分区合并起来,放到新的 p0 分区中。

LIST 分区重建
ALTER TABLE users REORGANIZE PARTITION p0,p1 INTO (PARTITION p0 VALUES IN(0,1,4,5,8,9,12,13));
将原来的 p0,p1 分区合并起来,放到新的 p0 分区中。

HASH/KEY 分区重建
ALTER TABLE users REORGANIZE PARTITION COALESCE PARTITION 2;
分区的数量改为2,
注意:在这里数量只能减少不能增加。想要增加可以用 ADD PARTITION 方法
			

调整HASH/KEY分区数量,将分区总数扩展到8个。

ALTER TABLE users ADD PARTITION PARTITIONS 8;
			

50.3.6.4. 分区维护

重建分区: 这和先删除保存在分区中的所有记录,然后重新插入它们,具有同样的效果。它可用于整理分区碎片。

示例:

ALTER TABLE t1 REBUILD PARTITION (p0, p1);
·         优化分区:如果从分区中删除了大量的行,或者对一个带有可变长度的行(也就是说,有VARCHAR,BLOB,或TEXT类型的列)作了许多修改,可以使用“ALTER TABLE ... OPTIMIZE PARTITION”来收回没有使用的空间,并整理分区数据文件的碎片。

示例:

ALTER TABLE t1 OPTIMIZE PARTITION (p0, p1);
在一个给定的分区表上使用“OPTIMIZE PARTITION”等同于在那个分区上运行CHECK PARTITION,ANALYZE PARTITION,和REPAIR PARTITION。

·         分析分区:读取并保存分区的键分布。

示例:

ALTER TABLE t1 ANALYZE PARTITION (p3);
·         修补分区: 修补被破坏的分区。

示例:

ALTER TABLE t1 REPAIR PARTITION (p0,p1);
·         检查分区: 可以使用几乎与对非分区表使用CHECK TABLE 相同的方式检查分区。

示例:

ALTER TABLE trb3 CHECK PARTITION (p1);
			

50.3.7. EXPLAIN PARTITIONS

EXPLAIN PARTITIONS

		
mysql> EXPLAIN PARTITIONS SELECT * FROM users\G
*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: users
   partitions: p0,p1,p2,p3,p4,p5,p6
         type: ALL
possible_keys: NULL
          key: NULL
      key_len: NULL
          ref: NULL
         rows: 7
        Extra:
1 row in set (0.03 sec)

mysql> EXPLAIN PARTITIONS SELECT * FROM users WHERE id < 5\G
*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: users
   partitions: p0,p1,p2,p3,p4,p5,p6
         type: range
possible_keys: PRIMARY
          key: PRIMARY
      key_len: 4
          ref: NULL
         rows: 7
        Extra: Using where
1 row in set (0.00 sec)
		
		

50.3.8. SHOW CREATE TABLE

SHOW CREATE TABLE

		
mysql> SHOW CREATE TABLE users\G
*************************** 1. row ***************************
       Table: users
Create Table: CREATE TABLE `users` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `username` varchar(20) NOT NULL DEFAULT '',
  `birthday` datetime DEFAULT NULL,
  PRIMARY KEY (`id`,`username`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=latin1
/*!50100 PARTITION BY KEY (id,username)
PARTITIONS 7 */
1 row in set (0.00 sec)

		
		

50.3.9. INFORMATION_SCHEMA.partitions 表

		
SELECT
  partition_name part,
  partition_expression expr,
  partition_description descr,
  table_rows
FROM
  INFORMATION_SCHEMA.partitions
WHERE
  TABLE_SCHEMA = schema()
  AND TABLE_NAME='employees';
		
		
		
select
  partition_name part,
  partition_expression expr,
  from_seconds(partition_description) descr,
  table_rows
FROM
INFORMATION_SCHEMA.partitions
WHERE
    TABLE_SCHEMA = 'test'
    AND TABLE_NAME='t2';
		
		

50.3.10. 分区数据操作

指定分区查询

SELECT * FROM employees PARTITION (p0, p2);

SELECT count(1) FROM employees PARTITION (p0);
SELECT count(1) FROM employees PARTITION (p0, p2);
SELECT count(1) FROM employees PARTITION (p0, p2, p1);
		

删除分区中的记录

DELETE FROM employees PARTITION (p0, p1);		
		

更新指定分区

UPDATE employees PARTITION (p0) SET store_id = 2 WHERE fname = 'Jill';		
		

指定分区连表查询

SELECT e.id, s.city FROM employees AS e JOIN stores PARTITION (p1) AS s ...;		
		

将某个表迁移到分区上

ALTER TABLE employees EXCHANGE PARTITION p0 WITH TABLE employees2;		
		

原文出处:Netkiller 系列 手札
本文作者:陈景峯
转载请与作者联系,同时请务必标明文章原始出处和作者信息及本声明。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/107780.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • phpstorm激活码永久[最新免费获取]2022.02.11「建议收藏」

    (phpstorm激活码永久)最近有小伙伴私信我,问我这边有没有免费的intellijIdea的激活码,然后我将全栈君台教程分享给他了。激活成功之后他一直表示感谢,哈哈~IntelliJ2021最新激活注册码,破解教程可免费永久激活,亲测有效,下面是详细链接哦~https://javaforall.net/100143.html4K…

    2022年4月1日
    531
  • Python 引用全局变量提示:local variable referenced before assignment. 问题解决办法,global使用方法介绍

    Python 引用全局变量提示:local variable referenced before assignment. 问题解决办法,global使用方法介绍Python技术篇-引用全局变量提示:localvariablereferencedbeforeassignment.问题解决办法。可能的情况一般有两种:情况一:变量没有被赋值直接引用了。情况二:函数引用全局变量的时候没有声明。就是说函数里想引用全局变量的话,函数前面要告诉函数这个变量是全局的,不然默认就是函数里能使用的局部变量。

    2025年6月13日
    3
  • 全面认识基站_移动基站设备认识

    全面认识基站_移动基站设备认识文章目录一、全面认识基站1.1基站的定义1.2基站的分类1.3基站的组成一、全面认识基站1.1基站的定义基站(BaseStation),即公用移动通信基站,实现了有线通信网络与无线终端之间的无线信号传输,是无线终端(如手机)接入互联网的接口设备。1.2基站的分类基站按照站型大小和功率可以大致分为:宏基站、微基站、皮基站、飞基站。宏基站主要用于室外覆盖,体型大、覆盖面积广。微基站通常指在楼宇中或人口密集区安装的小型基站。这种基站的体积小、覆盖面积小,承载的用户量比较低。皮基

    2025年7月21日
    4
  • 记忆化搜索(Memory Search)

    记忆化搜索(Memory Search)Question输入n,符合要求的序列为:第一个数为n,第二个数不大于n,从第三个数起小于前两个数的差的绝对值,后面以此类推。求有多少种序列?(数据:n最大为1000)Sampleinput:4/output:7input:5/output:14input:6/output:26Hintn为4时有如下序列:4142434441141242…

    2022年7月26日
    12
  • t-io文档_如何区别服务端与客户端

    t-io文档_如何区别服务端与客户端<dependency><groupId>org.t-io</groupId><artifactId>tio-core</artifactId><version>3.7.4.v20210808-RELEASE</version></dependency>总共五个类。数据模型Packet、客户端处理器、客户端监听器.

    2022年10月2日
    2
  • 成熟的男人喜欢什么样的女性?

    成熟的男人喜欢什么样的女性?很多人以为男人不管是18还是88,都喜欢18的女孩子。其实错了,准确来说是片面了。就我自己和身边朋友的观察,大多数真正成熟的男性,更喜欢的是性格的契合,而不单是你的身高、三围、和精致的脸。具体说说吧,但仅代表我自己。1、能独立自主的女性最有吸引力。男人的征服欲仿佛是带在基因里的,特别是成熟的男人。傻白甜人设,在成熟男人那里,真的不太有优势。他们更喜欢的是“势均力敌”的较量,而不是给小迷妹当人生启蒙老师。事业独立、生活独立的女性,更受男人的欢迎。大多数成年人的世界里,感情与性,是生活的调味品,而不是必需品

    2022年7月25日
    7

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号