Mysql 查询优化

MySQL查询优化

查询优化就是MySQl会将程序员编写的⼀些⽐较耗费性能的语句进⾏查询重写

  1. 条件化简
  2. 移除不必要的括号
  3. 常量传递:
    (1)某个表达式是某个列和某个常量的等值匹配,会直接⽤常量替换列名
  4. 移除没⽤的条件:
    (1)⽐如永远为true或false:
  5. 表达式计算:
    (1)表达式只包含常量的话,值会被计算出来
    (2)如果某个列在函数中或者以运算形式出现,优化器不会进⾏化简
  6. having和where⼦句的合并:
    (1)查询语句中没有sum、max这样的聚集函数以及group⼦句的话,优化器会将having和where⼦句合并
    (2)having⼦句⽤于分组后过滤,where⽤于分组前合并
  7. 常量表检测:
    (1)使⽤主键等值匹配、使⽤唯⼀⼆级索引列等值匹配进⾏查询的表称为常量表
    (2)优化器会优先执⾏常量表查询,因为速度⾮常快
  8. 外连接消除
  9. 优化器会将右连接转换为左连接查询
  10. 空值拒绝
    (1)在外连接查询中,指定的where⼦句中包含被驱动表的列不为null值的条件(就是不允许查出来的记录中含有null值)
    (2)被驱动表的where⼦句符合空值拒绝的条件后,外连接和内连接可以相互转换

⼦查询优化

  1. ⼦查询简介
    在⼀个查询语句中的某个位置可以出现另⼀个查询语句,这另⼀个查询就叫⼦查询
    (1)按出现位置分类
  • 在select⼦句中
    1
    select (select m1 from t1 limit 1);
  • 在from⼦句中
    1
    select m, n from (select ...);
    将这种⼦查询的结果当做⼀个表,在from⼦句中的⼦查询称为派⽣表
  • 在where或on⼦句中
    1
    select * from t1 where m1 in (select ...);

(2)按返回的结果集分类

  • 标量⼦查询
    只返回⼀个单⼀值
    1
    select (select m1 from t1 limit 1);
  • ⾏⼦查询
    返回⼀条记录,需要包含多个列
    1
    select * from t1 where (m1, n1) = (select m2, n2 from t2 limit 1);
    使⽤limit 1保证⼦查询的结果只有⼀条记录
  • 列⼦查询
    返回⼀个列的数据,可能包含多条纪录
    1
    select * from t1 where m1 in (select m2 from t2);
  • 表⼦查询
    ⼦查询的结果既有多条纪录,又有多个列
    1
    select * from t1 where (m1, n1) = (select m2, n2 from t2);
  • 按外层查询关系分类
  • 不相关⼦查询
    ⼦查询可以单独运⾏出结果,不依赖于外层查询的值

上⾯都是例⼦

  • 相关⼦查询
    ⼦查询的执⾏需要依赖于外层查询的值
    1
    select * from t1 where m1 in (select m2 from t2 where n1 = n2);

⼦查询的注意事项:

  1. 必须⽤⼩括号括起来
  2. select⼦句中的⼦查询必须是标量⼦查询
  3. 要想得到标量⼦查询/⾏⼦查询,应该使⽤limit 1
  4. 对于[not] in/any/som/all⼦查询来说,⼦查询不允许出现limit
  5. ⼦查询中不必使⽤order by:⼦查询相当于⼀个集合,集合没必要排序
  6. ⼦查询中不必使⽤distinct,因为集合也不需要去重
  7. ⼦查询中没有聚集函数以及having⼦句时,不必使⽤group by⼦句

⼦查询的执⾏⽅式

(1)不优化

  • 对于不相关⼦查询,先执⾏⼦查询,再将⼦查询的结果作为外层查询的参数
  • 对于相关⼦查询,先从外层查询中取⼀条记录,取相关列进⾏⼦查询,如此循环

(2)in⼦查询的优化
(3)物化

  • 将⼦查询的结果写⼊临时表中,该临时表就是物化表
  • 基于内存的物化表建⽴哈希索引,基于磁盘的物化表建⽴B+树索引
    (4)半连接
  • s1表和s2表半连接的意思是:对于s1表的某条肌理,只关⼼在s2表中是否存在与之匹配的记录,⽽不关⼼与多少条记录与之匹配
  • 这只是MySQL内部执⾏⼦查询的⼀种⽅式,不⾯向⽤户
    (5)实现⽅式
    (6)table pullout(表上拉)
  • 查询列表只有主键或唯⼀索引列是,将⼦查询中的表上拉到外层查询的from⼦句中

(7)重复值消除

  • ⽤临时表消除半连接结果集的重复值
  • 松散扫描
  • 半连接物化