关于SQL的常规优化

111 阅读4分钟

一、关于索引

  1、对关联关系字段、常用查询条件且基数高的字段(对于低基数字段如性别建立索引所提供的性能提升有限)、排序字段、唯一值字段建立索引

  2、索引字段值应该尽量简短,字段太长会影响索引效率,如果一定要对大字段创建索引,可以考虑前缀索引

    即:CREATE INDEX idx_field_prefix ON table (SUBSTR(field, 1, 10));
        select field... from table where field like 'content%';

  3、复合索引的创建,越频繁使用的字段应该放在更左侧,字段不能过多

     - 过多字段会增大索引维护开销、存储成本
     - 并非所有查询都会涉及到多个索引列,应该经常结合使用的字段组合成为复合索引
     - 复合索引太大也会影响到内存效率
     - 复合索引字段过多,会导致索引扇出过高,虽然会提高数据读取的效率,不利于数据的写入能力

  4、复合索引包含列不是越多越好,索引数量也不是越多越好                  索引虽然提高了 select 的效率,但是也降低了 insert 和 update 的效率,创建索引应该谨慎

  5、避免回表,应该尽量使用覆盖索引

  6、对于复合索引的使用,应该满足最左匹配原则

    例如:index(a, b, c),则where语句中条件应为 a = ? and b = ? and c = ?
	- 最左匹配原则只要满足最左前缀就可以利用索引
	- 查询条件中的范围查询条件右侧的字段不能使用索引
	- 可以配合覆盖索引一起使用

  7、对于索引类型,范围查询和排序操作,应该选择B-Tree,确定值匹配应该选择Hash

  8、为了系统后期维护和数据可靠性,尽量不要使用外键

  9、应该善于使用explain来判断sql对索引的使用情况

  10、一定要定期维护索引列

二、关于SQL

  1、创建表应该选择合适的的存储引擎。绝大多数情况下,数据表应该创建主键

  2、select 查询应指定具体的字段。可以考虑利用MyBatis的 <sql> 标签定义字段sql片段

  3、创建表的时候字段应该尽量为 NOT NULL ,不管是后期维护优化或者是开发过程,不用判断字段是否为null都是非常友好的

  4、对有空值字段的表的查询,应该尽量避免在 where 语句中对字段进行 null 值判断

  5、对于非确定值的查询,应该避免在 where 语句中使用 != 、<> 符号,会导致索引失效

  6、对于连续的值的判断,能用 between 就不要用 in,如果范围太大的情况下,使用in会进行全表扫描,也尽量避免使用 not in,因为大多数情况下 not in 不会使用索引

  7、使用 in 的时候,越频繁使用的字段应该尽量放前面,减少判断次数

  8、对于 like %,应该确保 % 前面是确定前缀,以此来使用索引

  9、在创建字段的时候能用数字类型尽量使用数字类型字段,可以提升查询的性能,减小存储开销

  10、能不用临时表就不要用临时表,毕竟要跨数据通信,会影响速度

  11、对于大数据量、复杂且重复使用的关联关系的查询可以尝试用临时表,降低对主表的压力、竟争压力,提高并发能力。但是,大数据量、大字段或者复杂的关联关系,应该首先考虑是否是表设计不合理?

  12、避免考虑复杂情况,尽量不使用nolock,一定要使用nolock需要考虑是否会拿到脏数据

  13、联表查询,关联表的数量尽量不要超过5个,尽量用别的方式来代替多连接的情况,比如临时表

  14、联表查询应该小表驱动大表

  15、对于主要业务表,能不用子查询就不用子查询

  16、尽量将数据的处理逻辑放在代码层面,或者存储过程(当然,平时接触少就还是别用吧),系统瓶颈大多都在数据库,那就让数据库单纯地存储数据就好了

  17、使用 gourp by 时,尽量将过数据滤条件放在之前,可以提升效率

  18、where 条件语句中应该避免使用 or 连接条件,会导致索引失效进行全表扫描 最好是用 union all 合并查询

  19、应该避免在 where 语句中使用函数、表达式,并且需要保证数据类型匹配,否则会导致全表扫描

  20、尽量避免大事务