SQL的编写原则

减少查询对象的数据页(db block)数量


select * 的危害

  1. 数据表并非所有的列都有索引,select * 会导致不能进行using index,必须回表查询,导致物理I/O增加
  2. 如果表中有text或blob等字段,表一行超过16k,会导致行链接
  3. select * 会导致不能进行using index,必须回表查询,导致物理I/O增加,增加了内存负担,减少内存hit率
  4. 如果后面有order by,select * 会对排序有负担
  5. 增加网络负担
  6. 有些架构,例如Java某些框架会自动生成dataset,会对was服务器内存造成负担,如果一个表的列很多,在数据库执行不到1s,数据只有几行,但是页面响应耗时20s,所有的时间都消耗在创建dataset

查看是否使用index


索引是SQL性能调优的重要手段 下面是几个注意点,否则会出现有索引但是不能使用的情况

  1. 在索引列中不进行加工,避免隐式转换
  2. 不诱导索引列的数据类型转换,保证join时等号两边数据类型一致
  3. 比较null的时候使用isnull
  4. 尽量避免使用非等号,将不等号作为二次过滤条件
  5. like计算的时候避免使用‘%a’

用index代替sort


排序一般在内存中进行,当内存不足以满足排序时,则会产生temp file,在磁盘中进行排序。产生大量I/O,影响效率。我们在创建index的时候是有顺序的,所以尽量使用index的这一特性代替排序

hint是最后手段


hint是最终手段,不建议使用hint。原因是执行计划会随着参数的变化而不同,使用hint强制执行后,执行计划则不会发生改变。我们更多的应该根据OPTIMIZER做绝大部分优化。数据转移批量处理的时候可以考虑使用hint

减少or的使用


尽可能的将单列的or语句改写为in查询如

select * from test where id = 2 or id = 4 or id = 8;
-- 改写为
select * from test where id in (2,4,8);

编写or语句的时候一定要加括号,or的位置不同会导致结果大相径庭

单纯存在与否的时候添加 limit 1


  1. 不包含聚合函数的标量子查询的时候一定要添加limit 1 确保数据唯一
  2. count函数和limit起到的效果是一样的

减少没必要的distinct


distinct在执行计划中是看不出来了。所有包含pk的查询,distinct都是不起作用的,所以要减少这些没有必要的操作

尽量避免union 使用union all代替 避免sort


在MySQL5.6版本union,和union all区别不大。在MySQL5.7及其以上版本union会导致排序异常,所以尽量使用union all

绝对不能在没有on条件时使用join(除非有特殊目的)


在没有on条件的时候,直接join会产生很大的笛卡尔积,严重影响效率,导致cpu暴增。

outer join的时候注意on和where


  1. 真正实现left join的 从执行计划上必须left join关键字左边的表在上边,为驱动表
  2. 从执行结果上 left join的表的总集合等于left join关键字左边的集合

你可能感兴趣的:(SQL的编写原则)