Mysql高级 索引(二)

390 阅读3分钟

索引场景

1.mysql索引:

  1. 主键自动建立唯一索引
  2. 频繁查询字段应该建索引
  3. 频繁更新字段不要创建索引
  4. where里用不到的字段不要建索引
  5. 组合索引比单值索引更好
  6. 建索引还要考虑order by
  7. 查询中统计或分组(分组前提必排序)字段

2.不建索引:

  1. 经常增删改的表
  2. 数据重复且分布平均(数据差异不高)
    • 索引选择性 = 一列中不同的值/一列中数据记录条数 越接近于1 建索引性能越好
  3. 表太小

3.性能分析

  1. mysql优化器
  2. MySQL瓶颈
    • cpu
    • io
    • top, free, iostat, vmstat查看性能
  3. explain(执行计划)
  4. explain作用
  • 表的加载顺序 看id
  • 数据读取的操作类型 select_type
    explain select * from tbl_emp emp left join tbl_dept dept on emp.deptId = dept.id;
    
    • 怎么用 explain + sql语句

explain表头解释

id

  • id相同 表示执行顺序相同的情况下 执行顺序从上到下 如下图emp, dept, id都是1, 执行顺序emp然后dept
  • id不同, id大的先执行 t3 t1 t2表
  • id有相同有不同 先走数字大的, 数字相同顺序执行 derived表示衍生, 2表示id=2

primary

  • 最外层是primary, 最后加载的
  • simple 简单的select 不包含子查询 union
  • subquery 在select或者where列表包含的子查询
  • derived from中包含子查询会被标记为衍生, 放在临时表里
  • union 第二个select语句标记在union之后, 则被标记为union, 若union包含在from子句查询中,外层select会被标记为 derived
  • union result 从union表获取结果的select

table

  • 数据关于哪张表

type 访问类型排列

从好到差

  • system > const > eq_ref > ref > range > index > all(全表扫描)
    • system 只有一行记录(等于系统表)
    • 只匹配一行数据,比较primary key或者unique(相当于常量)
    explain (select tbl_dept.id from tbl_dept where id = 1);
    
    • eq_ref 唯一性索引扫描 (t1, t2比如t2是boss表, t2数据只有一个)
    • ref (一对多 = )
    • range(between , < , > , in) 有个范围
    • index 全索引扫描,遍历了索引树, id是主键本来就建了索引
  • range/ref级别就差不多可以了

possible_keys 和 keys

  1. possible 可能运用到表中的索引, 可能一个或多个 但不一定使用
  2. keys实际用的索引, 如果为null则没有用索引(查询中若用了覆盖索引, 则该索引仅出现在key列表中, select后面字段都在建好的索引内)

key_len

  • 表示索引中使用的字节数,
  • 显示的值为索引字段最大可能长度, 而非实际长度, 是根据表定义计算而不是检索

ref

  • 第一个const 表示 t1.other_column = '' 常量
  • 第二个test.t1.ID表示索引哪些列被引用(关联)

rows

  • 大致估算每张表多少行被优化器查询 越少越好 建立索引前 ---- 建立索引后, 641行-143行

extra

  • using filesort 产生文件内排序, 没有按照索引的排序, 而是mysql自己重新排序了
  • using temporary 新建了内部的临时表, 常见于order by/ group by
  • using index 表明用了覆盖索引
  • using where where值总是false
  • using join buffer join多了用到了buffer
  • impossible where 不太可能
  • distinct 很少用