SQL语句优化
2015-06-24 16:47
441 查看
1. 数据准备:
sakila数据库 mysql5.5 http://dev.mysql.com/doc/index-other.html
表结构信息: http://dev.mysql.com/doc/sakila/en/sakila-installation.html
2. mysql慢日志开启方式
利用慢查询日志对效率问题进行监控 -- 用来发现有问题的日志
1. 查询是否开启对未设置索引的查询开启慢查询
show variables like 'log_queries_not_using_indexes';
set global log_queries_not_using_indexes = on;
show variables like 'long_query_time';
set long_query_time = 0; (单位:秒)
show variables like 'slow_query_log'
set global slow_query_log = on;
show variables like 'slow_query_log_file';
set global slow_query_log_file = '/home/log'
实际应用过程中,使用命令行上面的配置没有生效,不知道为什么。最后修改my.ini,重启mysql之后,才生效。
慢查询日志的存储格式
select * from payment;
# Time: 2015-06-24T06:52:58.315864Z
# User@Host: root[root] @ localhost [::1] Id: 1
# Query_time: 0.076355 Lock_time: 0.061227 Rows_sent: 1 Rows_examined: 0
SET timestamp=4294967113;
包括: 主机信息、SQL执行信息、SQL执行时间、SQL内容
如何分析日志?
分析工具:
1. mysqldumpslow
mysqldumpslow -h
mysqldumpslow -t 3 日志路径 | more (前3个最慢的查询)
2.pt-query-digest工具
pt-query-digest 慢查询日志 > slow_log.report //输出到日志
//输出到数据库
pt-query-digest mysql-slow.log -review \
h=127.0.0.1,D=test,p=root,P=3306,u=root,t=query_review\
--create-reviewtable \
--review-history t = hostname_slow
如何发现问题?
1.查询次数多且每次查询占用时间长
2.I/O大的SQL rows examine参数
3. 未命中索引的SQL row examine 和 Row send参数
如何分析查询?
使用explain查询SQL的执行计划
参数含义:
table --- 从哪个表查询
type --- 从好到坏const(主键,唯一索引), eq_reg(范围查找), ref(连接查询), range(索引范围), index(索引扫描), all(表扫描)
possible_keys --- 可以用到的索引
key: 实际使用的索引
ken_len:索引长度,在不影响精度情况下,索引长度越少越好
ref: 索引的哪一列被使用
rows: mysql认为必须检查的用来返回请求数据的行数
Using filesort: 看到这个的时候,查询就需要优化。Mysql需要额外的步骤来发现如何对返回的行排序。它根据连接类型以及存储排序键值和匹配条件的全部行指针排序。
Using temporary: 需要优化。Mysql需要创建一个临时表来存储数据。通常发生在对不同的列集进行ORDER BY,而不是GROUP BY
优化MAX()
explain max(payment_date) from payment; //扫描行数较多
create index idx_paydate on payment(payment_date); //覆盖索引,按顺序排列,只需取最后一行的索引数据
优化COUNT()
count(*) 与 count(id) 区别: count(id) 对于NULL值不会计数。
子查询优化--一般优化成join方式,但需要注意是否存在一对多关系。
如果存在一对多关系的化,子查询仍然会返回正确的记录,但是join方式会返回多条记录,会有冗余,所以要添加distinct
select * from t where t.id in(select t1.tid from t1); --> select t.id from t join t1 on t.id = t1.tid;
GROUP BY
explain select actor.first_name, actor.last_name,count(*) from sakila.film_actor inner join sakila.actor using(actor_id) group by film_actor.actor_id\G;
改写为:
explain select actor.first_name, actor.last_name, c.cnt from sakila.actor inner join (select actor_id, count(*) as cnt from sakila.film_actor group by actor_id) as c using(actor_id)\G;
LIMIT
limit常用于分页处理,伴随order by 从句使用。
explain select film_id, description from film order by title limit 50,5\G;
优化步骤1:使用有索引的列或主键进行order by
优化步骤2:记录上次返回的主键,在下次查询时候使用主键过滤。(注意:保证主键连续增长)
思想:避免数据量大时候扫描过多的记录
sakila数据库 mysql5.5 http://dev.mysql.com/doc/index-other.html
表结构信息: http://dev.mysql.com/doc/sakila/en/sakila-installation.html
2. mysql慢日志开启方式
利用慢查询日志对效率问题进行监控 -- 用来发现有问题的日志
1. 查询是否开启对未设置索引的查询开启慢查询
show variables like 'log_queries_not_using_indexes';
set global log_queries_not_using_indexes = on;
show variables like 'long_query_time';
set long_query_time = 0; (单位:秒)
show variables like 'slow_query_log'
set global slow_query_log = on;
show variables like 'slow_query_log_file';
set global slow_query_log_file = '/home/log'
实际应用过程中,使用命令行上面的配置没有生效,不知道为什么。最后修改my.ini,重启mysql之后,才生效。
慢查询日志的存储格式
select * from payment;
# Time: 2015-06-24T06:52:58.315864Z
# User@Host: root[root] @ localhost [::1] Id: 1
# Query_time: 0.076355 Lock_time: 0.061227 Rows_sent: 1 Rows_examined: 0
SET timestamp=4294967113;
包括: 主机信息、SQL执行信息、SQL执行时间、SQL内容
如何分析日志?
分析工具:
1. mysqldumpslow
mysqldumpslow -h
mysqldumpslow -t 3 日志路径 | more (前3个最慢的查询)
2.pt-query-digest工具
pt-query-digest 慢查询日志 > slow_log.report //输出到日志
//输出到数据库
pt-query-digest mysql-slow.log -review \
h=127.0.0.1,D=test,p=root,P=3306,u=root,t=query_review\
--create-reviewtable \
--review-history t = hostname_slow
如何发现问题?
1.查询次数多且每次查询占用时间长
2.I/O大的SQL rows examine参数
3. 未命中索引的SQL row examine 和 Row send参数
如何分析查询?
使用explain查询SQL的执行计划
参数含义:
table --- 从哪个表查询
type --- 从好到坏const(主键,唯一索引), eq_reg(范围查找), ref(连接查询), range(索引范围), index(索引扫描), all(表扫描)
possible_keys --- 可以用到的索引
key: 实际使用的索引
ken_len:索引长度,在不影响精度情况下,索引长度越少越好
ref: 索引的哪一列被使用
rows: mysql认为必须检查的用来返回请求数据的行数
Using filesort: 看到这个的时候,查询就需要优化。Mysql需要额外的步骤来发现如何对返回的行排序。它根据连接类型以及存储排序键值和匹配条件的全部行指针排序。
Using temporary: 需要优化。Mysql需要创建一个临时表来存储数据。通常发生在对不同的列集进行ORDER BY,而不是GROUP BY
优化MAX()
explain max(payment_date) from payment; //扫描行数较多
create index idx_paydate on payment(payment_date); //覆盖索引,按顺序排列,只需取最后一行的索引数据
优化COUNT()
count(*) 与 count(id) 区别: count(id) 对于NULL值不会计数。
子查询优化--一般优化成join方式,但需要注意是否存在一对多关系。
如果存在一对多关系的化,子查询仍然会返回正确的记录,但是join方式会返回多条记录,会有冗余,所以要添加distinct
select * from t where t.id in(select t1.tid from t1); --> select t.id from t join t1 on t.id = t1.tid;
GROUP BY
explain select actor.first_name, actor.last_name,count(*) from sakila.film_actor inner join sakila.actor using(actor_id) group by film_actor.actor_id\G;
改写为:
explain select actor.first_name, actor.last_name, c.cnt from sakila.actor inner join (select actor_id, count(*) as cnt from sakila.film_actor group by actor_id) as c using(actor_id)\G;
LIMIT
limit常用于分页处理,伴随order by 从句使用。
explain select film_id, description from film order by title limit 50,5\G;
优化步骤1:使用有索引的列或主键进行order by
优化步骤2:记录上次返回的主键,在下次查询时候使用主键过滤。(注意:保证主键连续增长)
思想:避免数据量大时候扫描过多的记录
相关文章推荐
- Oracle建立表空间和用户
- Oracle建立表空间和用户
- 初探Redis
- 不需要注册码,破解PL/SQL
- sql语句中count(*)与count(1)以及count(字段名)的异同点
- MySQL性能优化
- [MySQL]B+树索引
- nodejs怎么同步从一个数据库查询函数中返回一个值
- oracle 序列重置
- MySQL 中的常用函数
- PL/SQL DEV Debug问题
- SQLserver2008R2之登录篇
- MySQL启动多实例
- js 如何实现对数据库的增删改查
- Zabbix监控Memcached PHP-FPM Tomcat Nginx MySQL 网站日志
- mysql预编译处理(mysqli、PDO)
- Mysql 查询表中重复数据和删除表中重复的数据
- Mysql主从状态的简单监视
- lnmp 环境搭建 源代码包安装 linux,nginx,mysql,php
- Oracle job调用存储过程