2023春招上海亿保健康科技集团有限公司.社招.一面面经
公司简介
面试官问题
1.介绍一下MySql的索引
定义:索引是帮助MySQL高效获取数据的排好序的数据结构。
索引的数据结构:
二叉树
红黑树
Hash表
B-Tree
-
二叉树
如果查询的元素是自增,都放到了右子树上,比如查询7这个结点,我们就需要查询6次,而且是线性结构,所以不适合。 -
红黑树
如果需要查询的数据是叶子结点上的数据,而且数据量很大的情况,其查询效率不稳定,其次红黑树在插入数据的时候,也是会按照规则进行旋转,其查询的效率不稳定,所以不合适 -
Hash表
无法进行范围查找。 -
B树
B树叶子结点和非叶子结点都存储数据,查询效率不稳定。其次,同B+树比较,相同的磁盘空间,B树非叶子结点存放了数据,那么其能存放的结点数量相比B+树来说会少。 -
B+树
非叶子结点只存放索引,叶子结点存放索引和数据这样就使得B+树的查询效率更加稳定,均为从根结点到叶子结点的路径。横向看,同一高度的叶子结点依次递增,方便范围查找。
页结点默认大小:16KB
示例:以bigint为例,占8字节,空白占6字节,那么一个页结点中一共可以存储1170个索引。
2.介绍一下聚簇(聚集)索引和非聚簇(非聚集)索引
-
Myisam
MYI结尾文件中,叶子结点存放的是磁盘文件的地址,指向存储的数据。
MyIsam的索引就是非聚簇索引,其索引和数据文件是分开的。 -
Innodb
innodb中主键索引就是聚集索引,其叶子结点保存了完整的数据记录。
innodb中普通索引就是非聚簇索引,其叶子结点中保存的是其对应的主键。
回表:普通索引查询方式,需要先查询普通索引树,得到其对应的主键值为3,再到主键索引树搜索一次,这个过程称为回表。
3.介绍一下项目的技术难点
4. 项目是否用过设计模式
创建者模式:单例模式
- 饿汉式 :线程安全
public class HungerManClass {
private String name;
// 1.创建私有的构造器
// 这里private原因;不想外部创建对象
private HungerManClass(String s){
this.name = name;
System.out.println(s);
}
// 2.在类的内部初始化对象,并且需要将其修饰为static
// 这里访问修饰符随意,可以是任意一个,因为本身只是当前类内创建对象
// 这里static的原因是下面的getInstance()方法是static的,静态方法调用静态对象
private static HungerManClass hungerManClass = new HungerManClass("饿汉式");
// 3.向外暴露一个静态的公共方法。getInstance
// 这里static是因为getInstance()作为给外部提供的方法,在构造器不能被外部使用的情况下,想到了用类名.方法名就能调用的静态方法
public static HungerManClass newInstance() {
return hungerManClass;
}
}
调用
public class TestH {
@Test
public void testHunger() {
HungerManClass hungerManClass = HungerManClass.newInstance();
System.out.println(hungerManClass);
}
}
输出
饿汉式
com.SingleModle.hunger.HungerManClass@2e817b38
- 懒汉式:线程不安全
/**
* @author wty
* @date 2023/2/22 14:53
*/
public class LazyManClass {
private String name;
// 1.私有化构造器,这里private后,外部不允许再创建对象
private LazyManClass(String name){
this.name = name;
System.out.println(name);
}
// 2.创建对象,但是不new
private static LazyManClass lazyManClass = null;
// 3.写getInstance方法,用static修饰
public static LazyManClass newInstance() {
// 这里判断一下,如果对象没有创建那么就创建一个对象
if (lazyManClass == null){
lazyManClass = new LazyManClass("懒汉式");
}
// 如果对象已经创建过了,那么直接返回即可
return lazyManClass;
}
}
测试类
public class TestLazyClass {
@Test
public void testLazy(){
LazyManClass lazyManClass = LazyManClass.newInstance();
System.out.println(lazyManClass);
}
}
输出结果
懒汉式
com.SingleModle.lazy.LazyManClass@2e817b38
但是上述方式是线程不安全的,因此我们的做法如下:
package com.SingleModle.lazy;
/**多线程环境下的懒汉式单例模式,(双检锁+volatile实现)
* @author wty
* @date 2023/2/22 15:00
*/
public class LazyManSafe {
private String name;
// 1.私有化构造器,这里private后,外部不允许再创建对象
private LazyManSafe(String name){
this.name = name;
System.out.println(name);
}
// 2.创建对象,但是不new
private static volatile LazyManSafe lazyManSafe = null;
// 3.写getInstance方法,用static修饰
public static LazyManSafe newInstance() {
// 这里判断一下,如果对象没有创建那么就创建一个对象
if (lazyManSafe == null){
synchronized (LazyManClass.class){
if (lazyManSafe == null){
lazyManSafe = new LazyManSafe("懒汉式");
}
}
}
// 如果对象已经创建过了,那么直接返回即可
return lazyManSafe;
}
}
- 工厂模式
见我另一篇文章
工厂模式详解