Mysql性能分析之explain

# 猜想

第一反应大概就是product_id没有建索引,事实确是如此,项目历史悠久,表索引建的很随意,再加上后续修改,已经不是当时的使用环境了,这里记录为了复习一下mysql的explain.

# explain

# id

描述table优先级

  1. 不存在子查询的sql;执行explain只会出现一条结果,且id=1 select * from t_user;
  2. 不存在子查询的sql;执行explain只会出现两条结果,且id都为1,表示两个表优先级从上到下; select * from t_user,t_role;
  3. 存在子查询;出现两条结果,且id递增,id=2的表为t_role优先级更高; select * from t_user u where u.user_id = (select r.user_id from t_role r where r.role_id = '')

# select_type

区分简单查询和复杂查询(子查询、联合查询等)

  • SIMPLE 简单的select查询,查询中不包含子查询或者UNION
  • PRIMARY 查询中若包含任何复杂的子部分,最外层查询则被标记为PRIMARY
  • SUBQUERY 在SELECT或WHERE列表中包含了子查询
  • DERIVED 在FROM列表中包含的子查询被标记为DERIVED(衍生),MySQL会递归执行这些子查询,把结果放在临时表中
  • UNION 若第二个SELECT出现在UNION之后,则被标记为UNION:若UNION包含在FROM子句的子查询中,外层SELECT将被标记为:DERIVED
  • UNION RESULT 从UNION表获取结果的SELECT

# table

表示当前执行的表

# type

查询使用的类型

type 含义
system 表只有一行数据,const类型的一种特例
const 只匹配一行数据,找到就返回,所以很快;场景:where查询条件为主键或唯一索引查询
eq_ref 唯一索引扫描
ref 非唯一索引扫描

查询效率从好到差依次为:system > const > eq_ref > ref > range > index > all;
一般而言,最低要求为range

# 一顿分析猛如虎

  首先查看表结构,发现supplier_id,product_id同为primary key,也就是联合主键,supplier_id可以重复,product_id也可以重复, 但是supplier_id+product_id不能重复;联合主键包含1个以上字段,并且会自动创建复合索引,既然是复合索引就符合最左匹配原则(简单来讲就是 带头大哥不能死,中间兄弟不能断),如果兄弟断了,索引有效范围就在断弟之前...
  回到正题,那么直接使用product_id作为查询条件,不符合带头大哥不能死的要求,所以会扫描全表,执行explain得知 type=ALL;