举个例子 当进行一条sql查询时:
select * from student where userName='小明' and age=19 and phone='1887821';
创建了一个单列索引:
ALTER TABLE student ADD INDEX userName_index (userName);
将userName列建索引,这样就把范围限制在userName='小明'的结果集上,之后扫描结果集,产生满足age='19'的结果集,再扫描该结果集,找到 phone=1887821的结果集,即最终结果。
由于创建了列索引所以比将表完全扫描相比减少了扫描比对数据的次数。
这存在一些问题,假如创建的是age列建索引,最左匹原则第一次userName匹配未命中的话,是直接全盘扫描还是,向下匹配age列建的索引。我在博客:看到:
当一条sql语句提交给mysql数据库进行查询的时候需要经历以下几步
1、先在where解析这一步把当前的查询语句中的查询条件分解成每一个独立的条件单元
2、mysql会自动将sql拆分重组
3、然后where条件会在B-tree index这部分进行索引匹配,如果命中索引,就会定位到指定的table records位置。如果没有命中,则只能采用全部扫描的方式
4、根据当前查询字段返回对应的数据值
以上解释在我看来应该是倾向于后者,但是具体的还要继续学习,等以后查清楚了在做修改。
创建了多单列索引:
ALTER TABLE student ADD INDEX userName_age_phone_index (userName,age,phone);
这种创建索引的方式在多项查找时要优于单一索引,由于mysql的采用的b+树方式,因此不在需要扫描任何记录,直接就可以得到满足需求的结果集。而这种方式其实相当于创建了三个索引(userName),(userName,age),(userName,age,phone)。
因此在当进行以下查询时仍会命中mysql索引
select * from student where userName='小明';
select * from student where userName='小明' and age=19;
select * from student where userName='小明' and age=19 and phone='1887821';
mysql有些情况在查询时也可能不会命中索引如
1.如果where后面有or,这样不会命中索引如:
select * from student where userName='小明' or age=19;
如果想要or后面的也走索引的话,应该是创建两个单列索引
2.like是以%开头的不会命中索引如:
select * from student where userName like %明
3.如果列类型是字符串,那一定要在条件中将数据使用引号引用起来,否则不使用索引如:
select * from student where userName='小明' and age=19 and phone=1887821;
4. 没有查询条件,或者查询条件没有建立索引
5. 查询条件中,在索引列上使用函数(+/-*/)
select * from student where userName='小明' and age-1=19 错误
select * from student where userName='小明' and age=20 正确
6. 采用 not in, not exist
7. B-tree 索引 is null 会走, is not null 不会走
只是简单学习要是有,错误的地方可以指正哦,日后会根据学习的深入在做补充