一、order by产生using filesort详解

1.首先建表和索引(以下使用的sql版本是5.5.54)

  /*课程表*/
  create table course(
  id int primary key auto_increment,/* 主键自增*/
  title varchar(50) not null,/* 标题*/
  category_id int not null,/* 属于哪个类目*/
  school_id int not null,/* 属于哪个学校*/
  buy_times int not null,/* 购买次数*/
  browse_times int not null/* 浏览次数*/
  );
  insert into course(title,category_id,school_id,buy_times,browse_times) values('java课程',1,1,800,8680);
  insert into course(title,category_id,school_id,buy_times,browse_times) values('android课程',2,1,400,8030);
  insert into course(title,category_id,school_id,buy_times,browse_times) values('mysql课程',3,2,200,2902);
  insert into course(title,category_id,school_id,buy_times,browse_times) values('oracle课程',2,2,100,6710);
  insert into course(title,category_id,school_id,buy_times,browse_times) values('C#课程',1,3,620,2890);
  insert into course(title,category_id,school_id,buy_times,browse_times) values('PS课程',4,4,210,4300);
  insert into course(title,category_id,school_id,buy_times,browse_times) values('CAD课程',5,1,403,6080);   /*在category_id和buy_times上建立组合索引*/
  create index idx_cate_buy on course(category_id,buy_times);

2.order by 和 group by 会产生 using filesort的有哪些?

  (1)explain select id from course where category_id>1 order by category_id;

    根据最左前缀原则,order by后面的的category_id会用到组合索引

  (2)explain select id from course where category_id>1 order by category_id,buy_times;

    根据最左前缀原则,order by后面的的category_id buy_times会用到组合索引,因为索引就是这两个字段

  (3)explain select id from course where category_id>1 order by buy_times;

    根据最左前缀原则,order by后面的字段是缺少了最左边的category_id,所以会产生 using filesort

  (4)explain select id from course where category_id>1 order by buy_times,category_id;

    order by后面的字段顺序不符合组合索引中的顺序,所以order by后面的不会走索引,即会产生using filesort

  (5)explain select id from course order by category_id;

    根据最左前缀原则,order by后面存在索引中的最左列,所以会用到索引

  (6)explain select id from course order by buy_times;

    根据最左前缀原则,order by后面的字段 没有索引中的最左列的字段,所以不会走索引,会产生using filesort

  (7)explain select id from course where buy_times > 1 order by buy_times;

    根据最左前缀原则,order by后面的字段 没有索引中的最左列的字段,所以不会走索引,会产生using fillesort

  (8)explain select id from course where buy_times > 1 order by category_id;

    根据最左前缀原则,order by后面的字段存在于索引中最左列,所以会走索引

  (9)explain select id from course order by buy_times desc,category_id asc;

    根据最最左前缀原则,order by后面的字段顺序和索引中的不符合,则会产生using filesort

  (10)explain select id from course order by category_id desc,buy_times asc;

    这一条虽然order by后面的字段和索引中字段顺序相同,但是一个是降序,一个是升序,所以也会产生using filesort,同时升序和同时降序就不会产生using filesort了

  总结:终上所述,(3)(4)(6)(7)(9)(10)都会产生using filesort.

二、in和exists哪个性能更优

sql脚本:

  /*建库*/
  create database testdb6;
  use testdb6;
  /* 用户表 */
  drop table if exists users;
  create table users(
    id int primary key auto_increment,
    name varchar(20)
  );
  insert into users(name) values ('A');
  insert into users(name) values ('B');
  insert into users(name) values ('C');
  insert into users(name) values ('D');
  insert into users(name) values ('E');
  insert into users(name) values ('F');
  insert into users(name) values ('G');
  insert into users(name) values ('H');
  insert into users(name) values ('I');
  insert into users(name) values ('J');   /* 订单表 */
  drop table if exists orders;
  create table orders(
    id int primary key auto_increment,/*订单id*/
    order_no varchar(20) not null,/*订单编号*/
    title varchar(20) not null,/*订单标题*/
    goods_num int not null,/*订单数量*/
    money decimal(7,4) not null,/*订单金额*/
    user_id int not null /*订单所属用户id*/
  )engine=myisam default charset=utf8 ;   delimiter $$
  drop procedure batch_orders $$   /* 存储过程 */
  create procedure batch_orders(in max int)
  begin
  declare start int default 0;
  declare i int default 0;
  set autocommit = 0;
  while i < max do
  set i = i + 1;
  insert into orders(order_no,title,goods_num,money,user_id)
    values (concat('NCS-',floor(1 + rand()*1000000000000 )),concat('订单title-',i),i%50,(100.0000+(i%50)),i%10);
  end while;
  commit;
  end $$
  delimiter ;   /*插入1000万条订单数据*/
  call batch_orders(10000000); /*插入数据的过程根据机器的性能 花费的时间不同,有的可能3分钟,有的可能10分钟*/

  上面的sql中 订单表中(orders) 存在user_id,而又有用户表(users),所以我们用orders表中user_id和user表中的id 来in 和 exists。

结果

  1.where后面是小表

  (1)select count(1) from orders o where o.user_id in(select u.id from users u);

    

  (2)select count(1) from orders o where exists (select 1 from users u where u.id = o.user_id);

    

  2.where后面是大表

  (1)select count(1) from users u where u.id in (select o.user_id from orders o);

    

  (2)select count(1) from users u where exists (select 1 from orders o where o.user_id = u.id);

    

分析

  我们用下面的这两条语句分析:

  select count(1) from orders o where o.user_id in(select u.id from users u);

  select count(1) from orders o where exists (select 1 from users u where u.id = o.user_id);

  1.in:先查询in后面的users表,然后再去orders中过滤,也就是先执行子查询,结果出来后,再遍历主查询,遍历主查询是根据user_id和id相等查询的。

       即查询users表相当于外层循环,主查询就是外层循环

    小结:in先执行子查询,也就是in()所包含的语句。子查询查询出数据以后,将前面的查询分为n次普通查询(n表示在子查询中返回的数据行数)

  2.exists:主查询是内层循环,先查询出orders,查询orders就是外层循环,然后会判断是不是存在order_id和 users表中的id相等,相等才保留数据,查询users表就是内层循环

    这里所说的外层循环和内层循环就是我们所说的嵌套循环,而嵌套循环应该遵循“外小内大”的原则,这就好比你复制很多个小文件和复制几个大文件的区别

    小结:如果子查询查到数据,就返回布尔值true;如果没有,就返回布尔值false。返回布尔值true则将该条数据保存下来,否则就舍弃掉。也就是说exists查询,是查询出一条数据就执行一次子查询

结论

  小表驱动大表。

  in适合于外表大而内表小的情况,exists适合于外表小而内表大的情况。

三、慢查询

1.慢查询的用途

  它能记录下所有执行超过long_query_time时间的SQL语句,帮我们找到执行慢的SQL,方便我们对这些SQL进行优化。

2.查看是否开启慢查询

   show variables like 'slow_query%';

   

   slow_query_log = off,表示没有开启慢查询

     slow_query_log_file 表示慢查询日志存放的目录

3.开启慢查询(需要的时候才开启,因为很耗性能,建议使用即时性的)

  方式一:(即时性的,重启mysql之后失效,常用的)

     set global slow_query_log=1; 或者 set global slow_query_log=ON;

     开启之后 我们会发现 /var/lib/mysql下已经存在 localhost-slow.log了,未开启的时候默认是不存在的。

  方式二:(永久性的)

     在/etc/my.cfg文件中的[mysqld]中加入:

           slow_query_log=ON

  slow_query_log_file=/var/lib/mysql/localhost-slow.log

4.设置慢查询记录的时间

   查询慢查询记录的时间:show variables like 'long_query%',默认是10秒钟,意思是大于10秒才算慢查询。

     

   我们现在设置慢查询记录时间为1秒:set long_query_time=1;

   

5.执行select count(1) from order o where o.user_id in (select u.id where users);

     因为我们开启了慢查询,且设置了超过1秒钟的就为慢查询,此sql执行了24秒,所以属于慢查询。

     我们在日志中查看:

     more /var/lib/mysql/localhost-slow.log,

    

    我们可以看到查询的时间,用户,花费的时间,使用的数据库,执行的sql语句等信息。在生产上我们就可以使用这种方式来查看 执行慢的sql。

6.查询慢查询的次数:show status like 'slow_queries';

    

    在我们重新执行刚刚的查询sql后,查询慢查询的次数会变为8

    

    当然,用 more /var/lib/mysql/localhost-slow.log 也是可以看到详细结果的。

    在生产中,我们会分析查询频率高的,且是慢查询的sql,并不是每一条查询慢的sql都需要分析。

7.慢查询日志分析工具Mysqldumpslow

  由于在生产上会有很多慢查询,所以采用上述的方法查看慢查询sql会很麻烦,还好MySQL提供了慢查询日志分析工具Mysqldumpslow。

  其功能是, 统计不同慢sql的出现次数(Count),执行最长时间(Time),累计总耗费时间(Time),等待锁的时间(Lock),发送给客户端的行总数(Rows),扫描的行总数(Rows)

  (1)查询Mysqldumpslow的帮助信息,随便进入一个文件夹下,执行:mysqldumpslow --help

          查看mysqldumpslow命令安装在哪个目录:whereis mysqldumpslow

    

    说明:

    -s,是order的顺序,主要有c(按query次数排序)、t(按查询时间排序)、l(按lock的时间排序)、r (按返回的记录数排序)和 at、al、ar,前面加了a的代表平均数

    -t,是top n的意思,即为返回前面多少条的数据

    -g,后边可以写一个正则匹配模式,大小写不敏感的

    -r:倒序

  (2)案例:取出耗时最长的两条sql

    格式:mysqldumpslow -s t -t 2 慢日志文件

    mysqldumpslow -s t -t 2 /var/lib/mysql/localhost-slow.log

    

    参数分析:

      出现次数(Count),

      执行最长时间(Time),

      累计总耗费时间(Time),

      等待锁的时间(Lock),

      发送给客户端的行总数(Rows),

      扫描的行总数(Rows),

      用户以及sql语句本身(抽象了一下格式, 比如 limit 1, 20 用 limit N,N 表示).

  (3)案例:取出查询次数最多,且使用了in关键字的1条sql

    mysqldumpslow -s c -t 1 -g 'in' /var/lib/mysql/localhost-slow.log

    

    这种方式更加方便,更加快捷!

8.show profile

   用途:用于分析当前会话中语句执行的资源消耗情况

  (1)查看是否开启profile,mysql默认是不开启的,因为开启很耗性能

     show variables like 'profiling%';

    

  (2)开启profile(会话级别的,关闭当前会话就会恢复原来的关闭状态)

      set profiling=1;  或者  set profiling=ON;

  (3)关闭profile

      set profiling=0;  或者  set profiling=OFF;

  (4)显示当前执行的语句和时间

     show profiles;

       

  (5)显示当前查询语句执行的时间和系统资源消耗

      show profile cpu,block io for query 4;(分析show profiles中query_id等于4的sql所占的CPU资源和IO操作)

      或者直接 : show profile for  query 4;

    

MySQL性能优化(六)-- using filesort,in和exists,慢查询,mysqldumpslow的更多相关文章

  1. MySQL性能优化(六):分区

    原文:MySQL性能优化(六):分区 版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明. 本文链接:https://blog.csdn.net/vbi ...

  2. Java面试准备十六:数据库——MySQL性能优化

    2017年04月20日 13:09:43 阅读数:6837 这里只是为了记录,由于自身水平实在不怎么样,难免错误百出,有错的地方还望大家多多指出,谢谢. 来自MySQL性能优化的最佳20+经验 为查询 ...

  3. MySQL性能优化总结

    一.MySQL的主要适用场景 1.Web网站系统 2.日志记录系统 3.数据仓库系统 4.嵌入式系统 二.MySQL架构图: 三.MySQL存储引擎概述 1)MyISAM存储引擎 MyISAM存储引擎 ...

  4. MySQL性能优化总结(转)https://yq.aliyun.com/articles/24249

    摘要: 一.MySQL的主要适用场景 1.Web网站系统 2.日志记录系统 3.数据仓库系统 4.嵌入式系统 二.MySQL架构图:   三.MySQL存储引擎概述 1)MyISAM存储引擎 MyIS ...

  5. MySQL性能优化总结___本文乃《MySQL性能调优与架构设计》读书笔记!

    一.MySQL的主要适用场景 1.Web网站系统 2.日志记录系统 3.数据仓库系统 4.嵌入式系统 二.MySQL架构图: 三.MySQL存储引擎概述 1)MyISAM存储引擎 MyISAM存储引擎 ...

  6. MySQL 性能优化技巧

    原文地址:MySQL 性能优化技巧 博客地址:http://www.extlight.com 一.背景 最近公司项目添加新功能,上线后发现有些功能的列表查询时间很久.原因是新功能用到旧功能的接口,而这 ...

  7. MySQL性能优化总结(转)

    MySQL性能优化总结   一.MySQL的主要适用场景 1.Web网站系统 2.日志记录系统 3.数据仓库系统 4.嵌入式系统 二.MySQL架构图: 三.MySQL存储引擎概述 1)MyISAM存 ...

  8. Mysql性能优化之---(一)

    mysql的性能优化无法一蹴而就,必须一步一步慢慢来,从各个方面进行优化,最终性能就会有大的提升. Mysql数据库的优化技术 对mysql优化是一个综合性的技术,主要包括 表的设计合理化(符合3NF ...

  9. MySQL性能优化(四):SQL优化

    原文:MySQL性能优化(四):SQL优化 版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明. 本文链接:https://blog.csdn.net/ ...

  10. mysql 性能优化方案

    网 上有不少MySQL 性能优化方案,不过,mysql的优化同sql server相比,更为麻烦与复杂,同样的设置,在不同的环境下 ,由于内存,访问量,读写频率,数据差异等等情况,可能会出现不同的结果 ...

随机推荐

  1. Python 部署 flask 用uwsgi和nginx

    安装uwsgi nginx 具体方法请百度 1.在项目目录下建立.ini文件 xad_uwsgi.ini [uwsgi] master=true #项目目录 chdir=/root/zhaoyingj ...

  2. bash deploy.sh 通过bash命令 执行scp -r 命令将本地文件拷贝到服务器

    deploy.sh 文件内容如下 #!/bin/bash #scp -r ./* root@XXXXX:/root/sunSH/xadserver/ function getdir(){ for el ...

  3. hdu 1007最近点对问题

    先说下题意,很简单,给n个点的坐标,求距离最近的一对点之间距离的一半.第一行是一个数n表示有n个点,接下来n行是n个点的x坐标和y坐标,实数. 这个题目其实就是求最近点对的距离.主要思想就是分治.先把 ...

  4. drop有default constraint的column

    有时候我们在drop column的时候,会遇到一些default constraints而不能drop,如果我们已经知道constraint name,则可以用下面的语句先把constraint r ...

  5. ubuntu下man帮助文档不全怎么办?如何解决?

    真心后悔用ubuntu学习linux 发现很多东西不全,kate没有,vi版本低,帮助文档不全一系列的问题.ubuntu下man帮助文档不全怎么办?如何解决?不用担心,下边小编就为大家带来最详细的解决 ...

  6. JavaScrip——练习(做悬浮框)

    通过HTML.CSS.JSP来实现 1.首先确定通过div嵌套来实现: 大的div里放默认显示的一层,限制其总层次高,设置超出部分隐藏 小的div里放鼠标移过去时显示的一层:3行1列的表格 1.1.什 ...

  7. 使用maven创建工程报错Could not resolve archetype org.apache.maven.archetype

    错误: Could not resolve archetype org.apache.maven.archetypes:maven-archetype-quickstart:1.1 from any ...

  8. Phalcon Framework的Mvc结构及启动流程(部分源码分析)

    创建项目 Phalcon环境配置安装后,可以通过命令行生成一个标准的Phalcon多模块应用 phalcon project eva --type modules入口文件为public/index.p ...

  9. FastDFS-单机版安装

    转载自: 搭建单机版的FastDFS服务器 * 为了便于理解,其中顺序有改变. 1.第八步创建软链接,可以等到第九步结束后进行.如果提前在第八步创建软链接,因为还没有安装 libfdfsclient. ...

  10. 【Spring boot】第一个项目 Springboot + mysql + hibernate

    今天公司要做一个小项目,好久没碰项目了(刷题好累...),听说spring boot很火,决定试一试.暂时就从mysql里面读数据好了,使用hiberante. 1.获取jar包. 从http://s ...