1)MyISAM存储引擎(不推荐使用)
特点:
设计理念:
2)InnoDB存储引擎 特点:
设计理念:
InnoDB
and NDB
storage engines do.
MySQL 5.7及以上版本中MyISAM引擎已经不支持数据库分区了,所以今早抛弃MyISAM吧已经基于行级锁的话,就没有办法从软件层面提升并发度了,否则会事务冲突。所以思路:行级锁、物理层面提升。
适用场景:大部分的读操作对数据的实时性要求并没有那么高,一般对时延的容忍在秒级以上 读写分离的本质:用硬件资源和带宽换性能。
数据库分区和分表对比:
数据库分库(物理层面进行拆分):
总的来说:优先考虑分区。当分区不能满足需求时,开始考虑分表,合理的分表对效率的提升会优于分区。
它是一种物理数据库设计技术,MySQL数据库默认使用水平分区。
分区类型:
其中最常用的是range和list分区
注意:无论哪种分区,要么你分区表上没有主键/唯一键,要么分区表的主键/唯一键都必须包含分区键, 也就是说不能使用主键/唯一键字段之外的其它字段分区
我们在分区表、单库分表和分库分表三种方案之间进行对比如下(需要说明的是分库分表包括单库分表和分库分表):
P.K. | 分区表 | 单库分表 | 分库分表 |
---|---|---|---|
连接数 | 单库限制 | 单库限制 | 无限制 |
存储能力 | 8192个分区 | 单库限制 | 无限制 |
不走分片键 | 全表锁 | 自研or中间件 | 自研or中间件 |
走分片键 | 性能高 | 性能高 | 性能高 |
并发能力 | 一般 | 一般 | 高 |
运维成本 | 低 | 高 | 很高 |
开发成本 | 低 | 高 | 很高 |
事务 | 本地事务 | 本地事务+分布式事务 | 本地事务+分布式事务 |
通过分区表、单库分表和分库分表三种方案的对比我们发现,单库分表相比分区表完全没有任何优势,它们都会受到单个数据库实例引发的连接数、存储能力、并发能力等的限制。单库分表相对于分区表甚至还会引入一些不必要的麻烦,例如跨分片键的操作,即使这种操作频率很低,但是只要有需求就需要自研或者引入第三方中间件,从而大大增加开发成本和维护成本。而分区表应对这类操作则不需要任何代价,甚至还可以通过引入一个从库给这些系统使用从而防止对核心主库的影响。
分区表和单库分表的并发能力有限,很多宝贵的资源都受到单个实例和服务器的限制,这才是一线互联网公司核心数据不使用分区表的主要原因。例如美团外卖订单表,淘宝订单表等,这些业务都有相同的特点:高并发、海量数据,所以只能选分库分表。所以那些高并发,海量数据场景下才会碰到的问题,例如冷热数据分离,数据归档,扩容等,就不在PK范围之内了。
但是为什么我还是要为分区表正名呢?因为满足高并发、海量数据的大表毕竟是小数公司。很多公司的很多业务表,虽然整个生命周期内也会有几亿,甚至上十亿,但是并不会有高并发的可能,这种业务表就非常适合分区表!毕竟分区表能够满足我们需求的情况下,它的开发成本和维护成本要比分库分表小很多呀!
分区总结
MySQL的分区发展这么多年,从来没见过官方有要将其抛弃的想法。这是因为,在很多特定业务场景下,它的便捷性和对性能的提升是显而易见的。
如果你的业务满足如下的特点,可以大胆尝试使用分区表:
很多业务非常适合使用分区表,这类大表生命周期内的上限是绝对可以预估在10亿量级以下的,即使这些表将来超过10亿,那起码也是若干年以后的事情。一个方案能抗3~5年那绝对是一个优秀的方案,如果能抗10年,那对于现阶段来说,绝对是一个完美的方案了。
mysql 不禁止在分区键值上使用 null , 分区键可能是一个字段或者一个用户定义的额表达式。一般情况下,mysql 的分区把 null 当作零值,或者一个最小值进行处理。
-- range添加新分区
alter table <table> add partition(
partition p4 values less than MAXVALUE
);
-- list添加新分区
alter table <table> add partition(
partition p4 values in (25,26,28)
);
-- hash重新分区
alter table <table> add partition partitions 4;
-- key重新分区
alter table <table> add partition partitions 4;
-- range重新分区
ALTER TABLE user REORGANIZE PARTITION p0,p1,p2,p3,p4 INTO (
PARTITION p0 VALUES LESS THAN MAXVALUE
);
-- list重新分区
ALTER TABLE <table> REORGANIZE PARTITION p0,p1,p2,p3,p4 INTO (
PARTITION p0 VALUES in (1,2,3,4,5)
);
-- 删除分区不删除数据
alter table <table> remove partitioning;
-- 删除list或者range分区(同时删除分区对应的数据)
alter table <table> drop partition <分区名称>;
删除表的所有分区: 不会丢失数据
ALTER TABLE t_question remove partitioning;
删除分区: 丢失数据 不可以删除hash或者key分区。
alter table emp drop partition p1;
一次性删除多个分区 丢失数据
alter table emp drop partition p1,p2;
增加分区:
alter table emp add partition (partition p3 values less than (4000));
alter table empl add partition (partition p3 values in (40));
分解分区: Reorganizepartition关键字可以对表的部分分区或全部分区进行修改,并且不会丢失数据。分解前后分区的整体范围应该一致。 不会丢失数据
alter table te
reorganize partition p1 into
(
partition p1 values less than (100),
partition p3 values less than (1000)
);
合并分区: Merge分区:把2个分区合并为一个。 不会丢失数据
alter table te
reorganize partition p1,p3 into
(
partition p1 values less than (1000)
);
重新定义hash分区表: 不会丢失数据
Alter table emp partition by hash(salary) partitions 7;
重新定义range分区表: 不会丢失数据
Alter table emp partition by range(salary)
(
partition p1 values less than (2000),
partition p2 values less than (4000)
);
重建分区: 这和先删除保存在分区中的所有记录,然后重新插入它们,具有同样的效果。它可用于整理分区碎片。
ALTER TABLE emp rebuild partitionp1,p2;
优化分区:
如果从分区中删除了大量的行,或者对一个带有可变长度的行(也就是说,有VARCHAR,BLOB,或TEXT类型的列)作了许多修改,可以使用“ALTER TABLE … OPTIMIZE PARTITION”来收回没有使用的空间,并整理分区数据文件的碎片。
ALTER TABLE emp optimize partition p1,p2;
分析分区: 读取并保存分区的键分布。
ALTER TABLE emp analyze partition p1,p2;
修补分区: 修补被破坏的分区。
ALTER TABLE emp repairpartition p1,p2;
检查分区:
可以使用几乎与对非分区表使用CHECK TABLE 相同的方式检查分区。 这个命令可以告诉你表emp的分区p1,p2中的数据或索引是否已经被破坏。如果发生了这种情况,使用“ALTER TABLE … REPAIR PARTITION”来修补该分区。
ALTER TABLE emp CHECK partition p1,p2;
相关查询
-- 跨分区查询
select sum(t.num) from
(
select count(*) num from t_question PARTITION (p0)
union all
select count(*) num from t_question PARTITION (p1)
) t;
-- 查询表上有多少分区
SELECT PARTITION_NAME,PARTITION_DESCRIPTION,PARTITION_METHOD,TABLE_ROWS,CREATE_TIME
FROM information_schema.PARTITIONS
WHERE TABLE_SCHEMA = 'db_name' AND TABLE_NAME = 'player_log'
ORDER BY partition_description DESC;
-- 删除分区表一个分区的数据
alter table table_name truncate partition p5;
在做分区表时,选择分区的依据字段时要谨慎,需要仔细斟酌这个字段拿来做为分区依据是否合适,这个字段加入到主键中做为复合主键是否适合。
使用range分区时表结构要么没有主键,要么分区字段必须是主键。
可以使用PRIMARY KEY (id
,xxx
)来将多个字段作为主键。
-- 创建分区表
CREATE TABLE `mytable` (
`id` int(11) NOT NULL ,
`username` varchar(255) DEFAULT NULL,
`email` varchar(20) DEFAULT NULL,
`age` tinyint(4) DEFAULT NULL,
`type` int(11) DEFAULT NULL,
`create_time` datetime DEFAULT CURRENT_TIMESTAMP
PRIMARY KEY (`id`,`age`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8
PARTITION BY RANGE (age) (
PARTITION p0 VALUES LESS THAN (20),
PARTITION p1 VALUES LESS THAN (40),
PARTITION p2 VALUES LESS THAN (60),
PARTITION p3 VALUES LESS THAN (80),
PARTITION p4 VALUES LESS THAN MAXVALUE
);
更新原有表
alter table results partition by RANGE (month(ttime))
(
PARTITION p0 VALUES LESS THAN (1),
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 (13)
);
-- 语法
create table `mytable` (
`id` int(11) NOT NULL ,
`username` varchar(255) DEFAULT NULL,
`email` varchar(20) DEFAULT NULL,
`age` tinyint(4) DEFAULT NULL,
`type` int(11) DEFAULT NULL,
`create_time` datetime DEFAULT CURRENT_TIMESTAMP
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8
partition by LIST (type) (
partition p0 values IN (0,1, 2),
partition p1 values IN (3, 4)
);
更新原有表
alter table results partition by LIST (type)
(
partition p0 values IN (0,1, 2),
partition p1 values IN (3, 4)
);
比如试题表中的数据量太大 我根据状态进行分区
-- 状态-2已确定题型-1未提交0待审核1已审核2已退回10正在纠错处理12审核中 101docHtml有问题102:ctype值有问题
select status,count(*) num from t_question group by `status`;
alter table t_question partition by LIST (status)
(
partition p0 values IN (-2,-1),
partition p1 values IN (0),
partition p2 values IN (1),
partition p3 values IN (2),
partition p4 values IN (10,12),
partition p5 values IN (101,102),
partition p6 values IN (103)
);
HASH分区 的目的将数据按照某列进行hash计算后更加均匀的分散到各个分区。
相比,RANGE分区 和 LIST分区 来说,HASH分区不用明确指定一个给定的列值或者列值集合,只需要基于将要进行HASH分区的列指定一个列值或者表达式,以及指定分区表将要被分割成的分区数量。
定义HASH分区的语句为 PARTITION BY HASH(expr)
,其中 expr 是一个整型列(类型为MySQL整型的列)的列名或者返回一个整数的表达式。
如果没有显式添加 PARTITIONS 子句声明需要分割的分区数量,那么默认只会创建一个分区。
create table t_p_hash(
`name` varchar(50),
age int
)engine=innodb
partition by hash(age)
partitions 4;
因为分区是按照整型列或者整数表达式进行的,这个值本身是离散的,如果对于连续的值进行HASH分区,则可以较好地将数据进行平均分布,例如自增长的主键。
但是需要注意的是,根据自增长主键作HASH分区并不能保证数据就一定会分布均匀。因为在数据插入失败进行了回滚时,当前的自增长主键值依然是增加了的,并且下次插入数据时的主键将会在当前失败了的主键基础上递增。
MySQL数据库还支持 LINEAR HASH分区 ,这可以看做 HASH分区 的一个变种。LINEAR HASH 分区的语法与 HASH分区 的语法大体一致,但是其内部使用的是一个更加复杂的算法来确定新行写入到分区中的位置。
相对于 HASH分区 来说,LINEAR HASH分区 在增加、删除、合并、拆分分区方面更加快捷,有利于处理含有大量数据的表,但是各个分区间数据的分布可能不大均衡。
create table t_p_linearhash(
`name` varchar(50),
age int
)engine=innodb
partition by linear hash(age)
partitions 4;
常规hash和线性hash对比
常规hash是基于分区个数取模(%)运算。根据余数插入到指定的分区。打算分4个分区,根据id字段来分区。
怎么算出新插入一行数据,需要放到分区1,还是分区4呢? id的值除以4,余下1,这一行数据就分到1分区。
常规hash,可以让数据非常平均的分布每一个分区。比如分为4个取,取余数,余数总是0-3之间的值(总到这几个分区去)。分配打散比较均匀。
但是也是有缺点的:由于分区的规则在创建表的时候已经固定了,数据就已经打散到各个分区。现在如果需要新增分区、减少分区,运算规则变化了,原来已经入库的数据,就需要适应新的运算规则来做迁移。
实际上在分库分表的时候,使用hash方式,也是数据量迁移的问题。不过还好。
针对这个情况,增加了线性hash的方式。
线性HASH(LINEAR HASH)稍微不同点。
两者也有有相同的地方:
考虑以后迁移数据量少,使用线性hash。
KEY分区 和 HASH分区 十分相似,不同之处在于 HASH分区 使用用户定义的函数进行分区,KEY分区 使用MySQL数据库提供的函数进行分区。
例如 InnoDB存储引擎 就是使用内部的 哈希函数 来进行分区。
create table t_p_key(
`name` varchar(50),
create_time datetime
) engine=innodb
partition by key(create_time)
partitions 4;
KEY分区 也有类似于HASH分区那样的的 LINEAR KEY分区 ,所带来的效果也是一致的。
COLUMNS分区 可以看作是对 RANGE分区 和 LIST分区 的一种加强,可以直接使用非整型的数据进行分区;
分区根据类型直接比较而得,不需要转化为整数。
使用的语法为 RANGE COLUMNS (expr)
和 LIST COLUMNS (expr)
,表达式 expr 不再必须为整型。
值得一提的是, RANGE COLUMNS分区还可以对多个列的值进行分区。
例如直接根据 字符串类型 的列作分区
create table t_p_rangecolumns(
`name` VARCHAR(50)
)engine=innodb
partition by list columns (`name`)(
partition r1 values in ('张三', '王五'),
partition r2 values in ((李四', '赵六')
);
创建分区表后,查看明细能够看到分区的表达式为字符串类型的字段 name
再来看下 RANGE COLUMNS 对多列进行分区
create table t_p_rangecolumns(
`name` varchar(50),
age int
)engine=innodb
partition by range columns (`name`, age)(
partition r1 values less than ('张三', 21),
partition r2 values less than ((李四', 23),
partition r3 values less than ( (XVALUE, MAXVALUE)
)
COLUMNS分区支持的数据类型有以下几种
所有的整型类型,如 INT、SMALLINT、TINYINT、BIGINT。
浮点型的FLOAT和DECIMAL则不予支持
日期类型,仅包含 DATE 和 DATETIME
字符串类型,如 CHAR、VARCHAR、BINARY和VARBINARY。
不支持BLOB和TEXT类型
子分区(subpartition):是分区表中对每个分区的再次分割,又被称为复合分区,
支持对range和list进行子分区,子分区即可以使用hash分区也可以使用key分区。
复合分区适用于保存非常大量的数据记录。
-- 根据年进行分区
-- 再根据天数hash分区
-- 3个range分区(p0,p1,p2)又被进一步分成2个子分区,实际上整个分区被分成了 3 x 2 = 6个分区
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 p0 values less than (2000),
partition p0 values less than maxvalue
);
项目案例
alter table t_question partition by LIST (status)
subpartition by key(id) subpartitions 2
(
partition p0 values IN (-2,-1),
partition p1 values IN (0),
partition p2 values IN (1),
partition p3 values IN (2),
partition p4 values IN (10,12),
partition p5 values IN (101,102),
partition p6 values IN (103)
);
SELECT PARTITION_NAME,PARTITION_DESCRIPTION,PARTITION_METHOD,TABLE_ROWS,CREATE_TIME
FROM information_schema.PARTITIONS
WHERE TABLE_SCHEMA = 'xhkjedu_question' AND TABLE_NAME = 't_question'
ORDER BY partition_description DESC;
explain partitions
SELECT q.testid,q.handletime,q.docHtml,q.typeTextId,q.typeTextName,q.complexityText,q.count,q.sourcename,q.checkertime,q.scienceOrWord,q.subjectid
FROM t_testquestion_director d INNER JOIN t_question q
ON d.Testid=q.testid
where d.directorid =2586 and q.subjectid=68 and q.deleter=0 and q.status=1 and q.papertype != 13
order by q.checkertime desc
limit 0,10;
使用分区和分表一样的思想:尽量让数据均匀分散,这样达到分流、压力减小的效果。
如果不能均匀分布,某个分区的操作量特别大,出现单点瓶颈。
虽然4种类型的分区方式。
其实总共两大类,按范围分区和按hash运算分区。
以用户表为例子,如果要使用分区方案。改使用哪种分区类型呢? 用户编号不是自增的编号,如果使用范围来分区,各个分区的数据做不到均匀分布的。原因如下:
比如说用户编号为1-200000000的用户分配到p1分区,20000000-40000000分配到p2分区,40000000-60000000分配到p3区,这样类推下去。
由于用户编号不是自增,注册分配到的用户编号,可能是1到2千万之间的数字,也可能是4千万到6千万之间的一个数字。如果被分配到4千万到6千万的数字会更多,那么各个分区给到的数据是不均匀的。
故不好使用范围来分区。
比较好的办法是,使用hash取模,user_id%分区数。数据就可以分散均匀到4个分区去了。
今天主要介绍下面这几个错误:
主键必须包括表的分区函数中的所有列,一个惟一的索引必须包括表的分区函数中的所有列,是不是不太好理解意思
其实就是这么个意思:表上的每一个唯一性索引必须用于分区表的表达式上(其中包括主键索引)
下面我来举几个例子:
SQL
CREATE TABLE t1 (
id INT NOT NULL,
aid DATE NOT NULL,
bid INT NOT NULL,
PRIMARY KEY (id)
)
PARTITION BY KEY(bid)
PARTITIONS 10;
[Err] 1503 - A PRIMARY KEY must include all columns in the table’s partitioning function
SQL
CREATE TABLE t1 (
id INT NOT NULL,
aid DATE NOT NULL,
bid INT NOT NULL,
UNIQUE KEY (id)
)
PARTITION BY KEY(bid)
PARTITIONS 10;
[Err] 1503 - A PRIMARY KEY must include all columns in the table’s partitioning function
SQL
CREATE TABLE t1 (
id INT NOT NULL,
aid DATE NOT NULL,
bid INT NOT NULL,
PRIMARY KEY (id,bid)
)
PARTITION BY KEY(bid)
PARTITIONS 10;
Query OK, 0 rows affected (0.535 sec)
SQL
CREATE TABLE t1 (
id INT NOT NULL,
aid DATE NOT NULL,
bid INT NOT NULL,
UNIQUE KEY (id,bid)
)
PARTITION BY KEY(bid)
PARTITIONS 10;
Query OK, 0 rows affected (0.625 sec)
这一组例子说明了如果要用bid作为分区key,则bid至少要包含在主键或者唯一键。
再来看一组例子:
SQL
CREATE TABLE t1 (
id INT NOT NULL,
aid DATE NOT NULL,
bid INT NOT NULL,
PRIMARY KEY (id,aid),
UNIQUE KEY (bid)
)
PARTITION BY KEY(bid)
PARTITIONS 10;
[Err] 1503 - A PRIMARY KEY must include all columns in the table’s partitioning function
SQL
CREATE TABLE t1 (
id INT NOT NULL,
aid DATE NOT NULL,
bid INT NOT NULL,
PRIMARY KEY (id,aid),
UNIQUE KEY (bid)
)
PARTITION BY KEY(aid)
PARTITIONS 10;
[Err] 1503 - A PRIMARY KEY must include all columns in the table’s partitioning function
这2个分区表是无法建立的,因为没有一个分区键,可以同时属于两个唯一性索引的键。
下面再来看一组例子:
SQL
CREATE TABLE t1 (
id INT NOT NULL,
aid DATE NOT NULL,
bid INT NOT NULL,
PRIMARY KEY (id,aid,bid)
)
PARTITION BY KEY(bid)
PARTITIONS 10;
Query OK, 0 rows affected (0.475 sec)
SQL
CREATE TABLE t1 (
id INT NOT NULL,
aid DATE NOT NULL,
bid INT NOT NULL,
UNIQUE KEY (id,aid,bid)
)
PARTITION BY KEY(bid)
PARTITIONS 10;
Query OK, 0 rows affected (0.532 sec)
SQL
CREATE TABLE t1 (
id INT NOT NULL,
aid DATE NOT NULL,
bid INT NOT NULL,
PRIMARY KEY (id,aid,bid),
UNIQUE KEY (bid)
)
PARTITION BY KEY(bid)
PARTITIONS 10;
Query OK, 0 rows affected (0.526 sec)
这三个都建立分区表成功了,因为bid同时属于一个或以上的唯一性索引的键
1、分区数量并非越多越好
分区表本身有一定的限制,单张表最多是只能有1024个分区的。另一方面,在对分区表进行查询时服务器需要扫描所有分区定义的列表来找到正确的分区,类似这样的线性搜索的效率不高,所以随着分区数的增长,成本会越来越高。
2、查询不能根据表达式来过滤分区
MySQL只能在使用分区函数列本身进行比较时才能过滤分区,而不能根据表达式的值去过滤分区,即便这个表达式就是分区函数也不行。
例如使用 year( create_time) 进行查询,实际上便扫描了所有的分区
explain partitions
select * from t_p_test where year(create_time) = '2017';
3、NULL值会使分区过滤无效
MySQL数据库允许对NULL值做分区,但是MySQL数据库的分区总是视NULL值小于任何一个非NULL值,不同分区对NULL值的处理也各不相同。
RANGE分区 会将NULL值放入最左边边的分区中, LIST分区 下使用NULL值则必须显式地指出在哪个分区存放,而 HASH分区 和 KEY分区 会将含有NULL值的记录返回为0。
4、分区列必须是唯一索引的一个组成部分
不论创建何种类型的分区,如果建表时没有指定主键、唯一索引,那么可以指定任何一个列为分区列。 但是当表中有主键或者唯一索引时,分区列就必须包含所有主键列和唯一索引列的一个组成部分。另外,分区表中无法使用外键约束。
例如创建表 t_p_test ,指定字段 id 为主键,但是定义分区时使用的是普通的整型列 age
create table t_p_test(
id bigint primary key not null auto_increment,
`name` varchar(50),
age int
)engine=innodb
partition by range( age)(
partition p1 values less than ( 20),
partition p2 values less than ( 30),
partition p3 values less than ( MAXVALUE)
);
此时显然是无法成功进行分区的,执行语句后将会得到错误提示
Error Code: 1503. A PRIMARY KEY must include all columns in the table’s partitioning function
如果将分区列改为主键列,则能正常进行分区
create table t_p_test(
id bigint primary key not null auto_increment,
`name` varchar(50),
age int
)engine=innodb
partition by range( id)(
partition p1 values less than (20),
partition p2 values less than (30),
partition p3 values less than (MAXVALUE)
);
需要注意的是,在包含唯一索引的表中进行分区,分区列只要求是唯一索引的一个组成部分,不需要整个唯一索引列都是分区列。
例如在表 t_p_test 中存在一个由id、age组成的唯一索引(该表中没有主键),那么在进行分区时可以只使用 id 或者 age 作分区列
create table t_p_test(
id bigint not null auto_increment,
`name` varchar(50),
age int,
unique index iname( id, age)
)engine=innodb
partition by range( age)(
partition p1 values less than ( 20),
partition p2 values less than ( 30),
partition p3 values less than ( MAXVALUE)
);
5、索引列和分区列不匹配会导致查询无法过滤分区
正如先前所说,MySQL数据库支持的分区为局部分区,索引是按照分区子表定义的,也就是说每个分区的索引相互独立。当索引列并非分区列时,对索引列进行扫描势必也就需要扫描全部分区。
这里创建分区表,在 name 列上建立索引,同时使用 age 列进行分区
create table t_p_test(
name varchar(50) not null,
age int,
index i_uname(name)
)partition by range columns( age)(
partition p1 values less than ( 18),
partition p2 values less than (30),
partition p3 values less than (50),
partition p4 values less than (maxvalue)
);
insert into t_p_test( name, age) values( '张三', 19), ( '李四', 29), ( '王五', 22), ( '赵六', 14), ( '田七', 71);
分析查询执行计划,能够看到使用 name 字段进行等值查询时使用了索引,但是却扫描了所有的分区
explain partitions
select * from t_p_test where name = '张三';
应该尽量避免建立和分区列不匹配的索引,除非查询中还同时包含了可以过滤分区的条件,这一点在多表关联时尤为重要。
6、维护分区的成本可能会很高
新增或者删除分区很快,但并不代表着对分区的维护操作总是很快。在对分区进重组时(更新分区操作),需要创建临时表,然后将数据复制到临时表中,最后再删除原分区;这个操作可能会带来很高的维护成本,特别是在有较为庞大的数据量的情况下。