慢吞云雾缓吐愁 发表于 2024-6-15 03:39:24

MySQL分区表:万字详解与实践指南

码到三十五 : 个人主页   MySQL分区是一种数据库优化的技术,它允许将一个大的表或一个索引分割成多个较小的、更易于管理的片断,称为分区。这种技术可以明显进步查询性能、维护的方便性以及数据管理效率。本文将详细介绍MySQL分区的基本概念、工作原理、使用场景以及操作。


一、分区的基本概念

MySQL分区 是一种数据库优化的技术,它允许将一个大的表、索引或其子集分割成多个较小的、更易于管理的片断,这些片断称为“分区”。每个分区都可以独立于其他分区进行存储、备份、索引和其他操作。这种技术主要是为了改善大型数据库表的查询性能、维护的方便性以及数据管理效率。
物理存储与逻辑分割


[*]物理上,每个分区可以存储在差别的文件或目次中,这取决于分区范例和配置。
[*]逻辑上,表数据根据分区键的值被分割到差别的分区里。
查询性能提拔


[*]当实验查询时,MySQL可以或许确定哪些分区包罗相关数据,并只在这些分区上进行搜索。这镌汰了必要搜索的数据量,从而进步了查询性能。
[*]对于范围查询或特定值的查询,分区可以明显镌汰扫描的数据量。
数据管理与维护


[*]分区可以使得数据管理更加灵活。比方,可以独立地备份、规复或优化某个分区,而无需对整个表进行操作。
[*]对于具有时效性的数据,可以通过删除或归档某个分区来快速释放存储空间。
扩展性与并行处置惩罚


[*]分区技术使得数据库表更轻易扩展到更大的数据集。当表的大小超过单个存储设备的容量时,可以使用分区将数据分布到多个存储设备上。
[*]由于每个分区可以独立处置惩罚,因此可以并行实验查询和其他数据库操作,从而进一步进步性能。
二、分区的原理和范例

InnoDB逻辑存储结构

InnoDB存储引擎的逻辑结构是一个层次化的体系,主要由表空间、段、区和页构成。
https://img-blog.csdnimg.cn/direct/36942e61ccaa4329a3603b99f9caf078.jpeg#pic_center

[*] 表空间:是InnoDB数据的最高层容器,所有数据都逻辑地存储在这里。
[*] 段(Segment):是表空间的紧张组成部分,根据用途可分为数据段、索引段和回滚段等。InnoDB引擎负责管理这些段,确保数据的完整性和高效访问。
[*] 区(Extent):由一连的页组成,每个区默认大小为1MB,岂论页的大小如何变革。为包管页的一连性,InnoDB会一次性从磁盘申请多个区。每个区包罗64个一连的页,当默认页大小为16KB时。在段开始时,InnoDB会先使用32个碎片页存储数据,以优化小表或特定段的空间使用率。
[*] 页(Page):是InnoDB磁盘管理的最小单元,也被称为块。其默认大小为16KB,但可通过配置参数进行调解。页的范例多样,包罗数据页、undo页、系统页等,每种页都有其特定的功能和结构。
分区的原理

分区技术是将表中的记录分散到差别的物理文件中,即每个分区对应一个.idb文件。这是MySQL 5.1及以后版本支持的一项高级功能,旨在进步大数据表的管理效率和查询性能。
https://img-blog.csdnimg.cn/direct/5a05a04c1c824aaf9d2f96c339416a2a.jpeg#pic_center

[*] 分区范例:MySQL支持水平分区,即根据某些条件将表中的行分配到差别的分区中。这些分区在物理上是独立的,可以单独处置惩罚,也可以作为整体处置惩罚。
[*] 性能和影响:固然分区可以进步查询性能和管理效率,但如果不适当使用,也大概对性能产生负面影响。因此,在使用分区时应审慎评估其影响。
[*] 索引与分区:在MySQL中,分区是局部的,意味着数据和索引都存储在各自的分区内。目前,MySQL尚不支持全局分区索引。
[*] 分区键与唯一索引:当表存在主键或唯一索引时,分区列必须是这些索引的一部分。这是为了确保分区的唯一性和查询效率。
通过合理使用分区技术,可以优化数据库性能、进步管理效率,并更好地适应大规模数据处置惩罚的需求。然而,为了充分使用这一功能,数据库管理员和开发者必要深入了解其工作原理和最佳实践。
分区范例

MySQL支持几种差别范例的分区方式,包罗RANGE、LIST、HASH和KEY。下面扼要介绍这些分区方式的工作原理:

[*]RANGE分区:基于列的值范围将数据分配到差别的分区。比方,可以根据日期范围将数据分配到差别的月份或年份的分区中。
[*]LIST分区:雷同于RANGE分区,但LIST分区是基于列的离散值集合来分配数据的。可以指定一个罗列列表来定义每个分区的值。
[*]HASH分区:基于用户定义的表达式的哈希值来分配数据到差别的分区。这种分区方式适用于确保数据在各个分区之间匀称分布。
[*]KEY分区:雷同于HASH分区,但KEY分区支持计算一列或多列的哈希值来分配数据。它支持多列作为分区键,并且提供了更好的数据分布和查询性能。
三、分区的优势和使用场景

MySQL分区带来了许多优势,适用于各种使用场景:

[*]性能提拔:通过将数据分散到多个分区中,可以并行处置惩罚查询,从而进步查询性能。同时,对于涉及大量数据的维护操作(如备份和规复),可以单独处置惩罚每个分区,镌汰了操作的复杂性和时间本钱。
[*]管理简化:分区可以使得数据管理更加灵活。比方,可以独立地备份、规复或优化某个分区,而无需对整个表进行操作。这对于大型数据库表来说尤为紧张,因为它可以明显镌汰维护时间和资源消耗。
[*]数据归档和整理:对于具有时间属性的数据(如日记、交易记录等),可以使用分区来轻松归档旧数据或删除不再必要的数据。通过简单地删除或归档某个分区,可以快速释放存储空间并进步性能。
[*]可扩展性:分区技术使得数据库表更轻易扩展到更大的数据集。当表的大小超过单个存储设备的容量时,可以使用分区将数据分布到多个存储设备上,从而实现水平扩展。
https://img-blog.csdnimg.cn/direct/bd4cc36e45f3481bb22b1cf55035f8df.jpeg#pic_center
四、如何实施分区

实施MySQL分区必要仔细规划和设计。以下是一些发起的步骤:

[*]确定分区键:选择一个合适的列作为分区键,该列的值将用于将数据分配到差别的分区中。通常选择具有一连值或离散值的列作为分区键。
[*]选择合适的分区范例:根据数据的特点和查询需求选择合适的分区范例(RANGE、LIST、HASH或KEY)。确保所选的分区范例可以或许匀称地分布数据并进步查询性能。
[*]创建分区表:使用CREATE TABLE语句创建分区表,并指定分区键和分区范例等参数。比方,使用RANGE分区范例创建一个按月分区的销售数据表:
CREATE TABLE sales (
    sale_id INT NOT NULL,
    sale_date DATE NOT NULL,
    amount DECIMAL(10, 2) NOT NULL,
    ...
) PARTITION BY RANGE (YEAR(sale_date)) (
    PARTITION p0 VALUES LESS THAN (2022),
    PARTITION p1 VALUES LESS THAN (2023),
    PARTITION p2 VALUES LESS THAN MAXVALUE
);

[*]查询和维护:一旦创建了分区表,就可以像平常表一样实验查询操作。MySQL会自动定位到相应的分区上实验查询。同时,可以独立地备份、规复或优化每个分区。
[*]监控和调解:定期监控分区的性能和存储使用情况,并根据必要进行调解。比方,可以添加新的分区来容纳新数据,大概删除旧的分区以释放存储空间。
五、分区表的操作

包罗创建分区表、修改分区和删除、合并、拆分等。
5.1. 创建带有分区的表

RANGE 分区

CREATE TABLE sales_range (
    id INT NOT NULL,
    sale_date DATE NOT NULL,
    amount DECIMAL(10, 2) NOT NULL
) PARTITION BY RANGE (YEAR(sale_date)) (
    PARTITION p0 VALUES LESS THAN (2010),
    PARTITION p1 VALUES LESS THAN (2011),
    PARTITION p2 VALUES LESS THAN (2012),
    PARTITION p3 VALUES LESS THAN MAXVALUE
);
LIST 分区

CREATE TABLE sales_list (
    id INT NOT NULL,
    region ENUM('North', 'South', 'East', 'West') NOT NULL,
    amount DECIMAL(10, 2) NOT NULL
) PARTITION BY LIST COLUMNS(region) (
    PARTITION pNorth VALUES IN('North'),
    PARTITION pSouth VALUES IN('South'),
    PARTITION pEast VALUES IN('East'),
    PARTITION pWest VALUES IN('West')
);
HASH 分区

CREATE TABLE sales_hash (
    id INT NOT NULL,
    sale_date DATE NOT NULL,
    amount DECIMAL(10, 2) NOT NULL
) PARTITION BY HASH(YEAR(sale_date)) PARTITIONS 4;
KEY 分区

CREATE TABLE sales_key (
    id INT NOT NULL,
    sale_date DATE NOT NULL,
    amount DECIMAL(10, 2) NOT NULL,
    PRIMARY KEY (id, sale_date)
) PARTITION BY KEY(id) PARTITIONS 4;
5.2. 修改分区表

添加分区

对于 RANGE 或 LIST 分区,可以使用 ALTER TABLE 语句添加分区:
ALTER TABLE sales_range ADD PARTITION (PARTITION p4 VALUES LESS THAN (2013));
对于 HASH 或 KEY 分区,由于它们是基于哈希函数进行分区的,因此不能直接添加分区,但可以通过重新创建表或调解分区数量来间接实现。
删除分区

可以使用 ALTER TABLE 语句删除分区:
ALTER TABLE sales_range DROP PARTITION p0;
这将删除名为 p0 的分区及其包罗的所有数据。
合并分区

对于相邻的 RANGE 或 LIST 分区,可以使用 ALTER TABLE 语句将它们合并为一个分区:
ALTER TABLE sales_range REORGANIZE PARTITION p1, p2 INTO (
    PARTITION p1_2 VALUES LESS THAN (2012)
);
把 p1 和 p2 分区合并为一个名为 p1_2 的新分区。
分区拆分限制:

[*]分区数量限制:MySQL对单个表的分区数量有限制,通常最大分区数目不能超过1024个。这意味着在进行拆分操作时,必要留意新生成的分区数量是否会超过这个限制。
[*]分区键和分区范例的限制:拆分操作通常受到分区键和分区范例的约束。比方,在RANGE分区中,拆分点必须基于分区键的一连值。对于LIST分区,拆分必要基于离散的罗列值。HASH和KEY分区由于其基于哈希函数的特性,不直接支持拆分操作。
[*]数据完整性:拆分分区时,必要确保数据的完整性。如果拆分操作导致数据丢失或损坏,那么这将是一个严峻的问题。因此,在实验拆分操作之前,最好进行数据备份。
[*]性能考虑:拆分大分区大概会影响数据库性能,因为必要重修索引和移动大量数据。这种操作最好在数据库负载较低的时间进行。
拆分分区

使用ALTER TABLE语句来拆分分区。语法,用于RANGE分区:
ALTER TABLE table_name REORGANIZE PARTITION partition_name INTO (
    PARTITION new_partition1 VALUES LESS THAN (value1),
    PARTITION new_partition2 VALUES LESS THAN (value2)
);
table_name是你要修改的表名,partition_name是要拆分的分区名,new_partition1和new_partition2是新分区的名称,而value1和value2是定义新分区键值范围的值。
ALTER TABLE sales_range REORGANIZE PARTITION p1_2 INTO (
    PARTITION p1 VALUES LESS THAN (value1),
    PARTITION p2 VALUES LESS THAN (value2)
);
把一个名为 p1_2 的分区拆分为 p1 和 p2 两个分区。
分区合并限制:

[*]相邻分区合并:在MySQL中,通常只能合并相邻的分区。这意味着你不能随意选择两个不相邻的分区进行合并。
[*]分区范例和键的限制:与拆分操作雷同,合并操作也受到分区范例和分区键的约束。不是所有范例的分区都可以轻松合并。
[*]数据迁徙和重修:合并分区时,大概必要进行数据迁徙和索引重修,这大概会影响数据库的性能和可用性。
重修分区

重修分区相当于先清除分区内的所有数据,并随后重新插入,这有助于整理分区内的碎片。


[*]语法:
ALTER TABLE tbl_name REBUILD PARTITION partition_name_list;


[*]示例:
ALTER TABLE tbl_users REBUILD PARTITION p2, p3;
通过这一操作,可以高效地整理p2和p3这两个分区中的碎片。
优化分区

当从分区中删除了大量数据,大概对包罗可变长度字段(如VARCHAR或TEXT范例列)的分区进行了多次修改后,优化分区可以回收未使用的空间并整理数据碎片。


[*]语法:
ALTER TABLE tbl_name OPTIMIZE PARTITION partition_name_list;


[*]示例:
ALTER TABLE tbl_users OPTIMIZE PARTITION p2, p3;
实验此操作后,p2和p3分区将会更加紧凑,未使用的空间将被回收。
分析分区

此操作会读取并生存分区的键分布统计信息,有助于查询优化器制定更有用的查询筹划。


[*]语法:
ALTER TABLE tbl_name ANALYZE PARTITION partition_name_list;


[*]示例:
ALTER TABLE tbl_users ANALYZE PARTITION p2, p3;
对p2和p3分区进行分析后,数据库能更准确地为这两个分区上的查询制定实验筹划。
检查分区

此操作用于验证分区中的数据或索引是否完整无损。


[*]语法 :
ALTER TABLE tbl_name CHECK PARTITION partition_name_list;


[*]示例:
ALTER TABLE tbl_users CHECK PARTITION p2, p3;
实验检查可以确保p2和p3分区的数据和索引的完整性。
修补分区

如果分区数据或索引受损,可以使用此操作进行修复。


[*]语法:
ALTER TABLE tbl_name REPAIR PARTITION partition_name_list;


[*]示例:
ALTER TABLE tbl_users REPAIR PARTITION p2, p3;
实验修补操作后,p2和p3分区中的任何损坏都将被修复。
5.3. 检察分区信息

可以使用以下查询来检察表的分区信息:
SELECT * FROM INFORMATION_SCHEMA.PARTITIONS WHERE TABLE_NAME = 'sales_range';
大概使用 SHOW CREATE TABLE 语句来检察表的创建语句,包罗分区定义:
SHOW CREATE TABLE sales_range;
六、复合分区

复合分区是指在分区表中的每个分区再次进行分割,这种再次分割的子分区既可以使用HASH分区,也可以使用KEY分区。这种技术也被称为子分区。
使用场景


[*]数据量巨大:当表中的数据量非常大时,单一分区大概无法满足性能需求。复合分区可以将数据更过细地划分,从而进步查询效率。
[*]多维度查询优化:如果查询常常涉及多个维度(如时间和地域),复合分区可以针对这些维度进行分区,从而优化查询性能。
在复合分区中,常见的组合是RANGE或LIST与HASH或KEY的组合
创建一个记任命户行为日记的表,首先根据日记日期进行RANGE分区,然后在每个日期范围内根据用户ID进行HASH子分区。
CREATE TABLE user_activity_logs (
    log_id BIGINT NOT NULL AUTO_INCREMENT,
    user_id INT NOT NULL,
    activity_date DATE NOT NULL,
    activity_description VARCHAR(255) NOT NULL,
    PRIMARY KEY (log_id, user_id)
)
PARTITION BY RANGE COLUMNS(activity_date) (
    PARTITION p2022 VALUES LESS THAN ('2023-01-01') (
      SUBPARTITION sp2022a HASH(user_id) PARTITIONS 4
    ),
    PARTITION p2023 VALUES LESS THAN ('2024-01-01') (
      SUBPARTITION sp2023 HASH(user_id) PARTITIONS 4
    ),
    -- 可以根据需要继续添加更多的年份分区和HASH子分区
    PARTITION pfuture VALUES LESS THAN (MAXVALUE) (
      SUBPARTITION spfuture HASH(user_id) PARTITIONS 4
    )
);


[*]先根据activity_date进行范围分区。每个范围分区内部,又根据user_id进行了HASH子分区。这样做的利益是可以更匀称地分布数据,进步查询性能,特殊是当查询条件同时包罗日期和用户ID时。
[*]预留了一个名为pfuture的分区,它的范围是小于最大值(MAXVALUE),这样可以确保未来的日记也能被正确地插入到表中。
[*]PARTITIONS 4表现在每个范围分区内创建4个哈希子分区。这个数字可以根据数据量的大小和查询模式进行调解。
七、留意事项和限制

在实施MySQL分区时,必要留意以下事项和限制:

[*]分区键选择:选择合适的分区键至关紧张。确保分区键可以或许匀称地分布数据,并且与查询条件相匹配,以进步查询性能。
[*]分区数量限制:MySQL对单个表的分区数量有限制(通常为1024个分区)。在设计分区策略时要考虑这个限制。
[*]全局唯一索引限制:在分区表上创建全局唯一索引时存在限制。确保了解这些限制,并根据必要进行调解。
[*]性能和资源消耗:固然分区可以进步性能,但在某些情况下,过多的分区大概导致额外的性能和资源消耗。因此,要合理设计分区策略以均衡性能和资源消耗。
[*]兼容性和迁徙:在迁徙现有表到分区表之前,要确保备份原始数据并测试迁徙过程的正确性。此外,要了解差别MySQL版本之间对分区功能的支持和兼容性差异。
八、解释几个问题

8.1 MySQL分区处置惩罚NULL值的方式

MySQL中,当涉及到分区时,系统并不会特殊禁止NULL值。岂论是列的实际值还是用户自定义的表达式效果,MySQL通常会将NULL值视为0进行处置惩罚。然而,这种行为大概并不总是符合数据完整性和准确性的要求。为了避免这种隐式的NULL到0的转换,最佳实践是在设计数据库表时,对相关列明白声明为“NOT NULL”。这样做可以确保数据的准确性和一致性,同时避免由于NULL值被错误地解释为0而导致的潜在问题。因此,在设计分区表时,应该审慎考虑NULL值的处置惩罚方式,并根据必要接纳相应的防备措施。
此外,如果确实必要存储NULL值,并且不希望MySQL将其视为0,可以考虑使用其他特殊值(如某个不大概在实际业务中出现的标识值)来代替NULL,大概在设计分区策略时明白考虑NULL值的处置惩罚逻辑。这样可以在保持数据完整性的同时,更好地满足业务需求。
8.2 分区列必须主键或唯一键的一部分

在MySQL中,当表存在主键(primary key)或唯一键(unique key)时,分区的列必须是这些键的一个组成部分的缘故原由主要涉及到数据的完整性和查询性能:

[*] 数据完整性:

[*]主键和唯一键用于包管表中数据的唯一性。如果分区列不是这些键的一部分,那么在差别分区中大概存在具有雷同主键或唯一键值的数据行,这将破坏数据的唯一性约束。

[*] 查询性能:

[*]分区的主要目标是为了进步查询性能,特殊是针对大数据量的表。如果分区列不是主键或唯一键的一部分,那么在进行基于主键或唯一键的查询时,MySQL大概必要在所有分区中进行搜索,从而低落了查询性能。

[*] 数据一致性:

[*]当表被分区时,每个分区实际上可以看作是一个独立的“子表”。如果分区列不是主键或唯一键的一部分,那么在实验更新或删除操作时,MySQL必要确保跨所有分区的数据一致性,这会增长操作的复杂性和开销。

[*] 分区策略:

[*]MySQL的分区策略是基于分区列的值来将数据分配到差别的分区中。如果分区列不是主键或唯一键的一部分,那么分区策略大概会变得复杂且低效,因为系统必要额外处置惩罚主键或唯一键的约束。

8.3 分区与性能考量

技术的运用必要恰到利益才能发挥其优势。以显式锁为例,固然功能强盛,但使用不妥大概导致性能下降或其他不良结果。同样地,分区技术也并非万能的性能提拔工具。
分区确实可以为某些SQL查询带来性能上的提拔,但其主要价值在于进步数据库的高可用性管理。在应用分区技术时,我们必要根据数据库的使用场景来审慎选择。
数据库应用大体上可分为OLTP(在线事件处置惩罚)和OLAP(在线分析处置惩罚)两类。对于OLAP应用来说,分区可以或许明显提拔查询性能,因为分析类查询往往必要处置惩罚大量数据。按时间进行分区,比方按月划分用户行为数据,可以使得查询只需扫描相关分区,从而进步效率。
然而,在OLTP应用中,使用分区则需更为审慎。这类应用通常不会查询大表中超过10%的数据,而是通过索引快速检索少量记录。比方,对于包罗1000万条记录的表,如果查询使用了辅助索引但未涉及分区键,大概导致性能下降。本来在单个B+树中3次逻辑IO就能完成的操作,在10个分区的情况下大概必要(3+3)*10次逻辑IO(分别访问聚集索引和辅助索引)。
因此,在OLTP应用中采用分区表时,务必进行充分的性能测试和优化。
为了便于开发者观察SQL查询对分区的使用情况,可以使用EXPLAIN PARTITIONS语句与SELECT查询联合,从而清晰地看到哪些分区被查询涉及。
    听说...关注下面公众号的人都变牛了,纯技术,纯干货 ! https://img-blog.csdnimg.cn/direct/d8a0f829c23843419a500ccf4932b1f3.gif#pic_center

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
页: [1]
查看完整版本: MySQL分区表:万字详解与实践指南