(三)MySQL高级——索引优化多案例

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Steriles_/article/details/84134371

最佳左前缀法则:如果索引了多列,就要遵守该法则。该法则指的是查询从索引的最左前列开始并且中间不跳过索引中的列

一、索引失效(应该避免)

(1)案例一:建立的索引是age、name、pos一起的,前两个情况中缺失第一个字段,或者中间缺失索引列都是没有用上最佳左前缀法则的,应该避免。

虽然显示用到了索引,但是可以上下比较key_len的长度并没有改变,这与实际是两个筛选条件是不相符的,因此这也是违背了最佳左前缀法则,查询中间跳过了索引中的列。此索引只用到了name,是部分匹配。

(2)案例二:在索引列上做任何操作(计算、函数、(自动or手动)类型转换),会导致索引失效而转向全表扫描。下图展示的就是两种查询语句都可以实现查询目的,但是在性能上有着很大的差异。

(3)案例三:在存储引擎中使用了索引中范围条件右边的列。由下图的对比其实已经很明确的清楚了,最后一条查询记录显示,在使用范围条件去筛选时,如果三个都被用到,那么key_len也不会是78而是140;那要是没有用到范围条件的话,type内容也不会是range。age>11是用到了,但是主要是用去排序的作用,name用去查找,所以后面的pos是没有被用到的。由此可以理解这个口诀:范围之后全失效。

(4)案例四:使用覆盖索引(只访问索引的查询(最好是索引列和查询列一致)),减少使用select *的使用。通过下图这两个select语句比较,就会发现不使用select * 的语句执行效果会能达到Using  index。

结合上一个案例中的范围条件,可以得到以下对比图。通过比较可以知道,案例三中,使用的是select * 语句,但是在下图中使用的是selece全索引的语句,那么这个age上的范围查询就不是用来去做排序了,而是用来做匹配查询了。这个可以用type内容为ref证明。

(5)案例五:MySQL在使用不等于(!=或者<>)查询的时候无法使用索引会导致全表扫描。下图显示的就是,没有用到索引以及是全表扫描了。但是不要因为会导致索引失效而不使用不等于查询,具体也是要看实现功能或者业务逻辑的,能够清除使用不等于查询会导致无法使用索引就行了。

(6)案例六:使用IS  NULL  或者 IS  NOT  NULL 也会导致无法使用索引。就算可能会用到的索引,在实际使用的时候并没有用上,跟上一个案例类似。

(7)案例七:LIKE以通配符开头(格式为:'%abc...'或者'%abc%...'),MySQL索引失效,会变成全表扫描的操作。所以用LIKE查询的时候,通配符放在右边,就可以使用索引,且type的内容为range。

解决LIEK ‘%字符串%’时索引不被使用的方法:用覆盖索引。所以一般用两个原则:LIKE百分号写右边;如果需要两边都有百分号就用覆盖索引解决索引问题。

(8)案例八:字符串不加单引号导致索引失效。这个就涉及到案例二中的问题了,不可以在索引列上做任何操作,包括这里的类型转换,尽管是隐式的操作,也是会导致索引失效的。下图所示的在查询name的值为‘2000’的时候,加单引号和不加单引号的性能分析,显而易见这违背了案例二中的原则。

(9)案例九:少用or,用它来连接时索引会失效。这里是少用,不是不用,具体还是要看实际需求的。

口诀:

全值匹配我最爱,最左前缀要遵守;

带头大哥不能死,中间兄弟不能断;

索引列上无计算,范围之后全失效;

LIKE百分写最右,覆盖索引不写星;

不等空值还有or,索引失效要少用;

字符串里有引号,SQL高级也不难。

二、一般性建议

对于单键索引,尽量选择针对当前query过滤性更好的索引;

在选择组合索引的时候,当前query中过滤性最好的字段在索引字段顺序中,位置越靠前(即靠左)越好;

在选择组合索引的时候,尽量选择可以能够包含当前query中的where字句中更多字段的索引;

尽可能通过分析统计信息和调整query的写法来达到选择合适索引的目的。

猜你喜欢

转载自blog.csdn.net/Steriles_/article/details/84134371