Java开发 - 不知道算不算详细的MySQL多维度性能优化剖析

利用机器学习优化定价纽约市出租车费用预测 该竞赛是由Google Cloud与Coursera合作举办的,旨在通过机器学习技术来预测纽约市出租车的乘车费用(包括过路费)。任务要求预测根据乘车起点和终点的坐标,计算出出租车的收费金额。通过机器学习技术,模型应能比简单的基于距离估算模型更准确地预测费用,后者通常会产生5到8美元的RMSE误差。竞赛提供了一个挑战:使用更先进的技术来提升模型的准确性,达到更低的误差水平。评估标准是根均方误差(RMSE),该指标衡量模型预测结果与实际结果之间的差异。 阅读详情

前言

MySQL性能优化是一个很大的话题,小到一句SQL,大到一个系统,都是我们优化的目标,博主之前曾写过一篇关于SQL优化的博客,感兴趣的小伙伴直接点击即可。本篇,我们将从多个维度来讲解MYSQL性能优化相关的内容,读完此篇,你将初步了解有哪些MySQL的优化策略,以及怎么去进行MySQL的性能优化。下面,我们直奔主题吧!

优化介绍

关于优化,我们不能够断章取义,有时候我们会直接去网上搜一些优化相关的博客,然后照着做。这是不对的,起码不是百分百正确,套路是这个套路,但优化就像不同的人去买衣服,每个人都有自己的特殊情况,我们要具体情况具体分析,毕竟不是每个人的应用和服务器都是一样的,千人千面用在这里再好不过了。

MySQL几乎是目前绝大多数互联网公司的选择,出色的性能,低廉的成本,丰富的资源深受大众的喜爱。所以本文我们将MySQL作为我们的目标数据库。

但优化有风险,优化需谨慎。风险来源在于以下几点:

  • 优化一般针对的是一个复杂的且已经上线的系统;
  • 优化是把双刃剑,可能提高性能,也可能降低性能;
  • 优化之前,要提前预测好可能出现的问题,将有可能出现的后果控制在可接受范围内,做好灾情预警方案;
  • 一般优化肯定是遇到了问题,保持现状就是风险;

所以,优化可能有这么多的问题存在,那我们为什么还要做优化呢?这是因为大多数已知的优化会给我们带来优质的体验。就好比吃多了真的会撑死,我们为什么还要吃饭呢?

在优化时,我们一般会考虑业务的稳定性和可持续性,优化不是单纯的进行SQL的优化,还涉及到整体的业务,任何脱离开业务的优化都是扯淡。

优化也不是一个两个人就可以做的,必定是以团队为基础进行实施,当然,前提是公司部门分工明确的情况下,因为一般公司权限控制都很严格,不是说动就随时能动的,大家都明白的。

优化的方向上,我们一般分为两个方向:

  • 安全,保证数据安全
  • 性能,高性能数据访问

如果你能想到第三个方向,欢迎留言一起讨论。关于安全方面,博主后期会针对分布式锁给大家进行讲解,分布式事务在上一篇已经给大家讲解过,所以在本篇,我们仅针对性能跟大家进行分析讨论。

这里有一张优化方向和效果的展示图,大家看看:

这张图很经典,希望大家记住这个变化的方向。

到这里,就是性能相关的介绍,想必你对MySQL优化的前提条件已经基本了解,下面,我们就开始对优化的具体内容展开说明。

常规SQL优化

查询优化

先奉上一张数据库的查询流程图:

我想,关于查询的具体步骤就不必向大家讲解太多了,否则就有点啰嗦。但关于里面的步骤的作用还是有必要一探究竟的。

查询缓存:数据库解析一个SQL语句前,如果查询缓存是开启的,MySQL就会判断当前查询是否能够命中缓存中的数据,如果命中,则直接从缓存中拿出相应的数据返回给客户端,此时不会解析SQL,不生成执行接话,不执行查询操作。

语法解析和预处理器:MySQL通过关键字对SQL进行解析,生成对应的解析树,接着MySQL就会根据自己的语法规则进行验证和解析查询。

查询优化树:语法树被效验合法后,由优化器转成查询计划。一条SQL会有多种执行方式,优化器的作用就是找到最合适的那个方式来执行本条SQL。

查询执行引擎:根据图,在解析和优化后,将生成对应的执行计划,查询引擎就根据这个执行计划来执行SQL,最常用的执行引擎是默认的innoDB,还有一种引擎也比较常见,叫MyISAM。

SQL是我们查询的主要手段,也是表面上我们打交道最多的东西,所以很大成分的优化都是在这个维度上展开的,而SQL的优化手段分为两种,慢日志查询和EXPLAIN分析查询。

慢日志查询

默认的慢日志查询是关闭的,查看状态可根据如下命令:

show variables like '%slow_query_log%';

接下来我们开启慢SQL日志 :

set global slow_query_log=1;

并重新查看状态:

设置慢查询时间临界点:

set long_query_time = 1;

设置慢查询存储的方式,默认是FILE,可修改为TABLE:

set global log_output='TABLE';

查询慢查询日志的开启状态和慢查询日志储存的位置:

show variables like '%quer%';

参数注意:

slow_query_log : 是否已经开启慢查询

slow_query_log_file : 慢查询日志文件路径

long_query_time : 超过多少秒的查询就写入日志

log_queries_not_using_indexes 如果值设置为ON,则会记录所有没有利用索引的查询(性能优化时开启此项,平时不要开启)

发现,慢日志查询已开启时,如果重启MySQL,会自动关闭,需要在 /etc/my.cnf 或 /etc/mysql/my.cnf 文件中添加如下:

slow_query_log=ON
slow-query-log-file=/var/lib/mysql/slow-query.log
long_query_time=0

修改完重启mysql:

service mysqld restart

永久开启博主觉得没人会这么做吧?

关于慢查询日志的分析,应该没人还不会用mysqldumpslow吧?由于它是mysql自带工具,使用简单,所以很是比较受欢迎的,也有一些需要单独安装的工具,比如pt-query-digest,看个人习惯吧。

mysqldumpslow的使用很简单:

mysqldumpslow -s c -t 10 /var/lib/mysql/8e46c78ba828-slow.log

后面的路径要填上面我们查询出来的路径,这里解释下里面字母的含义:

-s代表排序方式,c为排序的选项之一,总共有c,t,l,r四种排序方式,分别是:记录次数,时间,查询时间,返回的记录数,如果想要倒叙,就在字母前加一个a,ac,at,al,ar。

-t代表top n的意思,这里是10,也就是top10的数据。

简单做个测试:

可以在途中的最后看到我们查询的语句,这也是mysqldumpslow 的一大优点之一,毕竟我们是要看具体哪条SQL查询的比较慢的。但要注意,慢日志查询还是比较耗性能的,一般不要随便开启,一旦使用,就是在生产环境,用到时开启,用完后关闭即可。

EXPLAIN分析查询

EXPLAIN关键字可以模拟优化器执行SQL查询语句,就可以知道MySQL是如何处理SQL语句的,EXPLAIN的作用如下:

  • 查看表的读取顺序;
  • 查看哪些索引被用到;
  • 查看表之间的引用关系;
  • 查看被优化器查询的数据有多少行;

EXPLAIN使用起来也比较简单:

explain sql语句

比如:

这里博主只是简单的一张表查询,下面我们来做个多表查询:

创建三张最简单的表:

create table    t1(
        id int primary key,
        name   varchar(20),
        col1   varchar(20),
        col2   varchar(20),
        col3   varchar(20) 
);
create table   t2(
        id int primary key,
        name   varchar(20),
        col1   varchar(20),
        col2   varchar(20),
        col3   varchar(20) 
);
create table   t3(
        id int primary key,
        name   varchar(20),
        col1   varchar(20),
        col2   varchar(20),
        col3   varchar(20) 
);
insert into    t1 values(1,'zs1','col1','col2','col3');
insert into    t2 values(1,'zs2','col2','col2','col3');
insert into    t3 values(1,'zs3','col3','col2','col3');
create index   ind_t1_c1  on t1(col1);
create index   ind_t2_c1  on t2(col1);
create index   ind_t3_c1  on t3(col1);
create index   ind_t1_c12 on t1(col1,col2);
create index   ind_t2_c12 on t2(col1,col2);
create index   ind_t3_c12 on t3(col1,col2); 

接着执行下面的explain语句:

explain select t2.* from t1,t2,t3 where t1.id = t2.id and t1.id = t3.id and t1.name = 'zs'; 

 下面我们来解释下各值的作用:

  •  id:id值越大,优先级越高,如果想等,则从上到下开始;
  • select_type
    • SIMPLE : 简单的select查询,查询中不包含子查询或者UNION
    • PRIMARY: 查询中若包含复杂的子查询,最外层的查询则标记为PRIMARY
    • SUBQUERY : 在SELECT或者WHERE列表中包含子查询
    • DERIVED : 在from列表中包含子查询被标记为DRIVED衍生,MYSQL会递归执行这些子查询,把结果放到临时表中
    • UNION: 若第二个SELECT出现在union之后,则被标记为UNION,若union包含在from子句的子查询中,外层select被标记为derived
    • UNION RESULT: 从union表获取结果的select
  • table:这一行和哪张表有关,是哪张表的;
  • type:type显示的是访问类型,是一个重要指标,结果值从最好到最坏依次是system > const > eq_ref > ref > fulltext > ref_or_null > index_merge > unique_subquery > index_subquery > range(尽量保证) > index > ALL,一般需要保证查询是range,最好是ref
    • system:表中只有一行记录(系统表),这是const类型的特例, 基本上不会出现
    • const:通过索引一次查询就找到了,const用于比较primary key或者unique索引,该表最多有一个匹配行,在查询开始时读取。由于只有一行, 因此该行中的值可以被优化器的其余部分视为常量。const 表非常快, 因为它们只读一次
    • eq_ref:读取本表中和关联表表中的每行组合成的一行。除 了 system 和 const 类型之外, 这是最好的联接类型。当连接使用索引的所有部分时, 索引是主键或唯一非 NULL 索引时, 将使用该值
    • ref :非唯一性索引扫描,返回匹配某个单独值的所有行,本质上也是一种索引访问,它返回所有符合条件的行
    • range : 只检索给定范围的行, 使用一个索引来选择行,key列显示的是真正使用了哪个索引,一般就是在where条件中使用between,>,<,in 等范围的条件,这种在索引范围内的扫描比全表扫描要好,因为它只在某个范围中扫描,不需要扫描全部的索引
    • index : 扫描整个索引表, index 和all的区别为index类型只遍历索引树,这通常比all快,因为索引文件通常比数据文件小,虽然index和all都是读全表,但是index是从索引中读取,而all是从硬盘中读取数据
    • all: 全表扫描 :将遍历全表以找到匹配的行
  • key:真正使用的索引,如果为null,表示没有使用索引,这个比较常用
  • key_len:索引中使用的字节数,可通过该列计算查询中使用的索引的长度,长度越短越好
  • ref:显示索引的哪一列被使用了,如果可能的话,是一个常数。表示哪些列或者常量被用于查找索引列上的值
  • rows:根据表统计信息及索引选用的情况,估算并找出所需记录要读取的行数 (有多少行记录被优化器读取) ,越少越好
  • extra:包含不适合在其他列中显示但十分重要的额外信息。

其实这里你能用到的信息很少,回看关键数据就行,主要看有没有使用我们预期的索引,判断索引是否生效,其他的一般不太用得到,但也要具体情况具体分析。

索引优化

关于索引的数据结构,可看这篇博客:索引的数据结构

这里仅说明索引失效的几种情况,方便大家对号入座:

  • 全值匹配,这是查询大忌,尽量用到什么给什么;
  • 最左前缀法则,如果索引有多列,要从左开始,并不跳过中间的索引,比如A,B,C三个索引,使用时,不能直接用BC,AC直接查,但可以AB,ABC使用,否则索引失效;
  • 不在索引列上做任何操作(计算、函数、(自动or手动)类型转换),如果做的话,会导致索引失效而转向全表扫描;
  • 存储引擎不能使用索引中范围条件(bettween、<、>、in等)右边的列(范围条件右边与范围条件使用的同一个组合索引,右边的才会失效,若是不同索引则不会失效);
  • mysql5.7 在使用不等于(!= 或者<>)的时候无法使用索引会导致全表扫描,但8.0不会;
  • mysql5.7 is not null无法使用索引,但是is null是可以使用索引的,但8.0不会
  • like以%开头('%abc...')mysql索引失效会变成全表扫描的操作
  • 字符串不加单引号索引失效 ( 底层进行转换使索引失效,使用了函数造成索引失效)(隐式类型转换)

 一般在开发中,当要进行调优时,需要有一定的依赖信息,可以通过show status like 'Handler_read%';查看索引的使用情况:

handler_read_key:这个值越大说明使用索引查询到的次数越多。

handler_read_rnd_next:这个值越高,说明查询越低效。

基于此,再去进行优化,如果这里数据很好,那就没这个必要。 

数据库优化

表结构优化

表结构优化其实很简单,在创建表的时候对字段进行约束就可以,但最简单的往往是最容易让人忽略的地方,下面,博主大致列出需要注意的地方:

  • 将表字段定义为NOT NULL约束,因为MySQL中空值的列不好进行查询优化,NULL值会使索引以及索引的统计信息变得很复杂;
  • 对于一些特定类型的字段,比如性别,可用布尔;类型,可用枚举;
  • 对于一些数值类型的字段,尽量准确使用其类型,比如年龄,简单的int就可以,甚至使用TINYINT(4)、SMALLINT(6)、MEDIUM_INT(8)作为整数类型而非INT,非负则加上UNSIGNED
  • VARCHAR的长度控制为需要的长度,比如身份证号码,位数难道还有超过18位的?
  • 使用TIMESTAMP而非DATETIME,但TIMESTAMP只能表示1970 - 2038年,比DATETIME表示的范围小得多,而且TIMESTAMP的值因时区不同而不同;
  • 单表不要有太多字段,建议在20以内;
  • 合理的加入冗余字段可以提高查询速度,比如用户表和角色表,你难道还要通过用户角色关系去查角色吗?干脆直接在用户表中增加一个角色的字段,这就是冗余。

分库分表

垂直拆分

其实分库分表本不应该出现在这里,这已经是微服务架构的内容,这里提供思路,详细的分库分表方式不在此处进行说明。

以表为例,垂直拆分是将一张表中的多个字段拆分成几张表,拆分后的表具有不同的结构,更少的列,但其缺点也比较明显,插入数据时需要使用事务,查询数据时需要关联查询。

以库为例,是将不同的模块单独分配一个数据库,比如购物车数据库,订单数据库,个人信息数据库这样。

当然,你也可以选择分库分表同时存在,只是会相对麻烦,还需要高可用的架构模式,Haproxy+keepalived+mycat,但目前的微服务我们一般使用在水平拆分上会多一些。主要还是看项目的体量,微服务真的很花服务器的钱。

水平拆分

水平拆分和垂直拆分不同。

以表为例,水平拆分就像是将一张表的结构复制了多份,水平拆分后的表,结构完全相同,存储的时候需要按照一定的规则或者权重存储到不同的表中,这里多会使用mycat进行拆分,读取的时候mycat也会帮助我们去不同的表中读取。

以库为例,水平拆分后的数据库结构完全一样,里面的表完全一样,表中的字段完全一样,除了表中存储的数据,其他都一样,也是按照一定的规则权重进行存储,一般到这里多半是上了微服务架构,高可用的Haproxy+keepalived+mycat负载均衡集群了解一下。

此处不再对具体的技术进行详细说明,后期有时间会给大家单独出一篇手把手教程。

读写分离

上了一定量级的服务器难免会遇到高并发的问题,如果还是只有一台服务器难免顾此失彼,无暇他顾,就会面临数据库崩溃,数据丢失的问题,要是碰到顾客下单,那真是亏大发了,为了解决这个问题,就有了读写分离的思想,甚至是主从复制,主主复制,级联复制等等一系列的数据库架构,关于此,博主推荐两篇前些时日写的博客:

Java开发 - MySQL主从复制初体验

Java开发 - 读写分离初体验

这里就不再过多的阐述了,相信大家对此也多有了解,这两篇博客基本上能说的七七八八,入个门不在话下。 

集群

这里只是提一嘴,如果需要更大的布局,就需要使用集群,主要目的是异地容灾,虽然目前大多数的服务器可能连正儿八经的微服务都没有实现,但这并不妨碍我们对这个东西要有一定的了解,关于集群,其实也是高可用负载均衡Haproxy+keepalived+mycat可以实现的功能,也许还有别的方式,博主熟悉的就是这种,后期再出教程吧,不再这里参杂了,我怕写10w的字。

存储引擎优化

InnoDB简介

InnoDB存储引擎提供了具有提交、回滚和崩溃恢复能力的事务安全,相比较MyISAM存储引擎,InnoDB写的处理效率要差一点,并且会占用更多的磁盘空间保留数据和索引。InnoDB提供了对数据库事务ACID(原子性Atomicity、一致性Consistency、隔离性Isolation、持久性Durability)的支持,实现了SQL标准的四种隔离级别。这点是MyISAM不具备的,MyISAM毕竟是非事务型数据库。

InnoDB设计的初衷就是处理大容量的数据,MySQL运行时,InnoDB会在内存中建立缓冲池,用于缓冲数据和索引。

在执行函数操作“select count(*) from table”语句时需要扫描全表,因为使用innodb引擎的表不会保存表的具体行数,需要扫描整个表才能计算多少行,是幸,也是不幸。

InnoDB引擎是行锁,粒度更小,所以写操作不会锁定全表,在并发较高时,使用InnoDB会提升效率。

综上,如果要支持事务,必须用InnoDB,基于事务回滚+日志,可以实现数据的恢复,同时,UPDETE/INSERT的表,使用处理多并发的写请求时,行锁的效率也会比表锁高。它还具有外键约束、列属性AUTO_INCREMENT支持的功能。

关于数据库结构,可以查看这两篇博客:

Java开发 - 数据库索引的数据结构

Java开发 - 数据库中的基本数据结构

相信对学习数据库有一定的帮助。

MyISAM简介

MyISAM不支持事务,不支持外键,以SELECT/INSERT为主的应用可以使用该引擎。每个MyISAM可以存储成3个文件,扩展名分别是:

  • frm:存储表定义(表结构等信息)
  • MYD(MYData),存储数据
  • MYI(MYIndex),存储索引

不同MyISAM表的索引文件和数据文件可以放置到不同的路径下,当然,其前提一定是可以放置在相同的目录下,这个看自己。MyISAM类型的表还提供修复的工具,可以用CHECK TABLE语句来检查MyISAM表健康,并用REPAIR TABLE语句修复一个损坏的MyISAM表。

MySQL5.6以前,只有MyISAM支持Full-text全文索引,所以5.6之后,InnoDB肯定也支持了。

MyISAM引擎适合需要经常SELECT的表,它虽然不支持事务,但却可以做很多的count函数计算。

两者的区别

综上我们所说的内容,他们的区别如下:

  • MyISAM是非事务安全型的,InnoDB是事务安全型的
  • MyISAM锁的粒度是表级,InnoDB支持行级锁定
  • MyISAM不支持外键,InnoDB支持外键
  • MyISAM相对简单,在效率上要优于InnoDB,所以小型应用可以考虑使用MyISAM
  • InnoDB表比MyISAM表更安全,体现在ACID

扯淡的优化方案

禁用索引

对于使用索引的表,插入记录时,MySQL会对插入的记录建立索引,如果插入大量数据,建立索引会降低插入数据速度,所以,为了解决这个问题,可以在批量插入数据之前禁用索引,数据插入完成后再开启索引。

禁用索引:

ALTER TABLE '表名' DISABLE KEYS

开启索引:

ALTER TABLE '表名' ENABLE KEYS

禁用唯一性检查

唯一性校验会降低插入记录的速度,可以在插入记录之前禁用唯一性检查,插入数据完成后再开启。

禁用唯一性检查:

SET UNIQUE_CHECKS = 0;

开启唯一性检查:

SET UNIQUE_CHECKS = 1;

禁用外键检查

插入数据之前执行禁止外键的检查,数据插入完成后再恢复,可以提高插入的速度。

禁用外键检查:

SET foreign_key_checks = 0;

开启外键检查:

SET foreign_key_checks = 1;

禁止自动提交 

插入数据之前执行禁止事务自动提交,数据插入完成后再恢复,可以提高插入速度。

禁用自动提交 :

SET autocommit = 0;

开启自动提交 :

SET autocommit = 1;

总结吐槽

博主觉得这个挺扯淡的,虽然能提高速度,但是也有风险,感觉弊大于利,效率可以通过其他方式提高,有兴趣的自己研究研究。这里要说明一点,不是所有的优化都是必要的,好比夏天天热,衣服穿的越少越凉快,但你可曾见过在大街上裸奔的人?

缓存优化

这里的缓存并不是指Redis,es这样的缓存,而是数据库本身的缓存,可能很多人都没有想到数据库还有这功能,基本也没用过,但是当面临某些查询数据量庞大却又不要求非实时的需求时,数据库缓存将起到很大的缓解压力的作用。

数据库缓存简单分类可大致分为四种:查询缓存,全局缓存,局部缓存,其他缓存。下面一起来认识一下吧。

查询缓存

查询缓存的设置参数为query_cache_size,它可以作用于整个数据库,用来缓存MySQL中的ResultSet,也就是SQL语句执行的结果集,所以只能用在select上面。但是,查询缓存从MySQL 5.7.20开始被弃用,并在MySQL 8.0中被删除。

鉴于此,我们就简单说明下。当打开了此功能,只要select语句符合Query Cache的要求,MySQL会根据预先设定好的HASH算法将此select语句以字符串方式进行hash,然后到Query Cache中直接查找是否已有缓存。如果有,select会直接将数据返回,而放弃正常的查询步骤(如SQL语句的解析,优化器优化以及向存储引擎请求数据等),可极大的提高性能。

但Query Cache也有一个严重缺陷,那就是当某个表的数据有任何任何变化,都会导致所有使用该select语句的查询在Query Cache中的缓存数据失效。这个使用时就要格外注意了。

缓存相关变量的查看方式:

show variables like '%query_cache%';

  

  • have_query_cache:表示此版本mysql是否支持缓存
  • query_cache_limit :缓存最大值
  • query_cache_size:缓存大小
  • query_cache_type:off 表示不缓存,on表示缓存所有结果。

 可见,博主的mysql版本不支持缓存,大家可以自行查看,不过根据其特性,除非你是纯查询的表可以考虑开启,否则还是算了。

全局缓存

全局缓存在mysql启动时就会分配内存,可以在MySQL的my.conf或者my.ini文件的[mysqld]组中配置,查询缓存也是全局缓存的一种。

为什么要使用缓存呢?我们在开发中会使用Redis缓存,ES缓存,其目的都是提高查询的效率,但是我们很多人没想过的是,数据库也有缓存。数据库作为一个高IO的应用程序,如果没有IO的缓存,那真是说不过去,缓存优化,必须要优化IO,全局缓存的参数有:

  • key_buffer_size(默认值:402653184,384M)、
  • innodb_buffer_pool_size(默认值:134217728,128M)、
  • innodb_additional_mem_pool_size(默认值:8388608,8M)、
  • innodb_log_buffer_size(默认值:8388608,8M)、
  • query_cache_size(默认值:33554432,32M)

以上参数看看就行,也不用记,没啥意义。下面我们来了解他们分别都是什么:

  • key_buffer_size:索引块的缓冲区大小,它越大,则越能更好的处理索引,它决定了数据库索引处理的速度,尤其是索引读的速度,是对MyISAM表性能影响最大的一个参数。但如果它太大,那就适得其反了,系统运行将会变慢
  • innodb_buffer_pool_size:功能和Key_buffer_size一样,是InnoDB表性能影响最大的一个参数,其在不承担任何工作时,自身的运行还需占用大约8%的开销,用于每个缓存页帧的描述、adaptive hash等数据结构,如果不是安全关闭,启动时还要恢复的话,还需另外大约12%的内存来恢复,总共多就有大约21%的开销
  • innodb_additional_mem_pool_size:用来设置InnoDB存储引擎用来存放数据字典和内部数据结构的内存空间大小,当一个MySQL Instance中的数据库对象非常多的时候,需适当调整该参数的大小以确保所有数据都能存放在内存中,提高访问效率,而众所周知,内存的访问效率要高于硬盘
  • innodb_log_buffer_size:设置InnoDB存储引擎的事务日志所使用的缓冲区大小,类似于Binlog Buffer,InnoDB在写事务日志的时候,为了提高性能,也是先将信息写入Innodb Log Buffer中,当满足innodb_flush_log_trx_commit参数所设置的相应条件(或者日志缓冲区写满)之后,才会将日志写到文件(或者同步到磁盘)中。可以通过innodb_log_buffer_size 参数设置其可以使用的最大内存空间。大的日志缓冲可以减少磁盘IO,理想值为1M-8M,最大不超过32M

局部缓存

局部缓存是MySQL为每一个单独的连接分配的缓存区,就像是程序中方法的栈区,大小为256K,在线程空闲时,他们还可使用线程堆栈,缓存等,而不必自己分配内存。较小的查询消耗的内存会很小,但当大的查询,发生时,如排序,临时表等,还需要分配read_buffer_size,sort_buffer_size,read_rnd_buffer_size,tmp_table_size,record_buffer的内存,这几个内存空间只在需要的时候才分配,并在使用完之后立即释放。

  • read_buffer_size:MySQL读入缓冲区大小,对表进行顺序扫描的请求将分配一个读入缓冲区,MySQL会为它分配一段内存缓冲区。read_buffer_size变量控制的就是该缓冲区的大小。如果对表的顺序扫描请求非常频繁,且扫描进行的太慢,可以通过增加该变量值大小提高性能
  • sort_buffer_size:MySQL执行排序使用的缓冲大小,如果想要增加ORDER BY的速度,首先让MySQL使用索引,如果不能使用索引,则尝试增加sort_buffer_size变量的大小来提高排序速度
  • read_rnd_buffer_size:MySQL随机读缓冲区大小,当按任意顺序读取行时(例如,按照排序顺序),将分配一个随机读缓存区。之后在进行排序查询时,MySQL会首先查询该缓冲区内是否有排好序的数据,从而避免磁盘搜索,提高查询效率,如果对大量数据进行排序,可适当调高该值。由于MySQL会为每个连接分配该缓冲空间,所以该值的大小应适当,不宜过大
  • tmp_table_size:MySQL的heap (堆积)表缓冲大小,简单说就是临时表大小。所有联合在一个DML指令内完成,并且大多数联合甚至可以不用临时表就可以完成。大多数临时表是基于内存的(HEAP)表,如果是大记录长度的临时表 (所有列的长度的和)或包含BLOB列的表存储在硬盘上。当某个内部heap(堆积)表大小超过tmp_table_size时,MySQL会自动将此heap表改为基于硬盘的MyISAM表,也可以通过设置tmp_table_size值增加临时表的大小。
  • record_buffer:每个顺序扫描的线程为其扫描的表分配一个这样大小的缓冲区,顺序扫描很频繁时增加该值的大小

其他缓存

  • table_cache:TABLE_CACHE(5.1.3及以后版本又名TABLE_OPEN_CACHE),table_cache是表缓存的大小,当MySQL访问一个表时,如果在表缓冲区中还有空间,该表就被打开并放入其中,这样可以更快地访问表内容,但这并不是随意设置table_cache的理由,如果设置过高,可能会造成文件描述符不足,造成性能不稳定或连接失败的问题
  • thread_cache_size:服务器线程缓存数量,默认thread_cache_size=8,表示可以重新被利用的保存在缓存中线程的数量,当断开连接时,如果缓存中还有空间,那么客户端的线程会被放到缓存中,如果线程重新被请求,就从缓存中读取,如果缓存中是空的或没有当前请求线程的缓存,若线程缓存有空间,就创建这个请求线程的缓存。增加这个值可以改善系统性能,可通过比较Connections 和 Threads_created 状态的变量查看作用。

服务器优化

服务器层面的优化,我们单纯从本地来讲,硬盘,内存,CPU是制约硬件的三大要素,但是有自己机房的公司还是在少数,云服务器还是我们的首要选择,基于此,硬盘,内存,CPU,砸钱呗!没啥好讲的。

服务器就是主机,咱暂且不说,另外两个可优化的点是MySQL服务器和Linux服务器,咱们分别来说说这俩东西。

MySQL服务器优化

这个其实也没什么好讲的,主要是参数的设置,一些常用参数如下:

  • back_log:当MySql的连接数据达到max_connections时,新的请求会被存在堆栈中等待,back_log就是可以存储的最大的请求数量。如果等待连接的数量超过back_log,就存不进去了
  • wait_timeout:当MySQL闲置时,超过一定时间后将会被强制关闭,默认的wait_timeout值为8小时,可自定义,如果经常发现MYSQL中有大量的Sleep进程,就需要修改wait_timeout的值了
  • max_connections:MySQL服务器允许的最大连接数,该值最大不超过16384,MySql会为每个连接提供连接缓冲区,占用的内存随连接数增加,所以要适当调整该值,不能盲目设置
  • max_user_connections:每个数据库用户的最大连接数,它针对的是某一个账号的所有客户端并行连接到MYSQL服务的最大并行连接数,不是所有用户。设置为0表示不限制。
  • thread_concurrency:并发线程数,合理设置它的值可以有效提高MySQL性能,一般我们建议设置它为CPU核数的2倍,这样才能充分利用CPU多核的特性
  • skip-name-resolve:​ 禁止MySQL对外部连接进行DNS解析,它可以降低MySQL进行DNS解析的时间。注意!!!如果开启该选项,所有远程主机连接授权都要使用IP地址方式,否则MySQL将无法正常处理连接请求
  • default-storage-engine:default-storage-engine=InnoDB(设置InnoDB类型,另外还可以设置MyISAM类型)设置数据库存储引擎

总结

写了很多陌生的参数啊,由此可见,这些值都是把双刃剑啊​ ,太小不行,太大也不行,所幸,默认值能满足很大一部分需求,只有当极限优化时才会使用这些值,我相信很多人根本没动过这些值,希望你们用不到吧,但这并不妨碍你们知道有这些东西。

结语

说实话,博主最熟悉的是优化SQL,服务器层面砸钱,分库分表优化,像是缓存上的和一些参数上的优化也很少接触,真实的环境上这些参数的设置都是比较慎重的,即使在测试环境设置了没事,也不代表生产环境可以正常,测试环境的并发...测试环境有并发吗?哈哈~所以啊,基本上普通开发不太需要考虑这些问题,还是要靠大佬们啊,不过,谁不想成为大佬啊,今天讲解的内容大家可以了解下详细的操作步骤,其实就是设置参数了,大多数参数设置多少要根据实际业务来计算,并不是随意设置的,具体还是自己用到的时候私下进行查询,希望每个看到这篇博客的童鞋都可以成为大佬。加油哦!!!

车载摄像头+max96712 + rk3568 调试过程中遇到的问题 本文主要讲述本人在调试rk3568通过mipi-csi2链接max967812,max96712再外接4路车载摄像头过程中遇到的问题,以及最终如何解决这些问题。图中会贴上很多重要且关键的波形图,以便读者在调试过程中进行比对,分析。 如果在调试过程中,mipi总线上的波形没得什么问题的话,还是抓图失败的情况下,需要着重检查 频率,lane数,摄像头分辨率,摄像头输入图像格式等重要配置。 阅读详情

相关推荐

TwinCAT报SSE invalid operation错误

错误类型 TwinCAT程序中报出以下错误: 严重性 代码 说明 项目 文件 行 禁止显示状态 错误 **** 383 ms | 'Port_851' (851): Exception (Exception Code: 0xc0000090, SSE invalid operation) in PLC Application Untitled1 Instance, Task PlcTask (RBP: 0xffffb3016c80ecc0, RIP: 0xffffe708ee5b5f53, RSP:

akadiao的博客 4164

多维度查询的最佳实践

普通的数据库查询,很难实现上述需求场景,更不用提模糊查询、全文检索了。下面结合楼主的经验和知识,介绍初级方案、进阶方案(上ElasticSearch),大部分情况下推荐使用ElasticSearch来实现多维度查询,赶时间的读者可以直接跳到“进阶方案:将ElasticSearch添加到现有系统中”。...

weixin_62421895的博客 800

ESP32基于Arduino环境开发128*160 TFT_LCD屏幕显示照片

ESP32基于Arduino环境开发128*160 TFT_LCD屏幕显示照片

weixin_42854045的博客 2059

MySql对统计多个维度

MySql对统计多个维度

weixin_43266529的博客 1725

疾病负担研究(GBD)介绍

今天我们来聊一聊第一个公共数据库——GBD数据库,全称叫做global burden of disease(全球疾病负担),该数据库每年都会更新,目前已经更新到GBD2019。 这里直接给大家贴出网址:Global Burden of Disease Study 2019 (GBD 2019) Data Resources | GHDx 上图中红色圈圈标识的就是数据库的数据获取界面的链接,大家直接点击即可. 数据的检索十分方便: Context下拉菜单中可以选择不同的选项,默认是caus

weixin_44240228的博客 1万+

新手必看!Cisco Packet Tracer 8.2从安装到完成第一个局域网实验(附常见问题解决)

本文为网络新手提供了Cisco Packet Tracer 8.2的完整入门指南。从官方下载安装、界面熟悉,到核心的拖拽设备、连线、配置IP地址三步操作,手把手教你完成第一个局域网组网实验。文章重点讲解了如何通过Ping命令验证连通性,并附带了连线错误、IP配置不当等常见问题的解决思路,帮助初学者快速上手这款强大的思科模拟器。

android的专栏 870

java 统计图 mysql_java实现各种数据统计图(转)

转自:http://blog.youkuaiyun.com/pzhtpf/article/details/7600100最近在做数据挖掘的课程设计,需要将数据分析的结果很直观的展现给用户,这就要用到数据统计图,要实现这个功能就需要几个第三方包了:1. jfreechart-1.0.13.jar2. jcommon-1.0.16.jar3. gnujaxp.jar先来看一下,...

weixin_30162121的博客 566

DrissionPage实战:5分钟搞定京东滑块验证码自动登录(附完整轨迹生成代码)

本文详细介绍了如何使用DrissionPage工具实现京东滑块验证码的自动化登录,包括环境配置、滑块缺口识别、拟人化轨迹生成算法及完整登录流程。通过物理运动学模型和智能识别技术,有效提升验证码破解成功率,适用于电商自动化场景。

weixin_29229055的博客 245

基于Mybatis使用MySql存储过程,实现数据统计功能

作为一个工作了很多年的程序员来说,没有在实际工作中真正使用过存储过程,其实对存储过程本身有过了解和学习,在日常的学习中,也会看过一些存储过程的相关介绍,不过“纸上得来终是浅”,正好这次做统计分析的业务功能时,适合使用存储过程的机会,就搞起来了,顺便记录一些遇见的一些问题,方便后续查看和学习。

向心行者 926

使用Simulink进行基于IIR滤波器的设计与稳定性分析仿真

IIR滤波器的稳定性与其系统函数的极点位置密切相关。如果所有极点都位于Z平面的单位圆内,则该滤波器是稳定的;否则,滤波器将是不稳定的。在设计IIR滤波器时,确保其稳定性对于避免输出信号发散至关重要。明确你的系统需求,比如输入信号类型(如正弦波)、采样率、IIR滤波器的设计参数(如滤波器类型、阶数、截止频率等)。假设我们需要设计一个低通IIR滤波器,用来去除高于500Hz的所有频率成分,保留低于500Hz的信号成分。采样率为8kHz。

xiaoheshang_123的博客 151

[xboard-real6410]39 real6410中的BL1和BL2实验及流程分析

文章目录uboot控制uboot 流程uboot加载kernel uboot控制 uboot 流程 uboot加载kernel

鹰之翔 298

Java 项目中 MySQL 数据向 Redis 迁移的技术实践与深度剖析

将 MySQL 数据存入 Redis 的过程,本质上是 “根据数据的访问特征,将合适的数据分配到合适的存储资源”—— 让 MySQL 承担 “持久化、高一致性” 的职责,让 Redis 承担 “高频访问、高并发” 的职责,二者协同构建高效的存储层。在 Java 项目中落地时,需避免 “为了用 Redis 而用 Redis” 的误区:需先分析业务场景(如数据的访问频率、修改频率、一致性要求),再选择同步方式、读写策略;同时关注细节(如 key 的命名、过期时间的设置、异常处理),才能真正发挥两者的协同价值。

hqxstudying的博客 1097

免ROOT、不刷机、不依赖Xposed实现Android改机的思路

最近在一个项目中需要模拟多种Android设备的环境。无奈市面上的大部分改机工具,要么需要ROOT权限,要么依赖Xposed,甚至还得重启设备。为了实现更灵活、更干净的改机方式,我开始了漫长的技术探索,最终找到了免ROOT、不刷机、拒绝Xposed的实现路径。Android_IDIMEI手机序列号手机型号、品牌、CPU型号等硬件信息GPS位置、Wi-Fi参数、通话记录、短信等软硬件数据这些信息通常用于标识设备唯一性,而改机就是对这些标识数据进行模拟或篡改。

代码简单说 Vue、JAVA、PHP、Node.js 熟练运用,接口、架构、性能全搞定。 2675

Github一夜爆火!字节内部人手一份的Java性能优化小册魅力何在

Java架构进阶面试及知识点文档笔记这份文档共498页,其中包括Java集合,并发编程,JVM,Dubbo,Redis,Spring全家桶,MySQL,Kafka等面试解析及知识点整理Java分布式高级面试问题解析文档其中都是包括分布式的面试问题解析,内容有分布式消息队列,Redis缓存,分库分表,微服务架构,分布式高可用,读写分离等等!互联网Java程序员面试必备问题解析及文档学习笔记Java架构进阶视频解析合集。

2401_86400233的博客 632

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

基于Java的旅行攻略与搭子系统源码剖析

本文深度剖析了Java旅行攻略与搭子系统的技术架构与核心功能。系统采用SpringBoot+SpringCloudAlibaba微服务架构,集成Redis缓存和RocketMQ消息队列,支持高并发访问和实时交互。核心功能包括智能行程规划(基于遗传算法)、旅行搭子匹配(三重维度算法)和实时协作工具,通过JWT认证和AES加密确保安全性,并采用多级缓存和异步处理优化性能。代码示例展示了行程规划、用户匹配等关键算法实现,系统可支撑10万级并发请求,匹配成功率≥85%。

小马总的博客 547

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

从心跳机制到性能优化:深入解析Navicat与MySQL的连接管理策略

本文深入解析Navicat与MySQL的连接管理策略,重点探讨心跳机制在解决连接卡顿问题中的关键作用。通过分析客户端与服务端的超时设置冲突,提供多维度性能优化方案,包括Navicat配置调整、MySQL参数优化及网络设置,帮助开发者有效提升数据库连接稳定性与响应速度。

alice7model的博客 937

SIMATIC S7-1200, S7-1500 PID 控制[手册]

SIMATIC S7-1200, S7-1500 PID 控制[手册]

Redis ZSet实现多维度排行榜的设计与实践

在分布式系统中,高效的数据排序是核心需求之一,Redis的ZSet(有序集合)通过跳跃表和哈希表的混合结构,实现了O(logN)的插入与范围查询效率。这种数据结构特别适合构建实时排行榜系统,尤其在游戏、电商等需要多维度排序的场景中。通过将多个业务维度(如积分、胜率、销量等)编码为复合分数,ZSet能够支持复杂的排序逻辑。工程实践中,结合位拼接、加权求和等策略,配合管道批处理、Lua脚本等Redis特性,可以构建出支持百万级数据的高性能排行榜。本文以电竞平台和电商系统为例,展示如何利用ZSet解决传统数据库在

weixin_30225755的博客 205

Java设计模式之抽象工厂模式:从入门到架构级实践

架构清晰化:通过垂直分层管理依赖扩展可控化:新产品族的加入无需修改已有代码协作标准化:统一的对象创建契约智能化工厂:通过机器学习自动选择最优产品实现边缘计算:动态生成适应边缘节点的轻量级产品区块链:确保工厂生成对象的不可篡改性。

java2cy 758

Java面试题及答案整理:JVM+Spring+MySQL+ 线程池 + 锁

就目前大环境来看,跳槽成功的难度比往年高很多。。这不马上又到了面试跳槽的黄金段,成功升职加薪,不成功饱受打击。当然也要注意,跳槽时时刻刻都在发生,但是我建议大家跳槽之前,先想清楚为什么要跳槽。切不可跟风,看到同事一个个都走了,自己也盲目的开始面试起来(期间也没有准备充分),到底是因为技术原因(影响自己的发展,偏移自己规划的轨迹),还是钱给少了,不受重视。只有考虑好了跳出去后才不会后悔。

m0_69632475的博客 752

mysql:MySQL中VARCHAR(100)与VARCHAR(10)的深度解析

设计原则按业务实际需要+20%余量定义长度多语言场景必须使用utf8mb4超过5K的文本考虑TEXT类型+外部存储性能优化-- 最佳实践示例监控指标平均行长度碎片率溢出页比例字符集转换次数架构建议将大VARCHAR字段拆分到扩展表使用生成列自动处理多字符集对索引列严格控制长度在阿里/字节等大厂的实际场景中,合理的VARCHAR设计能使TP99延迟降低30%以上。记住:长度定义不仅是业务约束,更是重要的性能优化手段。

weixin_43290370的博客 1400

java.sql.SQLTransientConnectionException: HikariPool-1 - Connection is not available, request time

💡 亲爱的技术伙伴们:你是否正在为这些问题焦虑——✅ 简历投出去杳无音信,明明技术不差却总卡在面试?✅ 每次终面都紧张不已,不知道面试官到底想要什么答案?✅ 技术知识点零零散散,遇到系统设计题就头脑一片空白?🎯这不是普通的面试题汇总,而是凝聚多年面试官经验的。我不仅告诉你答案,更帮你建立面试官的思维模式。🔗🎯 精准人群定位🔥 《》(完整技术体系)🚀⚡🌊🛠️🔒🔄👥🏗️🚀 立即行动,改变从现在开始!🔗不要再让面试成为你职业发展的绊脚石!用时间系统准备,轻松应对各种技术面试场景。💪。

我是Java程序员廖志伟,感谢朋友们的支持! 631

大数据新视界 -- Impala 性能优化:量子计算启发下的数据加密与性能平衡(下)(30 / 30)

本文聚焦于[Impala](https://blog.youkuaiyun.com/atgfg/category_12809599.html)性能优化中量子计算对数据加密与性能平衡的作用。阐述量子计算原理,详细解析量子密钥分发在 Impala 数据加密的应用并对比传统方式,提出多维度加密策略与硬件加速方案,以社交媒体、金融、医疗、交通等多行业案例展示其成效,最后提及 Impala 与 Hive 关联及新专栏,发起互动探讨加密性能平衡难题与量子计算应用创新,为 Impala 大数据处理提供前沿思路与实践参考。

【青云交】华为云云享专家 | 阿里云开发者社区专家博主 技术圈个人影响力前 9 | 博客之星 TOP12 优快云 首位四榜(原力榜 / 作者周榜 / 领军人物 / 综合热榜)榜首,破平台纪录! 苏州地区全榜霸榜,感恩全网十多万粉丝同行! 2720

MySQL TEXT 类型字段 “Data too long“ 错误深入解读与优化方案

MySQL大容量文本存储问题解析:当遇到"Data too long"错误时,需从多个维度解决。MySQL文本类型包含TINYTEXT(255B)、TEXT(64KB)、MEDIUMTEXT(16MB)和LONGTEXT(4GB),实际存储容量受字符集影响。解决方案包括:升级列类型至MEDIUMTEXT/LONGTEXT、应用层长度校验、分段存储、压缩存储或使用外部存储。优化时需考虑查询性能、行宽限制和备份效率。最佳实践建议先升级列类型,再结合分段存储或对象存储进行综合优化,同时建立全链

x² 1977

Mysql全面详解

本文深入解析MySQL架构与执行流程,重点分析InnoDB引擎的核心机制。MySQL采用分层架构设计,包含客户端层、Server层(连接器、解析器、优化器等)、存储引擎层和文件系统层。SQL执行流程分为Server层处理和InnoDB引擎处理两阶段,涉及查询优化、BufferPool缓存、Undo/Redo日志等关键技术。其中InnoDB的事务处理尤为关键,通过WAL机制、两阶段提交(RedoLog Prepare/Commit)确保数据一致性,同时利用MVCC实现高并发。文章还对比了Binlog与Redo

shi796188的博客 1060

推客带货小程序开发代码剖析:规则引擎、奖励发放与实时统计

**模块** | **技术方案** | **优势** || **前端** | Uni-app/Taro(跨端支持小程序/H5/APP) | 一次开发多端适配,降低维护成本 || **数据库** | MySQL(关系数据) + Redis(缓存/计数器) | 高频操作性能提升10倍+ |

2503_92485789的博客 792
上一篇: Java开发 - 不知道算不算详细的分布式事务详解
下一篇: Java开发 - 不知道算不算详细的分布式锁详解
CodingFire
CodingFire  2022年度博客之星移动开发领域TOP 5 2022年度博客之星移动开发领域TOP 5 领域专家: 移动开发技术领域 领域专家: 移动开发技术领域
博客等级 码龄11年 7927粉丝 387原创
评论 38
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

CodingFire

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值