InnoDB
一、范围查询如何进行的?不走索引如何进行查询?
1.假设有一个以a为字段的索引树,执行select * from t1 where a>6 会先走索引树进行查询找到a=6数据节点位置。然后再把a=6节点后面的结果(通过相邻叶子节点指针)返回即可。
2.若执行select * from t1 where b=5 则会进行全表查询,从数据节点(叶子节点)从小到大遍历。
二、范围索引失效原理?
建立b,c,d字段联合索引,create index idx_t1_bcd on t1(b,c,d);然后执行select * from t1 where b>1,实际上有两种查找方式:
①是联合索引找到b=1d的数据节点位置,然后读出该节点后面的所有节点的主键,每个节点再去主键索引树进行一次回表查询。
②直接对主键索引树的叶子节点进行全表扫描。
MySQL会根据这两种方式查询效率进行比较和优化,如果是b>1可能是②方式查找效率高一些,而如果是b>100或者是select a,b,c,d(覆盖索引)可能就是①快一些。
三、order by为什么会导致索引失效?
执行select * from t1 order by b,c,d有两种方式:
①主键叶子节点全表扫描,读入磁盘后再排序。
②b,c,d索引树的叶子节点顺序就是所要排序的顺序,每个节点按照叶子节点顺序依次读出主键值,再回表查询。
四、InnoDB和MyISAM的区别是什么?
1.InnoDB支持事务,而MyISAM不支持事务。InnoDB最小锁粒度是行锁,而MyISAM最小锁粒度是表锁。
2.InnoDB是聚簇索引,数据文件和索引文件都存储在ibd文件。而MyISAM是非聚簇索引,数据文件和索引文件分开存储。
3.InnoDB不保存表的具体行数,select count(*) from table是全表查询。MyISAM用一个变量保存整个表的行数。
五、MySQL什么情况下设置了索引但是无法使用?
1.不符合最左前缀原则
2.走索引没有走全库查询效率快。
Spring
一、Spring如何创建Bean对象?
Bean类–>无参的构造方法(推断构造方法)–>普通的对象–>依赖注入–>初始化前(@PostConstruct)–>初始化(实现InitializingBean接口)–>初始化后(AOP)–>代理对象–>放入Map单例池–>Bean对象
1.调用Spring容器的getBean()函数,如果BeanName(key)存在,则直接返回Bean对象,否则创建一个新的Bean对象。首先默认会先调用该类的无参构造方法,否则去调用@Autowired注释的构造方法。其中如果构造函数的参数的为其它类对象Bean(A a),则Spring会通过先byType再byName的方式,在容器中找出一个A类的对象。(先匹配类名,再匹配对象名key是否为a)
2.创建得到的普通对象中属性都是指向null还没有赋值的,此时需要给当前Bean类内依赖的对象进行依赖注入。
首先会先通过Bean类反射去获取Bean类的属性Bean.getclass().getDeclaredFields(),找出@Autowired注解的属性然后赋值,方法也是去Spring容器内先byType再byName的方式找出那个对象并赋值。
3.初始化前可以去执行@PostConstruct注解的方法,然后看当前Bean对象是否实现了InitializingBean接口,并调用那个方法。
4.通过CGlib动态代理创建代理对象后,代理对象里面并不会给@Autowired注解的属性进行依赖注入。
二、如何解决循环依赖?
让我们初始化A bean时,如果它的初始化依赖于B bean,而B的初始化又依赖于A那么就会有循环依赖的问题。Spring是通过三级缓存来解决循环依赖:
1.首先实例化A对象,然后把A对象放入到第三级缓存中,把他的引用暴露出来,接着进行属性注入。
2.A发现依赖于B,那么此时会去三级缓存查看是否有B对象,没有则重新创建B对象,跟A实例化步骤一致。
3.这时候发现B依赖于A,getBean(A)时可以在第三级缓存找到A引用,直接返回完成B的属性注入,进而成功创建B的Bean对象,然后返回去给A,A也创建成功。
三、为什么使用三级而非二级解决IOC问题?
使用三级是出于AOP考虑,如果只使用二级缓存,在AOP情形下,可以先创建代理对象,再进行初始化一系列工作。但是这样就和Spring的AOP设计原理相悖,一般应该是Bean实例化初始化后再创建AOP对象。因此需要第三级缓存来保存产生的代理对象。