后台-插件-广告管理-首页/栏目/内容广告位一(PC) |
后台-插件-广告管理-首页/栏目/内容广告位一(手机) |
随着业务的不断发展,数据库中的数据会越来越多,相应地,单表的数据量也会越到越大,大到一个临界值,单表的查询性能就会下降。
这个临界值,并不能一概而论,它与硬件能力、具体业务有关。
虽然在很多 MySQL 运维规范里,都建议单表不超过 500w、1000w。
但实际上,我在生产环境,也见过大小超过 2T,记录数过亿的表,同时,业务不受影响。
单表过大时,业务通常会考虑两种拆分方案:水平切分和垂直切分。
水平拆分 VS 垂直拆分
水平切分,拆分的维度是行,一般会根据某种规则或算法将表中的记录拆分到多张表中。
拆分后的表既可在一个实例,也可在多个不同实例中。如果是后者,又会涉及到分布式事务。
垂直切分,拆分的维度是列,一般是将列拆分到多个业务模块中。这种拆分更多的是上层业务的拆分。
从改造的复杂程度来说,前者小于后者。
所以,在单表数据量过大时,业界用得较多的还是水平拆分。
常见的水平拆分方案有:分库分表、分区表。
虽然分库分表是一个比较彻底的水平拆分方案,但一方面,它的改造需要一定的时间;另一方面,它对开发的能力也有一定的要求。相对来说,分区表就比较简单,也无需业务改造。
分区表
很多人可能会认为 MySQL 的优势在于 OLTP 应用,对于 OLAP 应用就不太适合,所以,也不太推荐分区表这种偏 OLAP 的特性。
但实际上,对于某些业务类型,还是比较适合使用分区表的,尤其是那些有明显冷热数据之分,且数据的冷热与时间相关的业务。
下面,我们看看分区表的优点:
-
提升查询性能
对于分区表的查询操作,如果查询条件中包含分区键,则这个查询操作就只会被下推到符合条件的分区内进行,无关分区将自动过滤掉。
在数据量比较大的情况下,能提升查询速度。
-
对业务透明
将表从一个非分区表转换为分区表,业务端无需做任何改造。
-
管理方便
在对单个分区进行删除、迁移和维护时,不会影响到其它分区。
尤其是针对单个分区的删除(DROP)操作,避免了针对这个分区所有记录的 DELETE 操作。
遗憾的是,MySQL 分区表不支持并行查询。理论上,当一个查询涉及到多个分区时,分区与分区之间应进行并行查询,这样才能充分利用多核 CPU 资源。
但 MySQL 并不支持,包括早期的官方文档,也提到了这个问题,也将这个功能的实现放到了优先级列表中。
These features are not currently implemented in MySQL Partitioning, but are high alt="MySQL 分区表,为什么分区键必须是主键的一部分? " height="449" loading="lazy" src="https:///d/file/20240124/3ce75dcd6a8c942d22c6c16bc16e3cb4.png" width="814" />
结合原理图,我们来看看两种索引之间的区别:
本地分区索引同时也是分区索引,分区索引和表分区之间是一一对应的。
而全局索引,既可以是分区的,也可以是不分区的。
如果是全局分区索引,一个分区索引可对应多个表分区,同样,一个表分区也可对应多个分区索引。
对本地分区索引的管理操作只会影响到单个分区,不会影响到其它分区。
而对全局分区索引的管理操作会造成整个索引的失效,当然,这一点可通过 UPDATE INDEXES 子句加以规避。
本地分区索引只能保证分区内的唯一性,无法保证表级别的唯一性,但全局分区可以。
在 Oracle 中,无论是索引组织表还是堆表,如果要创建本地唯一索引,同样也要求分区键必须是唯一键的一部分。
SQL> create unique index uk_opr_no_local on opr_oracle(opr_no) local; create unique index uk_opr_no_local on opr_oracle(opr_no) local * ERROR at line 1: ORA-14039: partitioning columns must form a subset of key columns of a UNIQUE index [!--empirenews.page--]
总结
1. MySQL 分区表关于“分区键必须是唯一键(主键和唯一索引)的一部分”的限制,本质上是索引组织表的限制。
2. MySQL 分区表只实现了本地分区索引,没有实现全局索引,所以无法保证非分区列的全局唯一。
如果要保证非分区列的全局唯一,只能依赖业务实现了。
3. 不推荐使用 MyISAM 分区表。当然,任何场景都不推荐使用 MyISAM 表。