为什么查询速度会慢--高性能MySQL笔记

为什么查询速度会慢

1.是否像数据库请求了不需要的数据

一些常见的事例

查询不必要的记录:比如我们在网站取出10条记录,习惯于先取出大量的记录,再返回前10条结果。有些人会认为MySQL会执行查询,并在返回10条记录后停止查询。
实际情况是,MySQL会查询出全部的结果集,客户端的应用程序会接收全部的结果集,然后抛弃其中绝大部分的数据。
最简单有效的方法是,在这样的查询后面加上Limit
 
多表关联时返回全部列:

总是取出全部列:取出全部列,会让优化器无法完成索引覆盖扫描这类优化,还会为服务器带来额外的I/O,内存,CPU消耗。
有的时候,查询返回超过需要的数据也不总是坏事,浪费了数据库的资源,但是可以简化开发,提高代码复用性。
 
重复查询相同的数据:比如在用户评论时,每一次发表评论都要获取用户自己的头像,多次评论就会反复查询这个数据。
比较好的方案是,初次查询时将这个数据缓存起来,需要的时候从缓存中取出
 

2.MySQL是否在扫描额外的记录

对于MySQL,最简单的衡量查询开销的三个指标如下:
  •     响应时间
  •     扫描的行数
  •     响应的行数
这三个指标都会记录到MySQL的慢日志中,检查慢日志可以找出扫描行数过多的查询
 
响应时间:是服务时间和排队时间两个部分之和
服务时间是指数据库处理这个查询真正花了多少时间
排队时间是指服务器因等待某些资源而没有真正执行查询的时间--可能是等I/O操作完成,也可能是等行锁,等等
估算响应时间--“快速查询估计法”
 

 
扫描的行数和返回的行数:一个查询扫描的行数可以在一定程度上说明该查询找到需要的数据的效率高不高。
但并不是所有的行的访问代价都是相同的。--较短的行的访问速度更快
                                                            --内存中的行也比磁盘中的行的访问速度要快得多
最理想的状态,扫描的行数和返回额行数应该是相同的。但实际上可能相差甚远
 
扫描的行数和访问类型:在EXPLAIN语句中的tpye列反应了访问类型,访问类型有全表扫描到索引扫描、范围扫描、唯一索引查询、常数引用等。这些访问类型速度从慢到快,扫描的行数也是从大到小
如果查询没有办法找到合适的访问类型,解决的最好办法通常是增加一个合适的索引
 
一般MySQL能够使用三种方式应用where条件,从好到坏依次为:
 
  • 在索引中使用where条件过滤不匹配的记录。这是在存储引擎层完成的。
  • 使用索引覆盖扫描(在Extra列出现了Using index)来返回记录,直接从索引中过滤不需要的记录并返回命中的结果。这是在MySQL服务器层完成的,但无需再回表查询记录
  • 从数据表中返回数据,然后过滤不满足条件的记录(在Extra列中出现Using Where)。这在MySQL服务器层完成,MySQL需要先从数据 表中读出记录然后过滤。
如果发现查询需要扫描大量的数据但只返回少数的行,那么通常可以尝试下面的技巧去优化它:
  • 使用索引覆盖扫描,把所有需要用的列都放在索引中,这样存储引擎无须回表获取对应行,就可以返回结果了
  • 改变库表结构。列如使用单独的汇总表
  • 重写这个复杂的查询,让MySQL优化器能够以更优化的方式执行这个查询
 

 

 
 
posted @ 2021-04-14 15:36  juicejuice  阅读(119)  评论(0编辑  收藏  举报