第四十三讲 分区表

70 阅读3分钟

分区表

语法

CREATE TABLE `t` (.....)ENGINE=InnoDB DEFAULT CHARSET=utfmb64
PARTITION BY RANGE (YEAR(ftime)) 
(PARTITION p_2017 VALUES LESS THAN (2017) ENGINE = InnoDB,.....);

创建完成后这个表包含了一个.frm文件和4个.ibd文件,每个分区对应一个.ibd文件。

  • 分区表对于引擎层来说,这是N个表;所以在所的纬度是以单个分表为维度
    (比方说间隙锁 2018-02-01在插入的时候锁住部分是2017这张表到无限大的间隙,因此,只会堵住在这个分区上执行的查询,落到其他分区的查询是不受影响的。)
  • 分区表对于Server层来说,是1个表。

手工分表和分区表

分区表和手工分表,一个是由server层来决定使用哪个分区,一个是由应用层代码来决定使用哪个分表。从引擎层看,这两种方式也是没有差别的。

区别主要是在server层上。从server层看,我们就不得不提到分区表一个被广为诟病的问题:打开表的行为。

分区表跟用户分表比起来,有两个绕不开的问题:一个是第一次访问的时候需要访问所有分区,另一个是共用MDL锁。如果要使用分区表,就不要创建太多的分区。

分区并不是越细越好。实际上,单表或者单分区的数据一千万行,只要没有特别大的索引,对于现在的硬件能力来说都已经是小表了。

分区策略

  • MySQL在第一次打开分区表的时候,需要访问所有的分区;

  • 在server层,认为这是同一张表,因此所有分区共用同一个MDL锁;

  • 在引擎层,认为这是不同的表,因此MDL锁之后的执行过程,会根据分区表规则,只访问必要的分区。
    (必要的分区”的判断,就是根据SQL语句中的where条件,结合分区规则来实现的。如果查询语句的where条件中没有分区key,那就只能访问所有分区了。)

分区策略:

一个典型的报错情况是这样的:如果一个分区表的分区很多,比如超过了1000个,而MySQL启动的时候,open_files_limit参数使用的是默认值1024,那么就会在访问这个表的时候,由于需要打开所有的文件,导致打开表文件的个数超过了上限而报错。

通用分区策略

MyISAM分区表使用的分区策略,我们称为通用分区策略(generic partitioning),每次访问分区都由server层控制。(刚开始支持分区表的代码,性能非常不好)

MySQL从5.7.17开始,将MyISAM分区表标记为即将弃用(deprecated) 8.0版本开始,就不允许创建MyISAM分区表了

本地分区策略

从MySQL 5.7.9开始,InnoDB引擎引入了本地分区策略(native partitioning)。在InnoDB内部自己管理打开分区的行为

分区表的应用场景

  • 对业务透明,相对于用户分表来说,使用分区表的业务代码更简洁。
  • 分区表可以很方便的清理历史数据。
    • 按照时间分区的分区表,就可以直接通过alter table t drop partition …这个语法删掉分区,从而删掉过期的历史数据。 drop partition操作是直接删除分区文件,效果跟drop普通表类似
    • 与使用delete语句删除数据相比,优势是速度快、对系统影响小。
  • 历史数据表的改造,利用存储过程创建和改造
  • 后台数据的分析汇总,比如日志数据,便于清理
  • 个人层面 分区表很少用 基本上没啥大用 个人观点