MySQL分区partition(为什么要做数据库拆分、为什么partition可以提升性能)

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-NC-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/zgdwxp/article/details/102315012

分区是为了缓解大数量下磁盘IO问题。

背景

当数据量较大时,存储的物理文件会变得非常大、使用性能很差。

解决思路

文件太大,常用思路是拆表、减少单表数据量,这样每个表文件变小、性能和维护都会更容易。
一般有两种拆分方式:

  • 水平拆分。即同个结构的表建多个,按一定规则将不同的行放到不同的表。

    按主键、数据所属用户或其他列,使用Hash、一致性Hash、Hash字典等方式。

  • 垂直拆分。将不同的表放到不同的数据库。

    一般按业务模块拆分。

实际上一般是两种方式混合使用。

这样原本一个巨大的文件,我们可以通过一定策略,拆分为很多小文件,性能会大大提升。

MySQL partition的意义

如果要自己在业务层实现水平或垂直拆分,势必会侵入业务代码、还需要dao层架构调整、增加代理处理路由等,开发成本很高。
如果在业务开发压力较大的时候,开发成本是一个很重要的考量。所以在解决问题的同时,应该尽可能考虑一种低成本的方案。

MySQL partition就是这样一个方案,业务开发几乎完全不用考虑分区的逻辑,都由DB层面、DBA处理即可。

为了提高分区检索效率,业务里sql条件一般最好带上分区键,这个成本不高。个别业务如全表汇总可以做分区并发,性能反而会提升。

小结:业务层无需考虑表结构区别。

如何使用partition

基本语法

partition支持哈希、范围等多种切片方式1
先简单介绍哈希方式:

CREATE TABLE `t_fact_prd_bom` (
	`k` BIGINT(19) UNSIGNED NOT NULL,
	`code` BIGINT(19) UNSIGNED NOT NULL,
	`partition_key` BIGINT(19) UNSIGNED NOT NULL,
	PRIMARY KEY (`k`, `partition_key`),
	UNIQUE KEY (`partition_key`, `code`)
) ENGINE=InnoDB PARTITION BY HASH (`partition_key`) PARTITIONS 100 
DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

声明分区的部分是:

PARTITION BY HASH (`partition_key`) PARTITIONS 100

表示一共有100个分区,按partition_key进行Hash映射。

其他方式暂时不作展开,可以参考官方文档《https://dev.mysql.com/doc/refman/8.0/en/partitioning-types.html》

如果理解不足,还可以参考下面文章:
https://dev.mysql.com/doc/refman/8.0/en/partitioning.html
https://blog.csdn.net/alex_xfboy/article/details/85245502
https://www.cnblogs.com/yaowen/p/8301816.html
https://www.cnblogs.com/aipiaoborensheng/p/6394702.html
https://www.cnblogs.com/alamps/p/6740572.html

常见问题

分区键(用来分区的列)须同时存在于所有的primary keyunique key中,这是最容易出现问题。

MySQL索引是跟分区走的,如果分区键不在唯一索引中,那么原本的唯一键,在在多个分区会出现重复。 于是MySQL给定了这么一个规则:要么去掉唯一索引、分区可以自由创建,要么分区键加入唯一索引、这样原唯一键+分区键这个组合是唯一。

  • “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.) "
  • 官方文档:https://dev.mysql.com/doc/refman/8.0/en/partitioning-limitations-partitioning-keys-unique-keys.html

A PRIMARY KEY must include all columns in the table's partitioning function

问题SQL:

CREATE TABLE `t_fact_prd_bom` (
	`k` BIGINT(19) UNSIGNED NOT NULL,
	`code` BIGINT(19) UNSIGNED NOT NULL,
	`partition_key` BIGINT(19) UNSIGNED NOT NULL,
	PRIMARY KEY (`k`),
	UNIQUE KEY (`partition_key`, `code`)
) ENGINE=InnoDB PARTITION BY HASH (`partition_key`) PARTITIONS 100 
DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

解决方式(将分区键partition_key放入主键):

PRIMARY KEY (`k`, `partition_key`)

如果主键是自增列,需要将分区键放到最后,否则会出现下面这个问题:
Incorrect table definition; there can be only one auto column and it must be defined as a key

A UNIQUE INDEX must include all columns in the table's partitioning function

与主键问题类似,只不过是唯一键(唯一索引)中没有分区键,加上即可。


以上。感谢您的阅读。


  1. MySQL官方文档 - 分区类型:《https://dev.mysql.com/doc/refman/8.0/en/partitioning-types.html》 ↩︎

猜你喜欢

转载自blog.csdn.net/zgdwxp/article/details/102315012