mysql 高级第三天:
    回顾:

    1. 7 种join 的链接写法!
      扩展掌门人的练习!
      总结:写多表关联的步骤!
    1. 2. 索引的类型:
    2. 单一索引:
    3. 主键索引:
    4. 符合索引:
    5. 唯一索引:
    6. 3. explain + sql
    7. id: 判断表的读取顺序!
    8. type
    9. system>const>eq_ref>ref>range>index>ALL
    10. key_len
    11. 使用到索引的长度,通常这个值越大越好!
    12. 公式:
    13. rows:列显示MySQL认为它执行查询时必须检查的行数。值越小越好
    14. Extra
    15. Using filesort 如果额外的列中出现了这个标识 则表示排序没有使用到索引!
    16. 解决方案:给排序字段添加索引
    17. create index idx_name on tableName();
    18. Using temporary: 表示分组没有使用到索引!
    19. Using index:表示使用了覆盖索引 :覆盖索引【后面的检索条件,正好在查询项中也存在!】
    20. using join buffer :表示关联字段没有使用索引!
    21. 4. 函数,存储过程! 最好能记住!
    22. java 有返回值的方法!
    23. 函数定义:CREATE [OR REPLACE] FUNCTION <过程名>[(参数列表)] RETURN 数据类型 IS
    24. [局部变量声明]
    25. BEGIN
    26. 可执行语句 【普通的sql
    27. EXCEPTION
    28. 异常处理语句
    29. END [<过程名>];
    30. java :没用返回值的方法!
    31. 存储过程定义:CREATE [OR REPLACE] PROCEDURE <过程名>[(参数列表)] IS
    32. [局部变量声明]
    33. BEGIN
    34. 可执行语句
    35. EXCEPTION
    36. 异常处理语句
    37. END [<过程名>];

    重点:

    1. 删除索引的存储过程!{了解}
      emp: 50万
      dept: 1万
    1. 删除:drop index idx_name on tname;
    2. #
    3. 功能: public void del(String table_schema String table_name){
    4. List<String> sList = SELECT index_name FROM information_schema.STATISTICS WHERE table_name=table_name AND table_schema=table_schema;
    5. for(int i=0;i<sList.size();i++){
    6. DROP INDEX sList.get(i) ON emp;
    7. }
    8. }
    9. 2. 索引使用:必须记住!
    10. a. 全值匹配我最爱
    11. CREATE INDEX idx_age_deptid_name ON emp(age,deptid,NAME);
    12. EXPLAIN SELECT SQL_NO_CACHE * FROM emp WHERE emp.age=30 and deptid=4 AND emp.name = 'abcd';
    13. b. 最佳左前缀法则
    14. EXPLAIN SELECT SQL_NO_CACHE * FROM emp WHERE emp.age=30 AND emp.name = 'abcd'; # 跳过了deptId 导致后面的name 不能使用索引!
    15. 或者
    16. EXPLAIN SELECT SQL_NO_CACHE * FROM emp WHERE emp.deptid=1 AND emp.name = 'abcd'; # 直接跳过了age ,后面的都不能使用索引!
    17. # 创建的索引列都存在! mysql 的优化器会自动给你排序!
    18. EXPLAIN SELECT SQL_NO_CACHE * FROM emp WHERE deptid=4 AND emp.age=30 AND emp.name = 'abcd';
    19. EXPLAIN SELECT SQL_NO_CACHE * FROM emp WHERE deptid=4 AND emp.name = 'abcd' AND emp.age=30;
    20. EXPLAIN SELECT SQL_NO_CACHE * FROM emp WHERE emp.name = 'abcd' AND deptid=4 AND emp.age=30;
    21. c. 计算、函数导致索引失效
    22. d. 范围条件右边的列索引失效
    23. SELECT SQL_NO_CACHE * FROM emp WHERE emp.age=30 AND emp.deptId>20 AND emp.name = 'abc' ;
    24. SELECT SQL_NO_CACHE * FROM emp WHERE emp.age=30 AND emp.name = 'abc' AND emp.deptId>20 ;
    25. 如果有范围条件查询的话,那么我们将其放在后面:建立对应的复合索引即可!
    26. e. 不等于(!= 或者<>)索引失效
    27. f. is not null无法使用索引,is null可使用索引
    28. g. like以通配符%开头索引失效
    29. h. 类型转换导致索引失效
    30. 3. 关联查询优化
    31. left Join
    32. EXPLAIN SELECT SQL_NO_CACHE * FROM class LEFT JOIN book ON class.card = book.card;
    33. 优化应该在on 条件后面!
    34. 情况一:在class 上添加索引
    35. create index idx_card on class(card);
    36. 情况二:在book 上添加索引
    37. create index idx_card on book(card);
    38. 综上所述:
    39. 建立索引的时候,应该在从表{被驱动表}上建立!
    40. inner Join
    41. EXPLAIN SELECT SQL_NO_CACHE * FROM class INNER JOIN book ON class.card=book.card;
    42. 会自动选择驱动表!
    43. mysql 没有full join
    44. 4. 子查询优化:
    45. 优化方案:
    46. where 筛选条件
    47. 关联条件 on
    48. 所有的条件:
    49. id : 主键索引
    50. ceo : dept.ceo 对应的掌门人
    51. deptid = 部门Id 忽略!
    52. 优化方案: 优化ceo
    53. 子查询:
    54. explain SELECT a.name ,(SELECT c.name FROM t_emp c WHERE c.id=b.ceo) AS ceoname FROM t_emp a LEFT JOIN t_dept b ON a.deptid = b.id ;
    55. left Join
    56. explain SELECT a.name,c.name AS ceoname FROM t_emp a LEFT JOIN t_dept b ON a.deptid = b.id LEFT JOIN t_emp c ON b.ceo = c.id ;
    57. 临时表:
    58. explain SELECT ab.name,c.name AS ceoname FROM ( SELECT a.name,b.ceo FROM t_emp a LEFT JOIN t_dept b ON a.deptid = b.id ) ab LEFT JOIN t_emp c ON ab.ceo = c.id ;
    59. 能使用left join 就不要使用子查询!
    60. 能够使用not in 就尽量替换成 LEFT JOIN xxx ON xx WHERE xx IS NULL
    61. NOT IN -->LEFT JOIN xxx ON xx WHERE xx IS NULL

    1. 排序、分组优化
      order by ``` a. 无过滤 不索引!

      b. 顺序错,必排序!

      c. 方向反 必排序

      当在查询数据的时候,如果将排序的字段用上了索引,那么效率必然会高!

      总结:

      1. where
      2. on
      3. order by
      4. 索引的选择:
      5. 当【范围条件】和【group by 或者 order by】的字段出现二选一时,优先观察条件字段的过滤数量,
      6. 如果过滤的数据足够多,而需要排序的数据并不多时,优先把索引放在范围字段上。反之,亦然。
    1. 双路排序和单路排序 了解:
    2. 双路排序:两次io
    3. 单路排序:一次io 但是需要调整sort_buffer_size 的容量,避免发生多次io
    4. 提高order by 的排序速度:
    5. 增大sort_buffer_size参数的设置 1M-8M
    6. 增大max_length_for_sort_data参数的设置 1024-8192字节
    7. 减少select 后面的查询的字段。 禁止使用select *
    8. 修改配置文件!
    1. <br />GROUP BY关键字优化<br />
    2. group by 先排序再分组,遵照索引建的最佳左前缀法则<br />
    3. 当无法使用索引列,增大max_length_for_sort_data和sort_buffer_size参数的设置<br />
    4. where高于having,能写在where限定的条件就不要写在having中了<br />
    5. group by没有过滤条件,也可以用上索引。Order By 必须有过滤条件才能使用上索引。
    6. 2.
    7. 覆盖索引:<br />
    8. 使用explain + sql ,在额外的选项中出现了 Using index ,则就是使用到了覆盖索引!

    select * from emp where id = 1; 表示只查询一次就可以找到数据! select id,name from emp where name = ‘zhangsan’; name 不是索引! 表示查询两次! 上述这个过程叫回表! 【了解】

    引出覆盖索引! select sql_no_cache id,age,deptid from emp where name like ‘%abc’; # 只需要查询一次!

    结论: 查询的时候 尽量 使用覆盖索引!{查询字段,尽量是索引字段}

    1. 3.
    2. 慢查询日志 {了解}<br />
    3. a. sql 语句执行的过程中超出了预定时间!<br />
    4. b. 修改my.cnf<br />
    5. slow_query_log =1<br />
    6. slow_query_log_file=/var/lib/mysql/localhost-slow.log <br />
    7. long_query_time=3<br />
    8. log_output=FILE

    c. 直接使用mysqldumpslow 进行分析: mysqldumpslow -s r -t 10 /var/lib/mysql/localhost-slow.log

    1. 总结:<br />
    2. 上午<br />
    3. a. 针对是where 条件后面的索引优化!哪些能用索引,哪些不能用索引!
    1. b. 关联查询优化
    2. on 条件 ,在被驱动表上建立索引!
    3. c. 能用left join 就不使用子查询!
    4. d. order by group by

    下午:

    1. 1. 排序、分组优化
    2. a. 无过滤 不索引!
    3. b. 顺序错,必排序!
    4. c. 方向反 必排序
    5. 2. 覆盖索引 如何使用!
    6. 尽量把查询项,与帅选项做成索引!
    7. select id,name,sex,age,addr,stuNo,email,createTimne,updateTime from stu where name = 'zs';
    8. 3. 慢查询 - 了解!

    ```