数据库数据太多导致的性能问题解决方案

数据库数据太多导致的性能问题解决⽅案
数据库数据太多跑不动怎么办?
随着业务的增长,MySQL中保存的数据会越来越多。此时,数据库很容易成为系统性能的⼀个瓶颈,单机存储容量、IO、CPU处理能⼒都有限,当单表的数据量达到1000W或100G以后,库表的增删改查操作⾯临着性能⼤幅下降的问题。
分库分表是⼀种解决办法。分库分表实际上就是对数据进⾏切分。
我们⼀般可以将数据切分,分为两种⽅式: 垂直(纵向)切分和 ⽔平(横向)切分。
垂直切分
垂直切分常见有 垂直分库 和 垂直分表 两种。
工夫在诗外1. 垂直分库驱逐出境
垂直分库就是根据业务耦合性,将关联度低的不同表存储在不同的数据库。
思想与“微服务治理”类似,将系统拆分为多个业务,每个业务使⽤⾃⼰单独的数据库。
医学整容
⽐如下图:
将应⽤拆分为客户、存款和贷款三个业务,每个业务使⽤⾃⼰单独的数据库。
2. 垂直分表
垂直分表是基于数据库中的表字段来进⾏的。业务中可能存在⼀些字段⽐较多的表,表中某些字段长度较⼤,这些长字段我们⼜只是偶尔需要⽤到,这时候我们就可以考虑将表进⾏垂直拆分了。
将某些不常⽤的,但是长度⼜很⼤的字段拎出来放到另外⼀张表。
MySQL底层是通过数据页存储的,⼀条记录占⽤空间过⼤会导致跨页,造成额外的性能开销。另外数据库以⾏为单位将数据加载到内存中,这样表中字段长度较短且访问频率较⾼,内存能加载更多的数据,命中率更⾼,减少了磁盘IO,从⽽提升了数据库性能。
保险电子商务垂直切分例⼦如下图:
我们将⼀张包含4个字段的表拆分为2张表,在业务代码⾥⾯,通过字段C1来进⾏关联。
3. 垂直切分优缺点
优点:
不同系统可以使⽤不同的库表,解决业务系统层⾯的耦合,业务清晰;
⾼并发场景下,垂直切分⼀定程度地提升IO、数据库连接数,缓解单机硬件资源的瓶颈。
缺点:
部分查询需要在业务代码逻辑⾥⾯做聚合,增加开发复杂度;
事务处理复杂,可能需要在业务代码层⾯做处理;
不能根本解决单表数据量过⼤的问题。
⽔平切分
当业务难以更细粒度地进⾏垂直切分,或者切分后单表数据依然过⼤,存在单库读写、存储性能瓶颈时候,这时候就可以考虑⽔平切分了。瓶颈问题
⽔平切分⼜可以分为 库内分表 和 分库分表。
⽔平切分是根据表内数据的内在逻辑关系,将同⼀个表按不同的条件分散到多个数据库或多个表中,每个表中只包含⼀部分数据,从⽽使得单个表的数据量变⼩,达到分布式的效果。
1. 库内分表
库内分表就是在同⼀个DB上,将表按照某种条件拆分为多张表。
⽐如⼀张订单表,我们可以依据订单的⽇期,按⽉建表。⼀⽉份的订单放month_201901这张表,⼆⽉份的订单放month_201902这张表。
库内分表只解决单表数据量过⼤问题,但没有将表分布到不同机器上, 所有请求还是在⼀台物理机上竞争cpu、内存、IO,对于减轻mysql负载压⼒来说帮助不⼤。
2. 分库分表
分库分表就是将表不仅拆分,⽽且拆分到不同机器上。
⽐如我们腾讯云上的DCDB就是这种处理⽅法。可以指定⼀张表的shardKey,然后对shardKey取hash,根据hash值将数据放到不同的数据库中, 可以解决单机物理资源的瓶颈问题。
分库分表的⽰例如下:
上⾯⽰例先根据业务耦合性垂直分库,然后再针对单个库进⾏分库分表。
3. 分库分表优缺点
优点:
不存在单库数据量过⼤、⾼并发的性能瓶颈,提升系统稳定性和负载能⼒;
应⽤端改造较⼩,不需要拆分业务模块。
缺点:
跨分⽚的事务⼀致性较难保障,⼀般需要⼀层中间件,介于业务和DB之间。对应腾讯云上的DCDB数据库所包含的Proxy层;
跨库的join关联查询性能较差。
分库分表带来的问题
分库分表能有效地缓解单机和单库带来的性能瓶颈和压⼒,突破⽹络IO、磁盘存储、CPU处理能⼒的瓶颈,同时也带来了⼀些问题。
1. 事务⼀致性问题
当更新内容同时分布在不同库中,不可避免会带来跨库事务问题。跨分⽚事务也是分布式事务,没有简单的⽅案,⼀般可使⽤”XA协议”和”两阶段提交”处理。
分布式事务能最⼤限度保证数据库操作的原⼦性,但在提交事务时需要协调多个节点,推后了提交事务的时间点,延长了事务的执⾏时间。导致事务在访问共享资源时发⽣冲突或死锁的概率增⾼。随着数据库节点的增多,这种趋势会越来越严重,从⽽成为系统在数据库层⾯上⽔平扩展的枷锁。
2. 跨节点关联查询 join 问题
切分之前,系统中很多列表和详情页所需的数据可以通过sql join来完成,⽽切分之后,数据可能分布在不同的节点上,此时join带来的问题就⽐较⿇烦了,考虑到性能,尽量避免使⽤join查询。
解决这个问题的⼀些⽅法:
2.1)全局表:
全局表,也可看做是”数据字典表”,就是系统中所有模块都可能依赖的⼀些表,为了避免跨库join查询,可以将这类表在每个数据库中都保存⼀份。这些数据通常很少会进⾏修改,所以也不担⼼⼀致性
的问题。⽐如腾讯云上的DCDB,可以创建⼴播表,其实就是全局表。每个节点都有该表的全量数据,该表的所有操作都将⼴播到所有物理分⽚(set)中。
2.2)字段冗余
⼀种典型的反范式设计,利⽤空间换时间,为了性能⽽避免join查询。例如:订单表保存userId时候,也将userName冗余保存⼀份,这样查询订单详情时就不需要再去查询”买家user表”了。
但这种⽅法适⽤场景也有限,⽐较适⽤于依赖字段⽐较少的情况。⽽冗余字段的数据⼀致性也较难保证,就像上⾯订单表的例⼦,买家修改了userName后,是否需要在历史订单中同步更新呢?这也要结合实际业务场景进⾏考虑。
云杉镇2.3)数据组装
在系统层⾯,分两次查询,第⼀次查询的结果集中出关联数据id,然后根据id发起第⼆次请求得到关联数据,最后将获得到的数据进⾏字段拼装。
3. 跨节点分页、排序、函数问题
跨节点多库进⾏查询时,会出现limit分页、order by排序等问题。分页需要按照指定字段进⾏排序,当排序字段就是分⽚字段时,通过分⽚规则就⽐较容易定位到指定的分⽚。
当排序字段⾮分⽚字段时,就变得⽐较复杂了。需要先在不同的分⽚节点中将数据进⾏排序并返回,然后将不同分⽚返回的结果集进⾏汇总和再次
排序,最终返回给⽤户。显然这个过程是会降低查询的效率,对IO,CPU也会增加额外负担。
如下图所⽰:
上图中只是取第⼀页的数据,对性能影响还不是很⼤。但是如果取得页数很⼤,情况则变得复杂很多,因为各分⽚节点中的数据可能是随机的,为了排序的准确性,需要将所有节点的前N页数据都排序好做合并,最后再进⾏整体的排序,这样的操作是很耗费CPU和内存资源的,所以页数越⼤,系统的性能也会越差。
在使⽤Max、Min、Sum、Count之类的函数进⾏计算的时候,也需要先在每个分⽚上执⾏相应的函数,然后将各个分⽚的结果集进⾏汇总、再次计算,最终将结果返回。
4. 全局主键避重问题
在分库分表环境中,由于表中数据同时存在不同数据库中,主键平时使⽤的⾃增长将⽆⽤武之地,某个分区数据库⾃⽣成的ID⽆法保证全局唯⼀。因此需要单独设计全局主键,以避免跨库主键重复问题。
总结
分库分表可以解决⼀些问题(⽐如单机的IO,CPU、磁盘瓶颈问题),但也增添了⼀些新问题(⽐如事务⼀致性问题,跨分⽚join问题)。当然随着⼀些新的NewSQL技术的成熟,分库分表这⼀⽅案也不再是业务扩张后的最优选择了,腾讯⾃研云原⽣数据库CynosDB就给出了更优的解决⽅案。

本文发布于:2024-09-21 02:46:06,感谢您对本站的认可!

本文链接:https://www.17tex.com/xueshu/694433.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:数据   数据库   业务   问题   需要
留言与评论(共有 0 条评论)
   
验证码:
Copyright ©2019-2024 Comsenz Inc.Powered by © 易纺专利技术学习网 豫ICP备2022007602号 豫公网安备41160202000603 站长QQ:729038198 关于我们 投诉建议