嘴对嘴教你讲数据库优化

前言

最近学起来了,心里火烧起来了,所以开一个新的专栏,狠狠的充实自己,顺便卷一下大家。说是卷,其实这个专栏相当务实,务实到了能拿来即用,喜欢的人肯定会很多,之前写过的如何挖掘项目亮点 的高收藏证明了这一点。该专栏结构和以往不同,除开保留节目的前言和写在最后,中间会有口播和微醺码头两个篇章。口播自然是大家最喜欢的桥段,我会用口语化的方式来讲解一整块的知识,真实做到我就是你们互联网的嘴替。码头篇会整点薯条,也就是一些零碎的小知识,我之前一些没法做出成体系知识输出的小技巧或者知识点有了一席之地。话不多说,口播开始。

口播

数据库优化是一个大问题,但是我们依旧可以找出一些通用解。优化思想整体遵照开源节流的思想以及软硬件双管齐下的方针执行,在数据库这一块总的可以分为三个大方向,减少数据量、空间换时间、更换架构。

接下来讲一讲经典关系型数据库MySQL的通用手段,首先可以想到的是最直接的硬件和实现层优化。硬件层属于成本比较高的,但也是上限最高的,钞能力解决所有问题。我们一般会从实现层入手,比如修改SQL或者合理利用索引,这种手段属于效果明显但上限较低,因此革命性的性能突破还是要放在存储结构和系统上面。

回到一开始的三大方向,减少数据量,由于MySQL索引接口基本固定B+Tree,因此时间复杂度O(logn),存储结构是行式存储,这一块从结构本身上无法变动了。所以得想想别的法子,我这里有四个思路:压缩字段数、数据归档、生成中间表、分库分表。

压缩字段数的手段比较局限,一般常见于设计阶段,将非检索的多个字段,改成JSON或是其他有规则地字符串,压缩成一个字段。比如订单详情里面地描述、备注之类的,看情况进行压缩。

数据归档在不新增中间件的情况下,可以选择低频率多次迁移少量非热点数据,到一张归档表,并且增加新的业务入口路由到对应的历史表。

生成中间表是日常开发中比较容易遇到的场景,我之前做的看板项目,就全部运用了这种优化手段。核心思想就是通过定时调度任务将复杂查询结果跑出来,单独存到一张额外的物理表,因为是汇总后的数据,所以也算是对原有数据源所有数据的压缩。

分库分表虽然是经典的优化手段,但是成本属实是太高了,应尽量避免选择这种方案,优先选择NoSQL进行优化,也可以选择新时代的分布式数据库比如TIDB来解决问题。但是作为曾经的优秀方案,我们依旧需要了解细节,比如两种拆分方式。垂直拆分方式,主要是根据业务做冷热字段隔离,常见与列表和详情这样的业务,但是原理是要减少数据库表中单行数据,innodb默认单页为16K,为了减少磁盘IO次数,因此单行数据越小,一个内存页能存下的数据行越多。咱们常常听到MySQL单表数据量保持在2-3kw比较好,但是这里没有提到的是,单行数据越大越容易提前触碰到单表性能瓶颈。除了垂直拆分还有水平拆分,这种拆分更符合大众对拆分的理解,这里主要是对数据行的拆分。比如一张2kw数据的表,拆分成两张1kw的表,通过降低单表数据总量的方式来提升性能。但是由此引发了新的问题,如何分散到不同的物理表,常见有两种方式,区间范围和HASH。区间范围一般常见的是时间区间,比如按月或者按天存放一张表,优点是查询很简单,见名知意,缺点就是分片数量不均。HASH的优点和缺点则是刚好相反。与分库分表的优点相比,他的问题和成本仍显得十分突出,不到万不得已,尽量不要用。

空间换时间有点类似于堆硬件,本质上是用额外的资源来提升性能,常见有两种方案分布式缓存和集群。

分布式缓存一般使用NoSQL比如Redis,缓存策略则一般使用旁路缓存,其思路分为查询和更新两种情况,查询先查缓存没有就查数据库返回并把数据存入缓存,更新则是先修改数据库,再删除缓存,这里如果考虑极端场景可以选择延时双删。缓存的应用场景主要是应对高并发读,同时一些长时间不会变动的数据比如配置信息也可以选择使用缓存。

集群比如一主多从,通过中间件或者自写的路由算法来实现读写分离,降低并发读的压力。现在比较流行的代理层中间件比如ShardingSphere,在代码实现层面会比较方便。但是一主多从本身并不是一个好的选择,相对于分片副本之类的实现来说,主从数据完全冗余,会增加过高的硬件成本,并且过多的从库会显著增加主库进行主从同步的压力。

最后的手段是更换架构,选择一个符合自己业务场景的非关系型数据,比如Redis、HBase、MongoDb、ES、ClickHouse。有两种更换方式,一种是写在关系型数据库,读在非关系性数据库,另一种就是完全迁移到非关系性数据库。简单举一个经典日志场景,就很适合完全使用ES来存储,因为不需要用到关系型数据库的ACID特性。

来码头整点薯条

MySQL常用优化手段

优化缓冲池BufferPool

检查当前InnoDB缓冲池的性能

show status like 'innodb_buffer_pool_read%';

image.png

InnoDB buffer pool 命中率 = innodb_buffer_pool_read_requests / (innodb_buffer_pool_read_requests + innodb_buffer_pool_reads ) * 100

7871383129/(7871383129+377797413)=0.9542018251296021 (分母和为8249180542)

此值低于99%,则可以考虑增加innodb_buffer_pool_size。

image.png

查询InnoDB缓冲池

show variables like 'innodb_buffer_pool%';

image.png

公式innodb_buffer_pool_size=(1024*1024)/innodb_buffer_pool_chunk_size/innodb_buffer_pool_instances。这里默认134217728/1024/1024=128MB。同时需要了解三个重要参数,innodb_buffer_pool_chunk_size是块大小,默认128M。innodb_buffer_pool_instances是缓冲池实例的数量,在具有大量内存的系统上,可以通过将缓冲池划分为多个来提高并发性。

调整策略

Linux查看当前内存

image.png

一般增加和减少buffer pool的大小都是以块的方式,块的大小由参数innodb_buffer_pool_chunk_size决定,默认为128M。

Innodb_buffer_pool_size的大小可以自行设定,推荐配置为系统内存的50%至75%,并且必须是innodb_buffer_pool_chunk_size 乘以 innodb_buffer_pool_instances的整数倍,如果不是,则buffer pool会被调整成大于设定值且最接近的一个值,如下例:默认 128MB * 16 = 2048 MB (2G) 但是 buffer_pool_size = 9G ,不是整倍数,因此调整为10G

优化连接数

查询最大连接数以及最大使用连接数

show variables like 'max_connections'

show status like 'max_used_connections'

查询当前用户被允许的最大连接数,0表示不受限

show variables like 'max_user_connections'

优化修改参数

max_connections=1000(set GLOBAL max_connections=1000;)

优化超时时间

查询超时时间相关

show variables like '%timeout%';

连接过程中握手的超时时间默认为10s,建议调大

connect_timeout=20

存疑:之前有连接池存在连接失效问题,试了很多种解决方式,这是其中一种,未验证。

简单聊聊

现在是晚上九点半,有点疲惫,想聊聊一些分布式数据库的简单想法。最近团队在主推TiDB,我也准备在后面在团队内出一篇TiDB的科普文章,带大家来细致了解下新一代的数据库。当然MySQL还是在用,集群搭的双主,监控手段很有限,我也在尽可能的去进行一些优化。但是老是感觉就像个黑箱,监控手段太少了,一旦出问题,备份、恢复等感觉都很麻烦,当然应该是我见识浅薄,没见过做得好的。但是从我看到TiDB这个自带看板的时候,我感觉是做的真好,想要的都有,Top Sql可以监控Cpu耗时较多的SQL,慢查询和MySQL差不多但是增加了最大内存的指标,服务器的诊断和监控更是详细的不行。除此之外,基于分布式架构,升级扩容也很方便,基本上算是干掉了传统的分库分表,备份和恢复官方也有详细的实现方案,感觉文档写的很详细。不过因为是兼容MySQL,内部一些优化器的逻辑可能与MySQL的不同,因此优化的手段可能有了变化,这一点需要重新学习,不过我觉得没啥大问题,毕竟官方文档写的还不错。

目前我是看到了分布式数据库带来的好处,还缺乏细致的了解,不过我认为这应该是一个流行趋势,毕竟就我们团队现在TiDB的体验来看,优点已经蒙蔽了双眼。不过面对新的东西,还是要保持谨慎的态度,一段时间后我会带来我的一个科普和体验分享。

image.png

写在最后

掘金人气作者我最后好像是128名,差点...也不是差点吧,和100名差的还不少,都不敢说遗憾了,哈哈。之前写的年终总结虽然被系统推荐了,但是因为元旦流量的影响只有2K的展现,这里手动给自己推一下吧,远古的火箭追着我跑,跑过了2022走进了2023,没看过的大佬们走过路过不要错过,里面有我对自己文章的自评,以及第一年写文的长篇总结。马上春节了,下周还要开新项目,我很头大,简直要麻了,还要强制加班,我是真的裂开,京城牢头冤种一等兵就是我了。春节前如果有机会我会再更一篇,可能和Flink有关。如果没有更新,那我是鸽子,去微醺码头整薯条了,这里就提前祝大家春节快乐了。

猜你喜欢

转载自juejin.im/post/7186444714042720313
今日推荐