互联网高级架构师 潜水
  • 2发帖数
  • 2主题数
  • 0关注数
  • 0粉丝
开启左侧

我们常说的数据库优化,可以从哪些维度入手?

[复制链接]
互联网高级架构师 发表于 2021-9-26 14:27:21 | 显示全部楼层 |阅读模式 打印 上一主题 下一主题
原文链接:https://mp.weixin.qq.com/s/5mbm1qy7MWee_iUPhhrfyw
当有人问你如何对数据库进行优化时,许多人第一反应想到的就是SQL优化,如何创建索引,如何改写SQL,他们把数据库优化与SQL优化划上了等号。

当然这不能算是完全错误的回答,只不过思考的角度稍微单方面了些,太“程序员头脑”化了,没有站在更高层次来思考回答。那今天我们就将视角拔高,站在架构的角度来聊聊这一题目,数据库优化可以从哪些维度入手?


                               
登录/注册后可看大图

正如上图所示,数据库优化可以从架构优化,硬件优化,DB优化,SQL优化四个维度入手。

此上而下,位置越靠前优化越显着,对数据库的性能提拔越高。我们常说的SQL优化反而是对性能提高最小的优化。

接下来我们再看看每种优化该如何实施。

架构优化

一样平常来说在高并发的场景下对架构层进行优化其结果最为显着,常见的优化手段有:分布式缓存,读写分离,分库分表等,每种优化手段又适用于差别的应用场景。

分布式缓存

有句老话说得好,性能不够,缓存来凑。当需要在架构层进行优化时我们第一时间就会想到缓存这个神器,在应用与数据库之间增长一个缓存服务,如Redis或Memcache。


                               
登录/注册后可看大图

当接收到查询哀求后,我们先查询缓存,判断缓存中是否有数据,有数据就直接返回给应用,如若没有再查询数据库,并加载到缓存中,如许就大大减少了对数据库的访问次数,自然而然也提高了数据库性能。

不过需要注意的是,引入分布式缓存后系统需要考虑如何应对缓存穿透、缓存击穿和缓存雪崩的题目。


简朴理解一下 缓存穿透、缓存击穿 和 缓存雪崩

缓存穿透:它是指当用户在查询一条数据的时间,而此时数据库和缓存都没有关于这条数据的任何记载。这条数据在缓存中没找到就会向数据库哀求获取数据。它拿不到数据时,是会不停查询数据库,如许会对数据库的访问造成很大的压力。

缓存击穿:一个热点key刚幸亏某个时间点失效了,但是这时间突然来了大量对这个key的并发访问哀求,导致大并发哀求直接穿透缓存直达数据库,瞬间对数据库的访问压力增大。

缓存雪崩:某一个时间段内,缓存集中过期失效,如果这个时间段内有大量哀求,而查询数据量巨大,所有的哀求都会达到存储层,存储层的调用量会暴增,引起数据库压力过大甚至宕机。


读写分离

一主多从,读写分离,主动同步,是一种常见的数据库架构优化手段。

一样平常来说当你的应用是读多写少,数据库扛不住读压力的时间,接纳读写分离,通过增长从库数目可以线性提拔系统读性能。


                               
登录/注册后可看大图

主库,提供数据库写服务;从库,提供数据库读本事;主从之间,通过binlog同步数据。

当预备实施读写分离时,为了保证高可用,需要实现故障的主动转移,主从架构会有潜在主从不一致性题目。

程度切分

程度切分,也是一种常见的数据库架构优化手段。

当你的应用业务数据量很大单库容量成为性能瓶颈后,接纳程度切分,可以低落数据库单库容量,提拔数据库写性能。


                               
登录/注册后可看大图

当预备实施程度切分时,需要联合实际业务选取合理的分片键(sharding-key),有时间为了办理非分片键查询题目还需要将数据写到单独的查询组件,如ElasticSearch。

架构优化小结


  • 读写分离主要是用于办理 “数据库读性能题目”
  • 程度切分主要是用于办理“数据库数据量大的题目”
  • 分布式缓存架构可能比读写分离更适用于高并发、大数据量大场景。
硬件优化

我们利用数据库,不管是读操作还是写操作,最终都是要访问磁盘,所以说磁盘的性能决定了数据库的性能。一块PCIE固态硬盘的性能是普通机械硬盘的几十倍不止。这里我们可以从吞吐率IOPS两个维度看一下机械硬盘、普通固态硬盘、PCIE固态硬盘之间的性能指标。

吞吐率:单元时间内读写的数据量


  • 机械硬盘:约100MB/s ~ 200MB/s
  • 普通固态硬盘:200MB/s ~ 500MB/s
  • PCIE固态硬盘:900MB/s ~ 3GB/s
IOPS:每秒IO操作的次数


  • 机械硬盘:100 ~200
  • 普通固态硬盘:30000 ~ 50000
  • PCIE固态硬盘:数十万
通过上面的数据可以很直观的看到差别规格的硬盘之间的性能差距非常大,当然性能更好的硬盘价格会更贵,在资金充足并且迫切需要提拔数据库性能时,尝试更换一下数据库的硬盘不失为一个非常好的举措,你之前遇到SQL实行迟钝题目在你更换硬盘后很可能将不再是题目。

DB优化

SQL实行慢有时间不一定完满是SQL题目,手动安装一台数据库而不做任何参数调解,再怎么优化SQL都无法让其性能最大化。要让一台数据库实例完全发挥其性能,起首我们就得先优化数据库的实例参数。

数据库实例参数优化遵循三句口诀:日记不能小、缓存充足大、连接要够用。

数据库事务提交后需要将事务对数据页的修改刷( fsync)到磁盘上,才能保证数据的持久性。这个刷盘,是一个随机写,性能较低,如果每次事务提交都要刷盘,会极大影响数据库的性能。数据库在架构设计中都会接纳如下两个优化手法:


  • 先将事务写到日记文件RedoLog(WAL),将随机写优化成顺序写
  • 加一层缓存结构Buffer,将单次写优化成顺序写
所以日记跟缓存对数据库实例尤其重要。而连接如果不够用,数据库会直接抛出非常,系统无法访问。

接下来我们以Oracle、MySQL(InnoDB)、POSTGRES、达梦为例,看看每种数据库的参数该如何配置。

Oracle

参数分类参数名参数值备注数据缓存SGA_TAGET、MEMORY_TARGET物理内存70-80%越大越好数据缓存DB_CACHE_SIZE物理内存70-80%越大越好SQL解析SHARED_POOL_SIZE4-16G不建议设置过大监听及连接PROCESSES、SESSIONS、OPEN_CURSORS根据业务需求设置一样平常为业务预估连接数的120%其他SESSION_CACHED_CURSORS大于200软软解析

MySQL

参数分类参数名参数值备注数据缓存INNODB_BUFFER_POOL_SIZE物理内存50-80%一样平常来说越大性能越好日记相关Innodb_log_buffer_size16-32M根据运行环境调解日记相关sync_binlog1、100、01安全性最好监听及连接max_connections根据业务环境调解可以预留一部门值文件读写性能innodb_flush_log_at_trx_commit2安全和性能的折中考虑其他wait_timeout,interactive_timeout28800制止应用连接定时中断

POSTGRES

参数分类参数名参数值备注数据缓存SHARED_BUFFERS物理内存10-25%
数据缓存CACHE_BUFFER_SIZE物理内存50-60%
日记相关wal_buffer8-64M不建议设置过大过小监听及连接max_connections根据业务环境调解一样平常为业务预估连接数的120%其他maintenance_work_mem512M或更大
其他work_mem8-16M原始配置1M过小其他checkpoint_segments32或者更大

达梦数据库

参数分类参数名参数值备注数据缓存MEMROY_TARGET、MEMROY_POOL物理内存90%
数据缓存BUFFER物理内存60%数据缓存数据缓存MAX_BUFFER物理内存70%最大数据缓存监听及连接max_sessions根据业务需求设置一样平常为业务预估连接数的120%

SQL优化

SQL优化很轻易理解,就是通过给查询字段添加索引或者改写SQL提高其实行服从,一样平常而言,SQL编写有以下几个通用的本事:


  • 合理利用索引
索引少了查询慢;索引多了占用空间大,实行增删改语句的时间需要动态维护索引,影响性能 选择率高(重复值少)且被where频繁引用需要建立B树索引;一样平常join列需要建立索引;复杂文档类型查询接纳全文索引服从更好;索引的建立要在查询和DML性能之间取得平衡;复合索引创建时要注意基于非前导列查询的环境


  • 利用UNION ALL替代UNION
UNION ALL的实行服从比UNION高,UNION实行时需要排重;UNION需要对数据进行排序


  • 制止select * 写法
实行SQL时优化器需要将 * 转成具体的列;每次查询都要回表,不能走覆盖索引。


  • JOIN字段建议建立索引
一样平常JOIN字段都提前加上索引


  • 制止复杂SQL语句
提拔可阅读性;制止慢查询的概率;可以转换成多个端查询,用业务端处置惩罚


  • 制止where 1=1写法
  • 制止order by rand()雷同写法
RAND()导致数据列被多次扫描

实行计划

要想优化SQL必须要会看实行计划,实行计划会告诉你哪些地方服从低,哪里可以需要优化。我们以MYSQL为例,来认识一下实行计划。

通过explain sql 可以查看实行计划,如:


                               
登录/注册后可看大图

字段表明id每个被独立实行的操作标识,标识对象被操作的顺序,id值越大,先被实行,如果相同,实行顺序从上到下select_type查询中每个select 字句的类型table被操作的对象名称,通常是表名,但有其他格式partitions匹配的分区信息(对于非分区表值为NULL)type连接操作的类型possible_keys可能用到的索引key优化器实际利用的索引(最重要的列) 从最好到最差的连接类型为const、eq_reg、ref、range、index和ALL。当出现ALL时表现当前SQL出现了“坏味道”key_len被优化器选定的索引键长度,单元是字节ref表现本行被操作对象的参照对象,无参照对象为NULLrows查询实行所扫描的元组个数(对于innodb,此值为估计值)filtered条件表上数据被过滤的元组个数百分比extra实行计划的重要增补信息,当此列出现Using filesort , Using temporary 字样时就要小心了,很可能SQL语句需要优化

SQL优化实战

这里为大家预备了一套SQL优化的综合实战,一步一步带你走一遍完整SQL优化的过程。

在实行优化之前我们需要先认识一下原始表及待优化的SQL。


  • 原数据库表结构
CREATE TABLE `a`(    `id`          int(11) NOT NULL AUTO_INCREMENT,    `seller_id`   bigint(20)                                       DEFAULT NULL,    `seller_name` varchar(100) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL,    `gmt_create`  varchar(30)                                      DEFAULT NULL,    PRIMARY KEY (`id`));CREATE TABLE `b`(    `id`          int(11) NOT NULL AUTO_INCREMENT,    `seller_name` varchar(100) DEFAULT NULL,    `user_id`     varchar(50)  DEFAULT NULL,    `user_name`   varchar(100) DEFAULT NULL,    `sales`       bigint(20)   DEFAULT NULL,    `gmt_create`  varchar(30)  DEFAULT NULL,    PRIMARY KEY (`id`));CREATE TABLE `c`(    `id`         int(11) NOT NULL AUTO_INCREMENT,    `user_id`    varchar(50)  DEFAULT NULL,    `order_id`   varchar(100) DEFAULT NULL,    `state`      bigint(20)   DEFAULT NULL,    `gmt_create` varchar(30)  DEFAULT NULL,    PRIMARY KEY (`id`));



  • 待优化的SQL(查询当前用户在当前时间前后10个小时的订单环境,并根据订单创建时间升序排列)
select a.seller_id,       a.seller_name,       b.user_name,       c.statefrom a,     b,     cwhere a.seller_name = b.seller_name  and b.user_id = c.user_id  and c.user_id = 17  and a.gmt_create    BETWEEN DATE_ADD(NOW(), INTERVAL – 600 MINUTE)    AND DATE_ADD(NOW(), INTERVAL 600 MINUTE)order by a.gmt_create;



  • 原表数据量:

                               
登录/注册后可看大图


  • 原实行时间

                               
登录/注册后可看大图

0.21s,实行速度还挺快


  • 原实行计划

                               
登录/注册后可看大图

真是糟糕的实行计划。(全表扫描,没有索引;临时表;排序)

初步优化思路:


  • SQL中 where条件字段类型要跟表结构一致,表中user_id 为varchar(50)类型,实际SQL用的int类型,存在隐式转换,也未添加索引。将b和c表user_id 字段改成int类型。
  • 因存在b表和c表关联,将b和c表user_id创建索引
  • 因存在a表和b表关联,将a和b表seller_name字段创建索引
  • 利用复合索引消除临时表和排序
初步优化SQL

alter table b modify `user_id` int(10) DEFAULT NULL;alter table c modify `user_id` int(10) DEFAULT NULL;alter table c add index `idx_user_id`(`user_id`);alter table b add index `idx_user_id_sell_name`(`user_id`,`seller_name`);alter table a add index `idx_sellname_gmt_sellid`(`gmt_create`,`seller_name`,`seller_id`);


查看优化后的实行时间


                               
登录/注册后可看大图

通过实行计划可以看到,实行时间从0.21s优化成了0.01s,实行时间近乎缩短20倍。
查看优化后的实行计划


                               
登录/注册后可看大图

实行计划表现从全表扫描优化成了走索引,rows减少,但是此时出现了2个告警。
通过show warning语句 查看告警信息


                               
登录/注册后可看大图

提示gmt_crteate 的格式不对,mysql进行了隐式转换导致不能利用索引。

继承优化,修改gmtc-create的格式

alter table a modify "gmt_create" datetime DEFAULT NULL;


再次查看实行时间


                               
登录/注册后可看大图

再次查看实行计划


                               
登录/注册后可看大图

至此,我们的优化过程结束,结果非常完美。

SQL优化小结

这里给大家总结一下SQL优化的套路:


  • 查看实行计划 explain sql
  • 如果有告警信息,查看告警信息 show warnings;
  • 查看SQL涉及的表结构和索引信息
  • 根据实行计划,思考可能的优化点
  • 按照可能的优化点实行表结构变更、增长索引、SQL改写等操作
  • 查看优化后的实行时间和实行计划
  • 如果优化结果不显着,重复第四步操作


小结

我们今天分别从架构优化、硬件优化、DB优化、SQL优化四个角度探讨了如何实施优化,提拔数据库性能。但是大家还是要记住一句话,数据库系统没有银弹, 要让得当的系统,做合适的事情。
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

猜你喜欢
在线客服邮箱
wxcy#wkgb.net

邮箱地址#换为@

Powered by 创意电子 ©2018-现在 专注资源实战分享源码下载站联盟商城