随着信息技术的不断发展和应用场景的不断扩大,大量数据的产生和存储已经成为了当今社会的一个重要问题。在许多领域,如互联网、金融、医疗等,都需要处理和存储海量的数据,这对数据库系统的存储和管理能力提出了巨大的挑战。对于数据库的海量数据存储,方案有很多,常见的有:
- **分区:**数据库按照规则对表做水平拆分。
- **分表:**开发者按需求对表做水平活垂直拆分。
- **分库:**根据业务将相关的表存放到不同的数据库。
- **集群:**给读写压力较大的数据库搭建主从集群。
1. 分区
**表分区(Partition)**是一种数据存储方案,可以解决单表数据较多的问题。MySQL5.1开始支持表分区功能。
数据库的表最终肯定是保存在磁盘中,对于InoDB引擎,一张表的数据在磁盘上对应一个ibd文件。比如,在test库中创建一个t_user表:
sql
CREATE TABLE `t_user` (
`id` int NOT NULL AUTO_INCREMENT,
`username` varchar(50) NOT NULL COMMENT '账号',
`password` varchar(50) NOT NULL COMMENT '密码',
`role` tinyint NOT NULL COMMENT '角色:0-管理员、1-1区用户、2-2区用户',
PRIMARY KEY (`id`)
)
会在MySQL数据目录的Data文件夹下test库生成一个t_user.ibd文件,如下图:
数据目录文件位置说明:
- windows系统:在MySQL安装过程中,指定的Data Directory目录位置:
- Linux系统:输入cat /etc/my.cnf | grep datadir命令
如果表数据过多,就会导致文件体积非常大。文件就会跨越多个磁盘分区,数据检索时的速度就会非常慢。
为了解决这个问题,MySQL在5.1版本引入表分区功能。简单来说,就是按照某种规则,把表数据对应的ibd文件拆分成多个文件来存储。从物理上来看,一张表的数据被拆到多个表文件存储了;从逻辑上来看,他们对外表现是一张表。
例如,将t_user表按用户角色拆分:
此时,t_user表的磁盘文件就被分成了两个文件。但逻辑上还是一张表。增删改查的方式不会有什么变化,只不过底层MySQL底层的处理上会有变更。例如检索时可以只检索某个文件,而不是全部。
注意:
操作分区表和操作普通表没有区别,数据库会自动根据数据来将该数据插入对应分区中。
1.1 表分区的优点
-
可以存储更多的数据,突破单表上限。甚至可以存储到不同磁盘,突破磁盘上限
-
查询时可以根据规则只检索某一个文件,提高查询效率
-
数据统计时,可以多文件并行统计,最后汇总结果,提高统计效率
-
对于一些历史数据,如果不需要时,可以直接删除分区文件,提高删除效率
1.2 表分区的限制和缺点
-
在MySQL 5.6.7之前的版本,一个表最多有1024个分区;从5.6.7开始,一个表最多可以有8192个分区。
-
MySQL的分区字段,必须包含在主键字段内。如果一个表有主键,那么分区字段必须包含在主键内,也就是分区字段必须是主键的一部分或者全部,不能以非主键的字段作为分区字段。当然,也可以为没有主键的表建立分区。
-
分区表无法使用外键约束。
-
NULL值会使分区过滤无效。
-
所有分区必须使用相同的存储引擎。
1.3 常见的分区方式
1.3.1 RANGE 分区
RANGE 分区是一种常用的分区方式,它根据某个列的值范围将数据分散到不同的分区中。这种分区方式特别适用于时间序列数据或具有明显范围特征的数据。
RANG分区特点:
- 每个分区包含一个值的范围。
- 支持动态范围值,可以根据业务需求灵活调整分区范围。
- 多个分区的分区键的值的范围要连续,依次递增,但是不能重叠。
- 默认情况下使用VALUES LESS THAN属性,但每个分区并不包括指定的那个值。
- MAXVALUE 是一个特殊值,表示大于所有指定值的范围。例如:PARTITION p3 VALUES LESS THAN MAXVALUE表示分区 p3 包含所有大于上一个分区的最大范围值。
1.3.2 LIST 分区
LIST 分区是一种根据列值的离散列表来分区数据的方式。这种方式特别适用于列值是特定集合的情况,例如部门 ID、地区代码等。
LIST分区的特点:
- 每个分区包含一组固定的值。
- 支持非连续的值。
- 分区值必须在创建分区时明确指定,不支持动态值。如PARTITION p0 VALUES IN (MAXVALUE) 。
- 各分区的列表值不能重复。
- 每一行数据必须能找到对应的分区列表,否则数据插入失败
1.3.3 HASH 分区
HASH 分区是一种基于哈希函数对数据进行分区的方式。它通过计算分区键的哈希值,并将数据分布到不同的分区中。这种方式特别适用于需要均匀分布数据的场景,如用户 ID、订单 ID 等。
HASH分区的特点:
- 通过哈希函数将数据均匀分布到各个分区中,避免数据倾斜。
- 分区逻辑简单,只需指定分区键和分区数量。例如,PARTITION BY HASH (customer_id) PARTITIONS 4 表示根据 customer_id 的哈希值将数据分成 4 个分区。
- 可以动态调整分区数量,以适应数据增长。
- MySQL 等支持 KEY 分区的数据库的 HASH 分区的键值必须是一个整数类型的值,或是通过函数可以转为整数类型。
1.3.4 KEY 分区
KEY 分区是一种基于哈希函数对数据进行分区的方式,类似于 HASH 分区,但它使用的是数据库内部的哈希函数,而不是用户指定的哈希函数。KEY 分区特别适用于需要均匀分布数据的场景。
KEY 分区的特点:
- 通过哈希函数将数据均匀分布到各个分区中,避免数据倾斜。
- 分区逻辑简单,只需指定分区键和分区数量。例如,PARTITION BY KEY (customer_id) PARTITIONS 4 表示根据 customer_id 的哈希值将数据分成 4 个分区。
- 使用数据库内部的哈希函数,无需用户指定具体的哈希算法。
- KEY 分区的键值不限定字段类型。
注意:
只有部分数据库有KEY 分区,如MySQL,达梦数据库。
1.3.5 子分区(复合分区)
子分区是分区表中每个分区的再次分割,适合保存非常大量的数据。
说明:
- 在MySQL 5.1中,对于已经通过RANGE或LIST分区了的表再进行子分区是可能的。子分区既可以使用HASH希分区,也可以使用KEY分区。这也被称为复合分区。
- 在 Oracle 11g 以前,组合分区主要有两种组合方式:"RANGE-HASH"以及"RANGE-LIST"。
- 在 Oracle 11g 以后,组合分区新增了四种组合方式:"RANGE-RANGE"、"LIST-RANGE"、"LIST-HASH"以及"LIST-LIST"。
2. 分表
分表是指将一个大表按照一定的规则拆分成多个小表,以提高数据库的读写性能和管理效率。分表的主要目的是解决单表数据量过大导致的查询慢、锁定时间长等问题。
分区和分表区别:
- 分区:在逻辑上是同一张表,增删改查与以前没有区别。
- 分表:无论在逻辑上,还是物理上,就从一张表变成了多张表!增删改查的方式就发生了变化,必须自己考虑要去哪张表做数据处理。
2.1 水平分表
2.2 垂直分表
如果一张表的字段非常多,比如达到30个以上,这样的表我们称为宽表。宽表由于字段太多,单行数据体积就会非常大,虽然数据不多,但可能表体积也会非常大!从而影响查询效率。
例如一个用户信息表,除了用户基本信息,还包含很多其它功能信息:
这个时候,我们就可以把其中的一些不常用字段拆分出去。一张表中包含登录常用字段,另一张表包含其它字段:
这个时候一张表就变成了两张表。而且两张表的结构不同,数据也不同。这种按照字段拆分表的方式,称为垂直拆分。
2.2 分表优点
- 分表后,每个表的数据量减少,查询时需要扫描的数据量也相应减少,从而提高了查询速度。
- 分表可以减少单表的锁竞争,提高并发性能,特别是在高并发写入场景下效果明显。
- 通过水平分表,可以轻松地增加新的表或分区,实现水平扩展,适应不断增长的数据量。
- 小表更易于管理和维护,例如备份、恢复、迁移等操作都更加高效。
- 分表可以降低单点故障的风险,提高系统的容错能力。
- 分表后可以更方便地对历史数据进行压缩和归档,减少存储空间占用。
- 多个表可以并行执行查询操作,进一步提升查询性能。
2.3 分表缺点
- 分表后,数据的插入、查询、更新和删除操作都需要根据分表规则进行处理,增加了开发和维护的难度。
- 分表后,如果需要调整分表策略,可能需要重新设计和迁移数据,增加了系统的维护难度和成本。
- 分表后,如果需要进行跨表查询,查询逻辑会变得更加复杂,可能需要使用联合查询或子查询,影响查询性能。
- 多个表的索引可能会产生更多的索引碎片,影响查询性能。
- 分表后,备份和恢复操作需要针对多个表进行,增加了操作的复杂性和时间成本。
- 分表后,需要对多个表进行权限管理,增加了安全性和权限管理的复杂性。
在开发中我们很多情况下业务需求复杂,更看重分表的灵活性。因此,我们大多数情况下都会选择分表方案。
3. 分库
分库是指将一个大型数据库中的数据按照一定的规则拆分到多个数据库实例中,每个实例管理一部分数据。分库的主要目的是解决单个数据库实例在数据量和并发访问方面的能力限制。
分库常用中间件:
- ShardingSphere:阿里巴巴开源的数据库中间件。
- MyCat:开源的数据库中间件。
- TDDL:阿里巴巴开源的分布式数据库访问层。
3.1 水平分库
- 范围分库:根据某个字段的值范围将数据分布到不同的数据库实例中,例如按时间范围分库。
- 哈希分库:根据某个字段的哈希值将数据分布到不同的数据库实例中,例如按用户ID取模。
- 列表分库:根据某个字段的具体值列表将数据分布到不同的数据库实例中,例如按地区分库。
3.2 垂直分库
- 功能分库:根据业务功能或模块将数据分布到不同的数据库实例中。
- 访问频率分库:将经常访问的数据和不经常访问的数据分别存储在不同的数据库实例中。
3.3 分库优点
- 提高性能:分库可以减少单个数据库实例的数据量和并发访问压力,提高查询和写入性能。
- 提高可扩展性:通过增加新的数据库实例,可以轻松实现水平扩展,适应不断增长的数据量和访问量。
- 故障隔离:分库后,即使某个数据库实例出现故障,也不会影响其他实例的正常运行,提高了系统的稳定性。
3.4 分库缺点
- 复杂性增加:分库需要设计合理的分库策略,增加了系统设计和实现的复杂性。
- 数据一致性问题:分库后,跨库的事务处理变得更加复杂,可能需要引入分布式事务管理。
- 查询复杂度增加:分库后,跨库查询和聚合查询需要在多个数据库实例中分别执行,再合并结果,增加了查询的复杂性和执行时间。
- 维护和管理难度增加:分库后,需要对多个数据库实例进行管理和维护,增加了运维工作的复杂性。
4. 集群
数据库集群是指将多个数据库实例组成一个集群,通过负载均衡、数据复制和故障切换等技术,实现高可用性和高性能。集群的主要目的是提高系统的可用性和并发处理能力。
4.1 主从复制
4.1.1 异步复制
1. 基本原理
- 主节点:负责处理所有的写操作,并将数据变更日志(如MySQL的binlog)发送给从节点。
- 从节点:接收主节点发送的数据变更日志,并异步地应用这些日志,以保持与主节点的数据同步。
2. 优点
- 主节点只需将数据变更日志发送给从节点,而不需要等待从节点完成数据同步,从而减少了主节点的等待时间和负担。
- 由于主节点不需要等待从节点的确认,写操作可以更快地完成,提高了系统的整体性能。
- 可以通过增加更多的从节点来分担读操作的压力,提高系统的读取能力和并发处理能力。
- 从节点可以在网络中断后重新连接并继续同步数据,提高了系统的容错能力。
3. 缺点
- 由于数据同步是异步的,从节点的数据可能会滞后于主节点,导致数据不一致。在某些情况下,这可能会影响业务逻辑的正确性。
- 如果主节点在数据变更日志传输前发生故障,且日志尚未被从节点接收,可能会导致数据丢失。
- 从节点在故障恢复时需要重新同步大量的数据,恢复时间较长,可能会影响系统的可用性。
- 由于数据同步是异步的,从节点的数据可能与主节点不完全一致,数据校验和修复较为困难。
- 需要监控主节点和从节点之间的数据同步状态,确保数据的一致性和完整性。
- 需要定期检查和维护从节点,确保其正常运行,增加了运维工作的复杂性。
4. 适用场景
- 读多写少:对于读操作远多于写操作的场景,异步复制可以有效分担读操作的压力,提高系统的读取性能。
- 数据量大:对于数据量较大的场景,通过增加从节点可以实现水平扩展,提高系统的整体性能。
- 网络延迟较高:在网络延迟较高的环境中,异步复制可以减少网络延迟对主节点性能的影响。
5. 不适合的场景
- 强一致性要求:对于要求数据强一致性的场景,如金融交易系统,异步复制可能导致数据不一致,不适合使用。
- 频繁写操作:对于写操作非常频繁的场景,异步复制可能导致从节点的数据严重滞后,影响业务逻辑的正确性。
4.1.2 半同步复制
半同步复制是数据库集群中的一种数据复制方式,介于异步复制和同步复制之间。它通过确保主节点在提交事务之前至少有一个从节点已经接收到并确认了数据变更日志,从而在一定程度上保证了数据的一致性和可靠性。
1. 基本原理
- 主节点:负责处理所有的写操作,并将数据变更日志(如MySQL的binlog)发送给从节点。
- 从节点:接收主节点发送的数据变更日志,并应用这些日志,更新自己的数据。
- 半同步:主节点在提交事务之前,必须等待至少一个从节点确认已经接收到并应用了数据变更日志。
2. 优点
- 提高数据一致性:通过确保至少一个从节点已经接收到并确认了数据变更日志,半同步复制在一定程度上保证了数据的一致性和可靠性。
- 减少数据丢失风险:即使主节点在数据变更日志传输前发生故障,只要从节点已经接收到并确认了日志,数据不会丢失。
- 性能较好:相比同步复制,半同步复制的性能更好,因为只需要等待一个从节点的确认,而不是所有从节点的确认。
3. 缺点
- 性能略低于异步复制:由于主节点需要等待至少一个从节点的确认,写操作的性能会略低于异步复制。
- 依赖网络稳定性:如果网络不稳定或从节点故障,主节点可能需要等待较长时间才能收到确认消息,影响系统的响应速度。
- 配置复杂:相比异步复制,半同步复制的配置和管理更为复杂,需要确保主节点和从节点的插件安装和配置正确。
4. 适用场景
- 数据一致性要求较高:对于要求数据一致性和可靠性的场景,如电子商务、社交网络等,半同步复制可以提供较好的数据一致性保障。
- 网络环境较好:在网络环境较为稳定的情况下,半同步复制可以有效地提高数据的一致性和可靠性,同时保持较好的性能。
- 读写比例适中:对于读写比例适中的场景,半同步复制可以平衡数据一致性和性能的需求。
5. 不适合的场景
- 写操作非常频繁:对于写操作非常频繁的场景,半同步复制可能会导致主节点的写操作性能下降,影响系统的响应速度。
- 网络环境较差:在网络环境较差的情况下,半同步复制可能会因为网络延迟或从节点故障而导致主节点等待时间过长,影响系统的可用性。
4.1.3 同步复制
同步复制是数据库集群中的一种数据复制方式,通过确保主节点在提交事务之前所有从节点都已经接收到并应用了数据变更日志,从而实现数据的强一致性。
1. 基本原理
- 主节点:负责处理所有的写操作,并将数据变更日志(如MySQL的binlog)发送给从节点。
- 从节点:接收主节点发送的数据变更日志,并应用这些日志,更新自己的数据。
- 同步:主节点在提交事务之前,必须等待所有从节点确认已经接收到并应用了数据变更日志。
2. 优点
- 数据强一致性:通过确保所有从节点都接收到并应用了数据变更日志,同步复制可以实现数据的强一致性,避免数据不一致的问题。
- 减少数据丢失风险:即使主节点在数据变更日志传输前发生故障,只要从节点已经接收到并确认了日志,数据不会丢失。
- 高可靠性:通过多个从节点的同步复制,可以提高系统的可靠性和可用性。
3. 缺点
- 性能较低:由于主节点需要等待所有从节点的确认,写操作的性能会显著降低,尤其是在网络延迟较高或从节点较多的情况下。
- 依赖网络稳定性:如果网络不稳定或从节点故障,主节点可能需要等待较长时间才能收到确认消息,影响系统的响应速度。
- 配置复杂:相比异步复制和半同步复制,同步复制的配置和管理更为复杂,需要确保主节点和从节点的配置正确,并且网络环境稳定。
4. 适用场景
- 数据一致性要求极高:对于要求数据强一致性和可靠性的场景,如金融交易系统、医疗信息系统等,同步复制可以提供最高的数据一致性保障。
- 网络环境较好:在网络环境较为稳定的情况下,同步复制可以有效地提高数据的一致性和可靠性,同时保持一定的性能。
- 写操作较少:对于写操作较少的场景,同步复制的性能影响较小,可以接受。
5. 不适合的场景
- 写操作非常频繁:对于写操作非常频繁的场景,同步复制可能会导致主节点的写操作性能大幅下降,影响系统的响应速度。
- 网络环境较差:在网络环境较差的情况下,同步复制可能会因为网络延迟或从节点故障而导致主节点等待时间过长,影响系统的可用性。
- 从节点较多:从节点数量较多时,同步复制的性能会显著下降,管理复杂度也会增加。
4.2 多主复制
4.2.1 环形复制
环形复制是一种数据库复制方式,通过将多个节点连接成一个环状结构,每个节点既是主节点又是从节点,从而实现数据的双向同步。
1. 基本原理
- 环状结构:多个节点连接成一个环状结构,每个节点既是主节点又是从节点。
- 双向同步:每个节点将数据变更日志发送给下一个节点,下一个节点接收到日志后应用这些日志,并继续传递给下一个节点,直到数据回到起始节点。
2. 工作流程
- 节点A写操作:客户端向节点A发送写操作请求,节点A执行写操作并将数据变更记录到日志文件中。
- 日志传输:节点A将数据变更日志发送给节点B。
- 节点B应用日志:节点B接收到日志后,应用这些日志并将其发送给节点C。
- 节点C应用日志:节点C接收到日志后,应用这些日志并将其发送给节点D。
- 节点D应用日志:节点D接收到日志后,应用这些日志并将其发送回节点A。
- 节点A确认:节点A接收到日志后,确认数据同步完成。
3. 优点
- 高可用性:通过环状结构,每个节点都有备份,提高了系统的可用性和冗余性。
- 双向同步:每个节点都可以作为主节点进行写操作,实现了数据的双向同步。
- 负载均衡:可以通过多个节点分担读写操作,提高系统的整体性能。
4. 缺点
- 复杂性:环形复制的配置和管理较为复杂,需要确保每个节点的配置正确,并且网络环境稳定。
- 数据冲突:由于多个节点可以进行写操作,容易出现数据冲突,需要额外的机制来解决冲突。
- 性能影响:数据需要经过多个节点传递,可能会导致较高的网络延迟,影响系统的性能。
- 环路问题:如果某个节点出现故障或网络中断,可能会导致环路断裂,影响数据同步。
5. 适用场景
- 分布式系统:对于需要高可用性和冗余性的分布式系统,环形复制可以提供良好的数据保护和负载均衡。
- 多数据中心:在多个数据中心之间实现数据同步,提高系统的可靠性和可用性。
- 地理分布广泛:对于地理分布广泛的系统,环形复制可以确保各个地区的数据同步。
6. 不适合的场景
- 写操作非常频繁:对于写操作非常频繁的场景,环形复制可能会导致较高的网络延迟和性能下降。
- 网络环境较差:在网络环境较差的情况下,环形复制可能会因为网络中断或延迟导致数据同步问题。
- 数据冲突频繁:如果多个节点频繁进行写操作,容易出现数据冲突,需要额外的机制来解决冲突。
4.2.2 多主并行复制
多主并行复制是一种数据库复制方式,允许多个主节点同时进行写操作,并将数据变更日志并行地发送给从节点。
1. 基本原理
- 多主节点:多个节点都可以作为主节点,进行写操作。
- 并行复制:每个主节点将数据变更日志并行地发送给从节点,从节点接收到日志后并行地应用这些日志。
- 数据一致性:通过特定的机制(如冲突检测和解决)确保数据的一致性。
2. 工作流程
- 主节点写操作:客户端向任意一个主节点发送写操作请求,主节点执行写操作并将数据变更记录到日志文件中。
- 日志传输:主节点将数据变更日志并行地发送给所有从节点。
- 从节点应用日志:从节点接收到日志后,应用这些日志并返回确认消息给主节点。
- 冲突检测和解决:从节点在应用日志时,检测并解决可能的数据冲突。
- 主节点提交:主节点收到从节点的确认消息后,提交事务。
3. 优点
- 高可用性:多个主节点可以同时进行写操作,提高了系统的可用性和冗余性。
- 负载均衡:可以通过多个主节点分担写操作的压力,提高系统的整体性能。
- 并行复制:从节点可以并行地应用多个主节点的数据变更日志,进一步提高复制效率。
4. 缺点
- 复杂性:多主并行复制的配置和管理较为复杂,需要确保每个节点的配置正确,并且网络环境稳定。
- 数据冲突:由于多个主节点可以同时进行写操作,容易出现数据冲突,需要额外的机制来解决冲突。
- 性能影响:虽然并行复制可以提高复制效率,但如果网络延迟较高或从节点处理能力不足,仍然可能影响系统的性能。
- 配置和管理:需要定期检查和维护从节点,确保其正常运行,增加了运维工作的复杂性。
5. 适用场景
- 分布式系统:对于需要高可用性和冗余性的分布式系统,多主并行复制可以提供良好的数据保护和负载均衡。
- 多数据中心:在多个数据中心之间实现数据同步,提高系统的可靠性和可用性。
- 地理分布广泛:对于地理分布广泛的系统,多主并行复制可以确保各个地区的数据同步。
6. 不适合的场景
- 写操作非常频繁:对于写操作非常频繁的场景,多主并行复制可能会导致较高的网络延迟和性能下降。
- 网络环境较差:在网络环境较差的情况下,多主并行复制可能会因为网络中断或延迟导致数据同步问题。
- 数据冲突频繁:如果多个主节点频繁进行写操作,容易出现数据冲突,需要额外的机制来解决冲突。
4.3 分片集群
分片集群分为:
- 水平分片:将数据按一定规则分片,每个分片存储在不同的数据库实例中。
- 垂直分片:将数据按功能或字段分片,每个分片存储在不同的数据库实例中。
分片集群常用中间件:
- ShardingSphere:阿里巴巴开源的数据库中间件。
- MyCat:开源的数据库中间件。
- TDDL:阿里巴巴开源的分布式数据库访问层。
4.4 集群优点
- 高可用性:通过主从复制和故障切换,可以实现高可用性,即使某个节点故障,系统仍然可以继续运行。
- 负载均衡:通过负载均衡技术,可以将读写请求分发到多个节点,提高系统的并发处理能力。
- 数据冗余:通过数据复制,可以实现数据冗余,提高数据的安全性和可靠性。
4.5 集群缺点
- 复杂性增加:集群需要配置和管理多个节点,增加了系统设计和实现的复杂性。
- 数据一致性问题:在多主复制和分片集群中,数据一致性问题更加复杂,需要引入冲突解决机制。
- 网络开销:集群中节点之间的数据同步和通信会增加网络开销,影响性能。
- 资源消耗:集群需要更多的硬件资源,增加了系统的成本。