1. create table dept(
  2. id int unsigned primary key auto_increment,
  3. deptno mediumint unsigned not null default 0,
  4. dname varchar(20) not null default "",
  5. loc varchar(13) not null default ""
  6. )ENGINE=innodb DEFAULT CHARSET =utf8;
  7. create table emp(
  8. id int unsigned primary key auto_increment,
  9. empno MEDIUMINT UNSIGNED not null default 0,
  10. ename varchar(20) not null default "",
  11. job varchar(9) not null default "",
  12. mgr MEDIUMINT UNSIGNED not null default 0,
  13. hiredate date not null,
  14. sal decimal(7,2) not null,
  15. comm decimal(7,2) not null,
  16. deptno mediumint unsigned not null default 0
  17. ) engine=innodb default charset=utf8;
  18. -- 创建函数,例如报错: This function has none of deterministic
  19. show variables like 'log_bin_trust_function_creators';
  20. set global log_bin_trust_function_creators = 1;
  21. -- 创建函数,例如报错: This function has none of deterministic
  22. show variables like 'log_bin_trust_function_creators';
  23. set global log_bin_trust_function_creators = 1;
  24. -- 存储工程
  25. -- 随机生成字符串
  26. DELIMITER $$
  27. create FUNCTION rand_string(n int) returns varchar(255)
  28. begin
  29. declare chars_str varchar(100) default 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
  30. DECLARE return_str varchar(255) default '';
  31. declare i int default 0;
  32. while i <n do
  33. set return_str = concat(return_str,substring(chars_str,floor(1+rand()*52),1));
  34. set i = i+1;
  35. end while;
  36. return return_str;
  37. end $$;
  38. -- 随机生成部门编号
  39. delimiter $$
  40. create function rand_num()
  41. returns int(5)
  42. begin
  43. declare i int default 0;
  44. set i = floor(100+rand()*10);
  45. return i;
  46. end $$
  47. -- 插入数据给emp
  48. delimiter $$
  49. create procedure insert_emp(in start int(10),in max_num int(10))
  50. begin
  51. declare i int default 0;
  52. set autocommit =0;
  53. repeat
  54. set i = i+1;
  55. insert into emp(empno,ename,job,mgr,hiredate,sal,comm,deptno)
  56. values((start+i),rand_string(6),'SALESMAN',0001,curdate(),2000,400,rand_num());
  57. until i = max_num
  58. end repeat;
  59. commit;
  60. end $$
  61. -- 插入dept数据
  62. delimiter $$
  63. create procedure insert_dept(in start int(10),in max_num int(10))
  64. begin
  65. declare i int default 0;
  66. set autocommit = 0;
  67. repeat
  68. set i = i+1;
  69. insert into dept (deptno,dname,loc) values((start+i),rand_string(10),rand_string(8));
  70. until i = max_num
  71. end repeat;
  72. commit;
  73. end $$
  74. call insert_dept(100,10);
  75. call insert_emp(100001,500000);
  76. select * from dept;

image.png

实战

in还有exists

-- 前提 dept :10行    emp: 500000行

-- 用in的时候,in后面的表是小表
-- 耗时 1.561s
select * from emp e where e.deptno in (select deptno from dept);
-- 耗时 5.538s
select * from emp e where exists (select 1 from dept d where d.deptno = e.deptno)



-- 用exists时,exists后面出现的是大表,虽然时间看起来很小

-- 耗时 0.230s
select * from dept d where d.deptno in (select deptno from emp);
-- 耗时 0.122s
select * from dept d where exists (select 1 from emp e where e.deptno = d.deptno)

两表联查

-- 前提  所有都没有index
-- 耗时 2.400s
select e.* from emp e left join dept d on e.deptno = d.deptno;

-- left join在右边添加索引
alter table dept add index idx_dno(deptno);


-- left join在右边添加索引,耗时1.891s

select e.* from emp e left join dept d on e.deptno = d.deptno;





-- 我们测试一下在大表上添加索引,并删除之前创建的索引
-- alter table dept drop index idx_dno;

-- 耗时1.426s
alter table dept add index idx_dno(deptno);
select e.* from dept d left join emp e on d.deptno = e.deptno




-- 两张表都加索引
alter table emp add index idx_dno(deptno);

alter table dept add index idx_dno(deptno);


-- 耗时 2.143s
select * from dept d left join emp e on d.deptno = e.deptno;

-- 耗时 2.579s
select * from emp e left join dept d on e.deptno = d.deptno;


-- 推荐使用小表驱动大表