问:有哪些常见的SQL优化手段?

这也是个高频面试题,并且并非面试造火箭的那种问题,实际项目中也会有非常多的地方需要进行SQL优化

避免使用 Select *

  • select *中,无用字段会增加网络带宽消耗,特别是varcharblobtext等大字段
  • select *无法使用Mysql优化器覆盖索引的优化。

  • 覆盖索引:即一个查询可以完全通过索引来满足,不需要回表
  • 回表:根据非聚集索引查询到主键,然后根据主键查询其他数据。

分页优化

Mysql分页时,并不是跳过 offset,而是取 offset + N 行,然后丢弃 offset行,只返回N行。

并且,offset 越大、N 越大、select出的字段越多,耗时就越久。

数据量少时,分页耗时还是比较少的。

但是上数据量上百万甚至千万的时候,直接limit 1000000, 20是非常慢的。

优化方案:先根据排序规则及limit条件查询出主键,然后根据主键关联到表本身。

即把

select t.* form the_table where 条件 limit 1000000, 20 

修改为:

select t1.* from the_table t1,
(select id from the_table where 条件 limit 1000000, 20) as t2 
where t1.id = t2.id

并且条件种的字段尽量创建了索引。

尽量避免多表Join

join 关联的效率不算很高,多个表关联时会使用嵌套循环,如果关联字段没有索引,会直接使用笛卡尔积实现 join,导致全表扫描,效率很低。

两种解决方式:

  1. 单表查询,根据查询结果进行二次查询,最后在 Service 层进行关联。
  2. 数据冗余:把重要字段冗余在表中,尽可能避免关联查询。

推荐使用第一种方式,因为数据库的计算资源更加宝贵,Service层可以很方便的水平扩展。并且如果数据量非常大的时候也会进行分库分表,这也会限制join。

建议不要使用外键与级联

外键概念应该在应用层解决。

选择合适的字段类型

存储字节越小,占用空间就越小,性能也就越好。

尽量使用 union all 代替 union

union会把结果集进行去重操作,更耗时。

批量操作

操作数据时,能批量操作尽量批量处理,减少请求数据库的次数。

使用Explain分析SQL

正确使用索引

适合作为索引的字段

  • 不为null的字段:索引字段应尽量不为null,对于数据为null的字段,数据库比较难优化。如果字段频繁被查询,又无法避免为null,可以使用-1、0、true、false等语义清晰地短字符作为代替。
  • 被频繁查询的字段
  • 被作为条件查询的字段
  • 频繁需要排序的字段
  • 频繁用于外连接的字段

被频繁更新的字段应慎重建立索引

虽然索引能带来查询上的效率,但是维护索引的成本也不小。
如果字段不经常被查询,反而经常被修改,那不应该在这种字段上创建索引。

尽可能创建联合索引,而不是单列索引

索引需要占用空间,如果是联合索引,多个字段在一个索引上,可以节省空间,并且修改数据时效率也会提升。

避免冗余索引

考虑在字符串类型上使用前缀索引代替普通索引

前缀索引只适用于字符串类型,比普通索引占用更少的空间

避免索引失效

  • 使用 select *查询
  • 创建了联合索引,但是没有遵循最左匹配原则
  • 在索引列上进行计算、函数、类型转换等操作
  • %开头的like查询,比如like '%abc'
  • 发生隐式转换
  • 查询时使用条件1 or 条件2,如果条件1或者条件2中存在未创建索引的字段,就不会使用索引

标签: SQL, 数据库, MySQL

添加新评论