SQL优化

SQL优化

2020-04-24

参考资料

  1. sql优化的几种方法:https://blog.csdn.net/jie_liang/article/details/77340905?depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-20&utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-20
  2. 数据库优化 - SQL优化:https://blog.csdn.net/jianzhang11/article/details/102867120?depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromBaidu-8&utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromBaidu-8

SQL优化方向和思路

  1. SQL查询慢。优化SQL语句,合理使用字段索引。
  2. 数据表层面:优化数据表结构、字段类型、字段索引、分表,分库、读写分离等等。
  3. 网络传输层面:减少数据库交互次数,如果能一次查询完毕的数据,就不要分成多次查询,网络传输会耗费不少时间,降低查询效率。
  4. 提升数据库服务器硬件配置,或者搭建数据库集群。
  5. 使用缓存。

SQL优化和编写技巧

  1. 合理使用索引。
    • 索引少了查询慢;索引多了占用空间大,执行增删改语句的时候需要动态维护索引,影响性能选择率高(重复值少)且被where频繁引用需要建立B树索引。
    • 一般join列需要建立索引;复杂文档类型查询采用全文索引效率更好;索引的建立要在查询和DML性能之间取得平衡;复合索引创建时要注意基于非前导列查询的情况。
  2. 对查询进行优化,应尽量避免全表扫描,首先应考虑在 where 及 order by 涉及的列上建立索引。
  3. 应尽量避免在 where 子句中对字段进行 null 值判断,否则将导致引擎放弃使用索引而进行全表扫描。 如:
    select id from t where num is null
    
    可以在num上设置默认值0,确保表中num列没有null值,然后这样查询
    select id from t where num=0
    
    • 最好不要给数据库留NULL,尽可能的使用 NOT NULL填充数据库。
    • 备注、描述、评论之类的可以设置为 NULL,其他的,最好不要使用NULL。
  4. 应尽量避免在 where子句中使用!=或<>操作符,否则将引擎放弃使用索引而进行全表扫描。
  5. 模糊查询,不能前置百分比号。前置百分比号会导致将导致全表扫描。 例如:
    select id from t where name like '%abc%'	
    
  6. 应尽量避免在 where 子句中使用 or 来连接条件,否则将导致引擎放弃使用索引而进行全表扫描,如:
    select id from t where num=10 or num=20	
    
    可以这样查询:
    select id from t where num=10	
    union all	
    select id from t where num=20
    
  7. in 和 not in 也要慎用,否则会导致全表扫描。 如:
    select id from t where num in(1,2,3)	
    
    对于连续的数值,能用 between 就不要用 in 了:
    select id from t where num between 1 and 3	
    
  8. 应尽量避免在 where 子句中对字段进行表达式操作,这将导致引擎放弃使用索引而进行全表扫描。如:
    select id from t where num/2=100
    
    应改为:
    select id from t where num=100*2
    
  9. 应尽量避免在where子句中对字段进行函数操作,这将导致引擎放弃使用索引而进行全表扫描。如:
    select id from t where substring(name,1,3)='abc'--name以abc开头的id	
    
    应改为:
    select id from t where name like 'abc%'
    
  10. 不要在 where 子句中的“=”左边进行函数、算术运算或其他表达式运算,否则系统将可能无法正确使用索引。
  11. 尽可能的使用 varchar代替char,因为首先变长字段存储空间小,可以节省存储空间,其次对于查询来说,在一个相对较小的字段内搜索效率显然要高些。
  12. 任何地方都不要使用 select * from t ,用具体的字段列表代替“*”,不要返回用不到的任何字段。
  • 执行SQL时优化器需要将*转成具体的列;每次查询都要回表,不能走覆盖索引。
  1. 谨慎使用DISTINCT,在没有必要时不要使用它,它同UNION一样会让查询变慢。(因为查询要进行唯一性判断)
  2. 减少数据访问。最好不要频繁查询数据库,如果能一次把所需要的数据查询出来,就不要分成多次查询,多次查询会大大降低查询效率,因为网络传输耗费不少时间。

连表查询优化技巧

1. Inner join 和 left join、right join、子查询

  1. 第一:inner join内连接也叫等值连接是,left/rightjoin是外连接。能用inner join连接尽量使用inner join连接
  2. 第二,子查询的性能又比外连接性能慢,尽量用外连接来替换子查询。
    • 反例:
    Select* from A where exists (select * from B where id>=3000 and A.uuid=B.uuid);
    
    执行时间:2s左右
    • 正例:
    Select* from A inner join B ON A.uuid=B.uuid where b.uuid>=3000;  
    
    执行时间:1s不到
  3. 使用JOIN时候,应该用小的结果驱动大的结果。 left join 左边表结果尽量小,如果有条件应该放到左边先处理,right join同理反向。
    • 反例:
    Select * from A left join B A.id=B.ref_id where  A.id>10
    
    • 正例
    select * from (select * from A wehre id >10) T1 left join B on T1.id=B.ref_id;
    
  4. exist 代替 in。
    • 反例:
    SELECT * from A WHERE id in ( SELECT id from B )
    
    • 正例:
    SELECT * from A WHERE id EXISTS ( SELECT 1 from A.id= B.id )
    

分析:
in 是在内存中遍历比较。
exist 需要查询数据库,所以当B的数据量比较大时,exists效率优于in。

in()只执行一次,把B表中的所有id字段缓存起来,之后检查A表的id是否与B表中的id相等,如果id相等则将A表的记录加入到结果集中,直到遍历完A表的所有记录。

你可能感兴趣的:(Java编程开发)