一、要会使用explain查看SQL的执行计划
下面是简单的使用一个语句示范
上面有几个关键的列,说说关键的几个列的意义
type列:表连接的类型,一个好的SQL一定要达到range级别以上,常见的有system,const,ref,range,ALL等,ALL表示最差
Key列:使用到的索引类型,如果没有使用到索引,则显示为NULL值。MySql有可以强制走索引方式。
Key_len列:索引的长度。
Rows列:扫描的行数,这个是预估值。
Extra列:常见的不友好的值有Using filesort, Using temporary。表示Mysql执行是可能使用到的条件方式。
详细的大家个搜索explain的参数讲解
二、SQL语句中IN包含的条件不能太多
MYSQL对有做过优化,IN中的常量会放入一个数组,并且这个数据是排好序的。如果IN中包含的值太多,会产生的消耗也更多对于常见优化例如范围值查询尽量换成between
select id from XXXXX where id IN(1,2,3) 换select id from XXX where id between 1 and 3 。
三、SELECT 字段时,最好写出需要的字段名称,避免盲目使用*
Select * 会增加一些不必要的带宽消耗(CPU,IO,内存,网络带宽)等;增加了覆盖索引的可能性,当表的结构发生变化时,前端也需要更新,所以最好在select 后面接上你所需要的字段名。
四、如果排序的字段没有用到索引,尽量少排序
这个会有可能导致MYSQL不走索引。
五、在限制条件中有字段是没有索引的,避免使用or
or 的两边中,如果有一个不是索引字段,而其他条件也不是索引字段的情况,会导致SQL不走索引查询,使用or最好两边是都索引字段。或者也可以用union 和union all来代表。
六、尽量使用union all 来代替union
两者的差异主要在于一个不会对结果集过滤,一个会对结果集唯一性去重。这就会涉及排序的操作,增大CPU的运算跟资源消耗。看业务的情况选择使用,如果两个结果集没有重复内容最好使用union all 。
七、区分使用IN 与exist 跟not IN 和ont exist
例如常用写法有 select id from 表A where id IN (select id from 表B )。大多数的习惯
上面应改成 select id from 表A where exist (select id from 表 B where 表A.id = 表B.id)。
IN 与exist区别在于,表的驱动顺序不一样,如果使用的是exists,那么以外表作为驱动先访问外表,如果是IN 那么优先执行子查询。 IN适合于外表大内表小的情况,exist 适合外表小内表大的情况。这里涉及的效率问题类似于left join 跟right join 使用如图下
这是表A的数据比B多,如果使用左链接,以A作为驱动表的话,B表中没有多余的数据与A表匹配,还是会继续匹配下去
没有对应则以NULL返回,本来1-1,2-2的。下面的9之12则变成9-null,10-null,多出的不必要的操作会影响SQL的效率。
八、避免在where条件中直接进行null值判断
对于null值,会导致引擎放弃走索引进行全表扫描。
九、不建议使用% 在前缀进行模糊查询
例如 like "%name" 或 like "%name %",这种查询会导致索引失效进行全表扫描。使用 like "name%" 是可以的,这种SQL还是会走索引的,如图
十、避免在where条件中进行表达性的运算
如: select user_id,user_name from user_info where age*2=24;
对字段就行了算术运算,这会造成引擎放弃使用索引,建议改成:
select user_id,user_name from user_info where age=24/2;
十一、必要的时候可以使用force index 强制查询走某个索引
有的时候MySQL优化器采取它认为合适的索引来检索SQL语句,但是可能它所采用的索引并不是我们想要的。这时就可以采用forceindex来强制优化器使用我们制定的索引。