首页 > 代码库 > MySQL性能优化(六)

MySQL性能优化(六)

 

一、order by产生using filesort详解

  1.首先建表和索引

/*课程表*/
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 会产生 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了

二、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);

   

 

  

三、慢查询

 

四、锁机制

MySQL性能优化(六)