建站教程

建站教程

Products

当前位置:首页 > 建站教程 >

mysql优化教程?(Mysql优化器)

GG网络技术分享 2025-03-18 16:11 0


1、对SQL语句、索引、表结构等进行优化。

2、开启查询缓存,Query Cache缓存了SELECT查询及其结果数据集,当执行一个同样的SELECT查询时,MySQL会从内存中直接取出结果,加快了查询执行速度、减小了数据库的压力。执行SHOW VARIABLES LIKE \'have_query_cache\';可以查看MySQL查询缓存是否打开,开启查询缓存只需配置my.cnf文件即可,具体如下:

query_cache_type = 1

query_cache_size = 128M

query_cache_limit = 1M

保存好后重启MySQL。

3、选用InnoDB存储引擎,MySQL常用存储引擎是MyISAM和InnoDB,二者区别如下:

MyISAM

查询速度快;

支持表级锁,在上锁期间表上不能进行其他操作;

支持全文检索;

支持数据压缩、自我复制、查询缓存、数据加密;

不支持外键;

不支持事务,所以也就没有COMMIT和ROLLBACK操作;

不支持集群数据库。

InnoDB

支持行级锁;

支持外键,对外键约束强制;

支持事务,可执行COMMIT和ROLLBACK操作;

支持数据压缩、自我复制、查询缓存、数据加密;

可用在集群环境,但并不完全支持。InnoDB表可以转换为NDB存储引擎,这样就能用在集群环境。

#####

MySQL的优化要根据实际业务,并没有什么通用的优化。

其实其他回答都说的很全,

但是我从比较实际的地方说说吧。


第一、开启MySQL的slowLog

slowLog会记录MySQL执行过的慢查询,比较佛系的办法就是让它记录一段时间,

然后查看里面执行的语句。


第二、通过desc的方式来查看慢的原因

比如:SELECT * FROM tbl WHERE Date = CURDATE();

你可以通过执行 desc SELECT * FROM tbl WHERE Date = CURDATE();

这个时候Mysql就会显示执行这句sql的计划,

如果你发现是全表查询,这个时候尝试在Date上增加索引,

然后再跑一次DESC,这个时候你就会发现这句语句已经走了索引。

*通常这个办法能解决90%的慢查询问题。


当上面的问题都无法满足到你的时候,

建议可以参考Mysql官方的参数设定,

然后根据业务特性对MySQL进行特定优化。

#####

答: 本文邀请ryangz分享近来项目的mysql优化经验~

准备知识

了解select的执行顺序有助于理解语句的结果并对其进行优化,执行顺序如下:

可以通过show status like \'XXX\', show global status like \'XXX\',show variables like \'XXX\' 查看很多重要的数据,eg:Connections 连接数,Slow_queries 慢查询(可以用 show variables like ‘%slow%’来查询是否开启慢查询日志)等等。

可以通过 desc sql命令 (同样可是使用explain命令,用法相同)获取这个查询的各种属性,检查这个语句是否达到性能标准。着重看重点要看这几列:

rows(影响行数)

select_type(查询类型,是单表查询还是多表查询)

type、possible_key和key(可能用到的索引,以及真正用到索引等)

[ possible_key说明可能用到索引competition_id,但是key为null表明最终没有使用索引,进行了全表扫描,rows为全表数量 ]

[ 本次查询是嵌套查询,两张表的主键都是id,通过desc命令可以看出,player_unique_id的查询时使用的主键索引,影响条数rows为1,但是外部查询虽然id是主键但是没有使用索引,进行了全表查询 ]

一些小技巧和注意事项:

(1)有些时候即便你加了索引,数据库查询的时候也不会使用:

like的%如果只有一个,并且放在开头,则不会使用索引;eg ‘%user’不会使用索引,但是’user%’,’%user%’都会使用索引;

查询的时候and和or 如果想使用索引的话需要前后都加索引,如果只有一个则不会使用索引;

如果查询的时候该列是varchar,但是写的时候没有带引号(写成2018,而不是’2018’),则不会使用索引;

反向条件查询不能使用索引,尽量少用 !=,not in,not exists;

复合索引最左前缀,eg: 复合索引(name`, age):

select * from XXX where age=? and name=? 使用索引

select * from XXX where name=? 使用索引

select from XXX where age=? *不使用索引

(2)尽量避免用嵌套查询,外层的就算是主键也不会使用索引(可以参看准备知识中的例子),可以使用左连接、右连接或者相同的功能的其他写法代替。

(3)如果明确知道只有一条结果返回,limit 1能够提高效率

(4)所有不清楚的操作可以通过?查询,类似linux的man操作,? view 就可以查询视图基本语法

(5)开始数据库慢日志:

vim /etc/my.cnf 添加log_slow_queries=slow.log 以及long_query_time=5(设置慢日志的时长), 然后重启mysql

综上,一般的查询优化步骤如下:

(1)查看慢查询日志,或者通过show status命令查看数据库各项指标是否正常,其中 show status like ‘%handler_read%’ 中 Handler_read_rnd_next如果很高的话,说明需要检查索引了,看看是索引加的不对还是用法不对。

(2)找到问题的语句,通过desc定位这个语句到底哪里有问题,是语句写法问题、索引问题、还是表结构问题等等。

(3)优化语句,重复第1步,直到符合业务需求

#####

对数据库优化我认为可以分一下步骤进行:\\r

1、表结构优化;\\r

根据实际项目的业务逻辑,对表结构进行合理拆分,和合并;减少数据冗余;适度的反范式。\\r

对表字段选择适当的字段类型;\\r

2、sql语句优化;\\r

针对一下特定的SQL查询进行优化,可以开启mysql慢日志,锁定慢查询语句然后进行查询优化;具体的优化方案还得根据实际业务来定;比如select * 替换 具体的查询字段;OR改写为IN()查询;查分join查询等等;\\r

3、合理构建索引,优化索引,避免滥用;\\r

建立索引被多少人认为是提升数据库性能的审计,于是甚至有人说把where后面所有的查询字段都加上索引;需要搞清楚的是,索引的确可以大大提高查询效率,但是索引对应添加和更新数据,增加了大量的I/O,而且对表的存在空间增大;不合理的索引反而成了累赘。\\r

4、构建集群;\\r

搭建数据库集群,配合数据库中间件实现读写分离负载均衡;\\r

5、存储业务拆分;\\r

对于一些业务和数据通过其他方式存在进行优化,比如检索字段可以用ES或者Solr进行查分。

#####

你好,我是全栈技术栈,很高兴回答你的问题

可以从以下几个方面对mysql进行优化:

1.对于select * 要时刻保持谨慎的态度

绝大多数情况,是不需要select *的。select * 为全表查询,建议查询指定的列信息

2.count()函数优化

count(列名)是不统计值为NULL的字段的!如果想要统计结果集,就使用count(*),性能也会很好。

3.合理创建索引

并不是表的索引创建的越多越好

4.尽量不使用子查询

子查询在数据量大的情况下,性能会很低

5.尽量使用exist/not exist代替 in/not in

6.能避免使用join的避免使用,越简单的sql一般效率是最高的


希望我的回答能够帮到你,谢谢!

#####

来看MySQL内部的观测,常用的观测手段是这样的,从上往下看,第一部分是Processlist,看一下哪个SQL压力不太正常,第二步是explain,解释一下它的执行计划,第三步我们要做Profilling,如果这个SQL能再执行一次的话, 就做一个Profilling,然后高级的DBA会直接动用performance_schema ,MySQL 5.7 以后直接动用sys_schema,sys_schema是一个视图,里面有便捷的各类信息,帮助大家来诊断性能。再高级一点,我们会动用innodb_metrics进行一个对引擎的诊断。

除了这些手段以外,大家还提出了一些乱七八糟的手段,我就不列在这了,这些是常规的一个MySQL的内部的状态观测的思路。除了这些以外,MySQL还陆陆续续提供了一些暴露自己状态的方案,但是这些方案并没有在实践中形成套路,原因是学习成本比较高。

外部资源观测这部分,我引用了一篇文章,这篇文章的二维码我贴在上面了。这篇文章是国外的一个神写的,标题是:60秒的快速巡检,我们来看一下它在60秒之内对服务器到底做了一个什么样的巡检。一共十条命令,这是前五条,我们一条一条来看。

1.uptime,uptime告诉我们这个机器活了多久,以及它的平均的负载是多少。
2.dmesg -T | tail,告诉我们系统日志里边有没有什么报错。

3.vmstat 1,告诉我们虚拟内存的状态,页的换进换出有没有问题,swap有没有使用。

4. mpstat -P ALL,告诉我们CPU压力在各个核上是不是均匀的。

5.pidstat 1,告诉我们各个进程的对资源的占用大概是什么样子。

我们来看一下后五条:


首先是iostat-xz 1,查看IO的问题,然后是free-m内存使用率,之后两个sar,按设备网卡设备的维度,看一下网络的消耗状态,以及总体看TCP的使用率和错误率是多少。最后一条命令top,看一下大概的进程和线程的问题。


这个就是对于外部资源的诊断,这十条命令揭示了应该去诊断哪些外部资源。

1.3 外部需求改造

第三个诊断思路是外部的需求改造,我在这里引用了一篇文档,这篇文档是MySQL的官方文档中的一章,这一章叫Examples of Common Queries,文档中介绍了常规的SQL怎么写, 给出了一些例子。文章的链接二维码在slide上。

我们来看一下它其中提到的一个例子。

它做的事情是从一个表里边去选取,这张表有三列,article、dealer、price,选取每个作者的最贵的商品列在结果集中,这是它的最原始的SQL,非常符合业务的写法,但是它是个关联子查询。

关联子查询成本是很贵的,所以上面的文档会教你快速地把它转成一个非关联子查询,大家可以看到中间的子查询和外边的查询之间是没有关联性的。

第三步,会教大家直接把子查询拿掉,然后转成这样一个SQL,这个就叫业务改造,前后三个SQL的成本都不一样,把关联子查询拆掉的成本,拆掉以后SQL会跑得非常好,但这个SQL已经不能良好表义了,只有在诊断到SQL成本比较高的情况下才建议大家使用这种方式。

为什么它能够把一个关联子查询拆掉呢?

这背后的原理是关系代数,所有的SQL都可以被表达成等价的关系代数式,关系代数式之间有等价关系,这个等价关系通过变换可以把关联子查询拆掉。

上面的这篇文档是一个大学的教材,它从头教了关于代数和SQL之间的关系。然后一步步推导怎么去简化这句SQL。

第一,MySQL本身提供了很多命令来观察MySQL自身的各类状态,大家从上往下检一般能检到SQL的问题或者服务器的问题。


第二,从服务器的角度,我们从巡检的脚本角度入手,服务器的资源就这几种,观测手法也就那么几种,我们把服务器的资源全部都观察一圈就可以了。


第三,如果实在搞不定,需求方一定要按照数据库容易接受的方式去写SQL,这个成本会下降的非常快,这个是常规的MySQL慢的诊断思路。

标签:

提交需求或反馈

Demand feedback