建表SQL
索引情况
一、全值匹配我最爱
二、最佳左前缀法则
1、where条件列的,从索引的最左前列开始,且不跳过索引中的列
2、违背原则:未以最左前列开始,索引失效
3、违背原则:跳过索引中间列(age),只引用了部分索引
结论:
where条件要满足
最佳左前缀法则。
口诀:带头大哥不能死,中间兄弟不能断
三、不在索引列上做任何操作(计算、函数、自动or手动类型转换),会导致索引失效而转向全表扫描
即使满足最左前缀原则,但where条件中使用了函数后,索引失效
四、存储引擎不能使用索引中范围条件后边的列
结论:组合索引中的列name用来检索,age只且到索引排序(没用到索引检索),而age后边的列pos就会失效了。
疑问:若使用最左边列做范围查找,那么后边的几个条件还会用到索引吗?
五、尽量使用覆盖索引(只访问索引的查询(索引列和查询列一致)),减少select *
1、select*,从表中检索数据
2、按需要查字段,从索引中检索数据
3、按需要查字段(查询列可只用索引列中的一部分),范围查询、未使用范围查询、查询部分索引列分析对比
结论:满足原则五时,用范围查找时,查询类型type:ref,而不是range,参考原则四的说明
六、mysql在使用不等于(!=或者<>)的时候无法使用索引会导致全表扫描
案例如下:
七、is null,is not null也无法使用索引
八、like以通配符开头('%abc')mysql索引失效,变成全表扫描的操作(注:以通配符结尾('abc%')不会失效)
1、以通配符开头,全表扫描,索引失效
2、未以通配符开头,只是通配符结尾,查询类型:range范围查找(未全表扫描),索引可用
3、问题:解决like '%字符串%'时索引失效的方法??》》》用覆盖索引来解决
案例分析如下
3.1 表结构:
3.2 未建索引(只设置了主键为id)
结论:全表扫描,未使用索引
3.2.2 只查一个id字段的情况,也未用到索引
3.2.3 以下几种情况都未使用到索引,执行后都是全表扫描
3.3 创建索引
3.3.1 重新分析
用覆盖索引 ,只查name,age
只查主键id,覆盖索引查询,索引有效
只查name或只查age,覆盖索引查询,索引有效
查询列的个数超过索引列的个数时(id不考虑在内),索引失效
总结:用覆盖索引来解决 '%字符串%'查询的问题
九、字符串 不加号索引失效
不加引号时,mysql会给name字段做隐式的类型转换(将整数类型转换成字符串型),违反了第三条原则:索引列上无计算,所以索引会失效
十、少用or,用它来连接时会索引失效
小结:不要因为以上各种情况的索引失效而感到束手束脚,在实际应用中,也难免会出现索引失效的情况,sql最优并不代表满足以上所有原则
口诀:
全值匹配我最爱,最左前缀要遵守;
带头大哥不能死,中间兄弟不能断;
索引列上无计算,范围之后全失效;
like百分加右边,覆盖索引不写星*
不等空值还有or,索引失效要少用;
字符串里有引号,SQL高级也不难
二、面试题讲解
题目SQL
1、顺序问题
1.1、where条件有带头大哥,中间兄弟顺序乱 ,索引有效
1.2、where条件带头大哥往后站,中间兄弟顺序乱,索引有效
1.3 原因:mysql有自带的sql优化器,where查询条件顺序问题并不会导致索引失效
2、范围之后全失效(C3只用来做排序)
3、where条件中C4列做范围查找,C1,C2,C3,C4索引列都生效
4、where条件有带头大哥,但中间兄弟断,sql用了order by,索引部分失效
4.1 条件中有C4
用到了索引中的c1,c2用作查找,只用到c3做排序,未用到索引中的C4
4.2 条件中没有c4,分析结果跟4.1相同
4.3 中间兄弟C3断,索引在排序中失效,出现了filesort
5 、filesort的 问题
5.1 只用到c1一个索引,排序用了c2,c3(按序),未出现filesort
5.2 只用到c1一个索引,排序用了c3,c2(乱序),出现了filesort
小结:查找和排序列的顺序最好按照索引列的顺序来
5.3 用到c1,c2两个索引,排序用了c2,c3(按序),未出现filesort
5.4 用到c1,c2两个索引,排序用了c3,c2(乱序),未出现filesort
原因 :因为在查找条件中用了c2,所以order by排序时,c2已经是一个常量了,换句话说只要按[order by c3,常量]来排序,并不会产生filesort
6、group by分组前必排序,所以索引使用原则和索引优化法则基本跟order by 相同,违反法则时会产生临时表和filesort
三、一般性建议