MySQL表分区

分区表

对用户来说,分区表是一个独立的逻辑表,但是底层由多个物理子表组成。
分区的一个主要目的是将数据按照一个较粗的粒度分在不同的表中,这样可以将相关的数据放在一起,另外,如果想一次批量删除整个分区的数据也会变得很方便。
在下面的场景中,分区可以起到非常大的作用:

  • 表非常大以至于无法全部都放在内存中,或者只在表的最后部分有热点数据,其他均是历史数据。
  • 分区表的数据更容易维护。例如,想批量删除大量数据可以使用清楚整个分区的方式,还可以对一个独立分区进行优化、检查、修复等操作。
  • 分区表的数据可以分布在不同的物理设备上,从而高效地利用多个硬件设备。
  • 使用分区表来避免某些特殊的瓶颈,例如InnoDB单个索引的互斥访问、ext3文件系统的inode锁竞争等。
  • 如果需要,还可以备份和恢复独立的分区,这在非常大的数据集的场景下效果非常好。
    分区表本身也有一些限制,下面是其中比较重要的几点:
  • 一个表最多只能由1024个分区。
  • 在MySQL5.1中,分区表达式必须是整数,或者是返回整数的表达式。
  • 如果分区字段中有主键或者唯一索引的列,那么所有主键列和唯一索引列都必须包含进来。
  • 分区表无法使用外键约束。

分区表的原理

  • SELECT查询:当查询一个分区表的时候,分区表先打开并锁住所有的底层表,优化器先判断是否可以过滤部分分区,然后再调用对应的存储引擎接口访问各个分区的数据。
  • INSERT操作:当写入一条记录时,分区层先打开并锁住所有的底层表,然后确定哪个分区接收这条记录,再将记录写入对应的底层表。
  • DELETE操作:当删除一条记录时,分区层先打开并锁住所有的底层表,然后确定数据对应的分区,最后对相应底层表进行删除操作。
  • UPDATE操作:当更新一条记录时,分区层先打开并锁住所有的底层表,MYSQL确定需要更新的记录在哪个分区,然后取出数据并更新,再判断更新后的数据应该放在哪个分区,最后对底层表进行

如何使用分区表

在数据量超大的时候,B-Tree索引就无法起作用了,因为产生大量的随机I/O。索引维护的代价也非常高。
分区可以看做是索引的最初形态,以代价非常小的方式定位到需要数据在哪一片区域。在这片区域中,你可以顺序扫描,可以建索引,还可以将数据存到内存中。
一般有下面两个策略:

  • 全量扫描数据,不要任何索引
  • 索引数据,并分离热点
    注意:上述讨论都是在建立在某个分区内。

分区可能出现的问题

  • NULL值会使分区过滤无效
    第一个分区是一个特殊的分区,假设按照PARTITION BY RANGE YEAR(order _date)分区,那么所有order_date为null或者一个非法值得时候,记录都会被存放到第一个分区中。如果第一个分区非常大,特别是当使用"全量扫描数据,不要任何索引"的策略时,代价会非常大。为了避免这种情况,可以创建一个“无用”分区的第一个分区。这样如果插入数据都是有效的,那么第一个分区就是空白的。这样即使要检查第一个分区,那么代价也非常小。
    在MySQL5.5中就不需要这个技巧了,因为可以直接使用列本身:PARTITION BY RANGE COLUMNS(order_date)。所以这个案例最好的解决方法是能够使用MySQL 5.5的这个语法。

  • 分区列和索引列不匹配
    假设在列a上定义了索引,在列b上进行分区。因为每个分区有其独立的索引,索引扫描列a上的索引时就需要扫描每个分区内对应的索引。

  • 选择分区的成本可能非常高,每次写入数据时都需要扫描所有的分区定义大的列表来找到正确答案,所以随着分区增多,成本增高。根据经验,对大多数系统来说,100个左右的分区是没有问题的。

  • 打开并锁住所有底层表的成本可能非常高。

  • 维护分区的成本可能很高。

使用分区来优化查询

利用分区函数的列找到对应分区,可以扫描更少的数据。where条件中带入的是分区列而不是基于分区列的表达式。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值