Mysql优化学习笔记

慕课网视频学习笔记

数据库优化的目的

避免出现页面访问错误

  • 由于数据连接timeout 产生页面5xx错误   
  • 由于慢查询造成页面无法加载
  • 由于阻塞造成数据无法提交          

增加数据库的稳定性

  • 很多数据库问题都是由于低效的查询引起的

优化用户体验

  • 流畅页面的访问速度
  • 良好的网站功能体验

数据库优化的几个方面:

1、SQL及索引

2、数据库表结构

3、系统配置

4、硬件


示例数据库的安装:

示例数据库下载地址:http://downloads.mysql.com/docs/sakila-db.zip 
安装教学地址:https://dev.mysql.com/doc/sakila/en/sakila-installation.html

注意:window下cmd安装  \ 全部替换成  /  才可以成功


SQL及索引优化

使用mysql慢查日志对有效率问题的sql进行监控

#1、查看mysql是否开启慢查询日志
show variables like 'slow_query_log';

#2、设置没有索引的记录到慢查询日志
set global log_queries_not_using_indexes=on;

#3、查看超过多长时间的sql进行记录到慢查询日志
show variables like 'long_query_time';

#4、开启慢查询日志
set global slow_query_log=on;

#5、设置超过多少秒以后的查询插入慢查日志中
set global long_query_time=1;

#6、查看日志记录位置
show variables like 'slow%';

#7、查看日志(退出mysql环境)
tail -50 D:\newphpStudy\MySQL\data\BlueSummer-PC-slow.log;

慢查日志分析工具:

pt-query-digest

安装过程:

[root@localhost ~]# wget percona.com/get/pt-query-digest

[root@localhost ~]# chmod u+x pt-query-digest

[root@localhost ~]# mv /root/pt-query-digest /usr/bin/

输出到文件:pt-query-digest slow-log > slow_log.report

输出到数据库表: pt-query-digest slow.log -review \

如何通过慢查日志发现有问题的SQL:

1、查询次数多且每次查询占用时间长的SQL(通常为pt-query-digest分析的前几个查询)

2、IO大的SQL(注意pt-query-digest分析中的Rows examine项)

3、未命中索引的SQL(注意pt-query-digest分析中的Rows examine和Rows Send的对比)

使用explain查询SQL的执行计划:

explain select customer_id,first_name,last_name from customer;

Mysql优化学习笔记_第1张图片

explain返回各列的含义:

  • table:显示这一行的数据是关于哪张表的
  • type:这是重要的列,显示连接使用了何种类型。从最好到最差的连接类型为const、eq_reg、ref、range、index和ALL
  • possible_keys:显示可能应用在这张表中的索引。如果为空,没有可能的索引。
  • key:实际使用的索引。如果为NULL,则没有使用索引。
  • key_len:使用的索引的长度。在不损失精确性的情况下,长度越短越好。
  • ref:显示索引的哪一列被使用了,如果可能的话,是一个常数
  • rows:MYSQL认为必须检查的用来返回请求数据的行数
  • extra:using filesort或者using temporary

Using filesort:看到这个的时候,查询就需要优化了。MYSQL需要进行额外的步骤来发现如何对返回的行排序。它根据连接类型以及存储排序键值和匹配条件的全部行的行指针来排序全部行。

Using temporary:看到这个的时候,查询需要优化了。这里,MYSQL需要创建一个临时表来存储接口,这通常发生在对不同的列表进行ORDER BY上,而不是GROUP BY上。

count()和max()的优化

max()优化:建立覆盖索引

优化前:

Mysql优化学习笔记_第2张图片

建立索引:

create index inx_paydate on payment(payment_date);

优化后:

Mysql优化学习笔记_第3张图片

count()优化:使用OR NULL

-- 在一条SQL中同时查出2006和2007年电影的数量-优化count()函数
SELECT COUNT(release_year='2006' OR NULL) AS '2006年电影数量',
COUNT(release_year='2007' OR NULL) AS '2007年电影数量'
FROM film;

子查询的优化

通常情况下,需要把子查询优化为join查询,但在优化时需要注意关联键是否有一对多的关系,因为此时要注意会有重复数据。(join查询不需要内建临时表)

distinct   --去除重复值

group by 的优化

优化前:

SELECT actor.first_name,actor.last_name,COUNT(*) 
FROM sakila.film_actor
INNER JOIN film_actor USING(actor_id)
GROUP BY film_actor.actor_id;

优化后:

SELECT actor.first_name,actor.last_name,c
FROM sakila.actor INNER JOIN(
    SELECT actor_id,COUNT(*) AS cnt FROM sakila.film_actor GROUP BY
    actor_id
)AS c USING(actor_id);

Limit查询的优化:

limit常用于分页处理,时常会伴随order by从句使用,因此大多时候会使用Filesorts,这样造成大量的IO问题。

SELECT film_id,description FROM sakila.film ORDER BY title LIMIT 50,5;

优化LImie查询:

优化步骤1:使用有索引的列或主键进行order by操作

SELECT film_id, descripytion FROM sakila.film ORDER BY film_id LIMIT 50,5;

优化步骤2:记录上次返回的主键,在下次查询时使用主键过滤(避免了数据量大时扫描过多的记录)

SELECT film_id, description FROM sakila.film WHERE film_id > 55 and film_id <= 60 ORDER BY film_id LIMIT 1,5;

-- 如果不是连续的,可以自己建一列保证其值顺序递增也可以。

*避免数据量大时扫描过多的记录

使用主键或索引来order by是可以减少扫描列: 
在表中建立索引,然后在索引中找到符合查询条件的索引值,最后通过保存在ROWID(相对于页码)快速找到表中对应的记录。索引的建立时表中比较有指向性的字段,相对于目录,比如说行政区域代码,同一个地域的行政区域代码都是相同的,那么给这一列加上索引,避免让它重复扫描,从而达到优化的目的。

如何选择合适的列建立索引:

 

你可能感兴趣的:(笔记)