由第一个图(二叉树,可以想象为只有两个分支的Btree)可知索引创建后本生就排好序了,这个排序特性决定了等值查询或者非等值的查询可以快速定位数据范围位置,模糊搜索时的varchar类型的排序BTree索引,在like 'asd%'时也是能快速锁定范围的,但是如果%在前边例如:like '%asd' 是无法利用索引的
下图是BTree树
很多时候我们可能还会用到符合索引,使用时要注意满足最佳左前缀原则(了解符合索引的存储结构变回理解为何要遵循此原则了);
如果某个where条件可适用于多个索引,一般会使用最早建立的那个,所以在有些优化时为了使新的索引生效不被之前的顶替,需要建立完自己的索引,在删掉原来的索引,再重新建立原来的索引,举例:t表有a,b两个字段如果我们在a列建立了索引,之后我们邮件里了(a,b)的复合索引,然后我们在查询select * from t where a=1 and b=2 时按理说使用复合索引更佳高效,但是由于之前的a上的单独索引也适用于该查询使得复合索引未被使用到,更好的或者使用force index(索引名...)参考:https://blog.csdn.net/bruce128/article/details/46777567
优化参考资料:https://mp.csdn.net/postedit/103472357
还有一点补充的:因为使用Innodb引擎使用的是行级锁,但如果数据在更新的时候使用的条件不是带索引的或者索引失效了,将导致此次更新操作变为表级锁;间隙锁:也是在使用索引的前提下,例如更新条件是 id>1 and id<10 则若要插入一条id为2-9之间的 的数据时会被锁住,导致等待。理解了索引的特性这些都好理解
另外说一些于无关索引的优化:
数据库引擎如果遇到嵌套循环,倾向于将大的循环放到内层,小的外层,例如在A left join B on A.id=B.aid 如果A是小表B是大表,则最内层的循环是A的某一条循环跟B的所有比较,满足内大外小的原则,效率会普遍的高一些,同样此规律在in和exists子查询使用时也适用,在以A表为主查询,B为子查询时,若A大B小则使用in(内层循环逻辑是in中的某个值一次和A中的比较 eg:select A.* from A where A.id in (select B.aid from B) );反之A小B大则使用exist(内层循环逻辑是A中的某一条数据依次和B中的进行逻辑判断 eg:select A.* from A where exists (select 1 from B where B.aid=A.id) )
mysql4.1之后数据库默认是单路路排序,但是如果max_length_for_sort_data太低不足以支持某次查询的单路排序,会自动转为双路排序,因此通过提升max_length_for_sort_data可避免此情况发生,从而提升数据库检索性能