查询优化
建索引(where 及 order by 涉及的列上建立索引)
索引使用注意点
在使用索引字段作为条件时,如果该索引是复合索引,那么必须使用到该索引中的第一个字段作为条件时才能保证系统使用该索引,否则该索引将不会被使用,并且应尽可能的让字段顺序与索引顺序相一致
索引并不是越多越好,索引固然可以提高相应的 select 的效率,但同时也降低了 insert 及 update 的效率,因为 insert 或 update 时有可能会重建索引,所以怎样建索引需要慎重考虑,视具体情况而定。一个表的索引数最好不要超过6个,若太多则应考虑一些不常使用到的列上建的索引是否有 必要。
SQL语句避免全表扫描,不然无法使用索引,以下情况会全表扫描
应尽量避免在 where 子句中对字段进行 null 值判断
应尽量避免在 where 子句中使用 != 或 <> 操作符
应尽量避免在 where 子句中使用 or 来连接条件,如果一个字段有索引,一个字段没有索引,将导致引擎放弃使用索引而进行全表扫描,or 的查询尽量用 union或者union all 代替
不要在 where 子句中的“=”左边进行函数、算术运算或其他表达式运算,否则系统将可能无法正确使用索引
应尽量避免在where子句中对字段进行函数操作
迷糊查询 like %keyword%,由于keyword前面用到了“%”,因此该查询必然走全表扫描,除非必要,否则不要在关键词前加%
对于连续的数值,能用 between 就不要用 in
根据查询原理写SQL
对于多张大数据量的表JOIN,要先分页再JOIN,否则逻辑读会很高,性能很差
更新优化
Update 语句,如果只更改1、2个字段,不要Update全部字段,否则频繁调用会引起明显的性能消耗,同时带来大量日志
个人经验之谈
select count(*) from table;这样不带任何条件的count会引起全表扫描,并且没有任何业务意义,是一定要杜绝的
任何地方都不要使用 select * from t ,用具体的字段列表代替“*”,不要返回用不到的任何字段
合理的增加冗余的字段(减少表的联接查询)
增加中间表进行优化(这个主要是在统计报表的场景,后台开定时任务将数据先统计好,尽量不要在查询的时候去统计)
根据业务分表(纵向、横向)
避免大批量的更新删除,这两个操作会锁表,导致大量访问数据库等待进而服务器奔溃
in 和 not in 也要慎用,否则会导致全表扫描,很多时候用 exists 代替 in 是一个好的选择
IN 和 EXISTS 的区别 参考https://blog.csdn.net/wqc19920906/article/details/79800374
IN 语句:只执行一次
确定给定的值是否与子查询或列表中的值相匹配。in在查询的时候,首先查询子查询的表,然后将内表和外表做一个笛卡尔积,然后按照条件进行筛选。所以相对内表比较小的时候,in的速度较快。
EXISTS语句:执行student.length次
指定一个子查询,检测行的存在。遍历循环外表,然后看外表中的记录有没有和内表的数据一样的。匹配上就将结果放入结果集中。
in 和 exists的区别: 如果子查询得出的结果集记录较少,主查询中的表较大且又有索引时应该用in, 反之如果外层的主查询记录较少,子查询中的表大,又有索引时使用exists。其实我们区分in和exists主要是造成了驱动顺序的改变(这是性能变化的关键),如果是exists,那么以外层表为驱动表,先被访问,如果是IN,那么先执行子查询,所以我们会以驱动表的快速返回为目标,那么就会考虑到索引及结果集的关系了 ,另外IN时不对NULL进行处理。
in 是把外表和内表作hash 连接,而exists是对外表作loop循环,每次loop循环再对内表进行查询。一直以来认为exists比in效率高的说法是不准确的。
not in 和not exists
如果查询语句使用了not in 那么内外表都进行全表扫描,没有用到索引;而not extsts 的子查询依然能用到表上的索引。所以无论那个表大,用not exists都比not in要快。