-
前段有一个分页查询需求,数据量1000万,你会怎么去设计SQL,每次查20条数据,数据量大?
- 直接在查询语句下加limit子句的话,例如limit 10000,20,底层是将10020行数据全都查出来,然后筛选后20条,但是查这10020行数据造成的IO消耗很大
- 可以利用子查询,子查询查id,利用id来筛选数据,同时因为查询id是覆盖索引,查询效率很快,最终得到这20条数据的id,然后外部查询添加where子句中id in这个子查询即可,外部查询查询的整行数据只有这20条,大大提高了效率。
-
说一下索引下推?
- 索引下推就是将原来查询过程中的部分过滤条件放到索引检索阶段,减少回表记录。
- 举个例子,例如有一个联合索引(a,b,c)但是查询条件为a=1 and c > 20,在这时候其实c的索引是失效的,那么没有索引下推的话就是根据索引找到a=1的那些数据,然后再在这些数据中筛选c>20的,而有了索引下推,那么在索引检索阶段就完成c>20的过滤,减少了IO次数,提高了性能。
-
在shell命令中,实现limit 10功能的命令怎么写?
- 利用sed -n ‘1,10p’ filename来实现,输出对应行号
-
有了解设计模式吗?单例模式,多线程下怎么保证单例安全?
- 单例模式在多线程环境下保证单例安全可以通过两种方式来解决
- 直接将单例设置为常量,在类加载的时候直接初始化这个对象
- 使用volatile和synchronized双重验证机制
- volatile主要是为了保证多线程环境下对多个线程的可见性,以及禁用指令重排序,因为new一个对象要经过三个步骤,1. 为对象分配空间 2. 初始化这个对象 3.将对应指针指向这个空间,如果没有volatile修饰的话,那么有可能出现为对象分配空间后,还没初始化的对象就已经将指针指向这块区域了
- synchronized主要是为了保证创建单例时的互斥性,确保不会出现两个线程同时创建单例的情况
- 双重验证是为了防止出现这种情况,外层判断两个线程都判断当前单例为空,a线程获取锁进入创建单例后释放锁,b线程此时因为之前判断了单例为空,进入if逻辑,然后获取了锁,然后也创建了单例,这样就创建了两个单例对象,因此要在里面加一层判断,防止出现创建多例对象的情况。
-
使用Redis时采用的是那种持久化方式?
- 使用的是默认的RDB方式,AOF需要额外开启
- RDB在默认情况下是900秒内发生1次数据修改,触发RDB,这个触发方式可以改,在redis.conf里修改
-
RDB和AOF的优劣势?
- RDB的优势是redis崩溃后恢复快,因为其存储的是对应数据页的真实数据,劣势是实时性不够,数据完整度不够
- AOF则是数据完整度足够,实时性强,但是redis崩溃后恢复较慢,因为其存储的是对应的指令,恢复需要重新执行这些指令
-
如果AOF文件比较占用空间,有什么优化的地方吗?
- redis中提供了两个配置项
- 一个是当AOF文件超过了固定大小触发重写,内部其实是读取redis内部的键值对来完成的,AOF文件会被重写为一个相对较小的AOF文件
- 还有一个是当超过了一个比例会触发重写,这个比例是当前AOF文件大小和上次重写后的AOF文件大小的比例
-
MySQL中悲观锁和乐观锁的特点是什么?
- 悲观锁的最大特点就是互斥,适用于写操作较多的情况,不允许其他事务对锁定的数据进行访问,如当要写数据时上的互斥锁,对其他事务的写操作和读操作都是拒绝的,同一时间段内只会有一个事务来对锁定的数据进行操作
- 乐观锁最大的特点就是不互斥,适用于读操作较多的情况,在一个事务对数据进行操作时,允许其他事务也对这个事务进行操作,例如使用额外的字段,比如版本号,还有时间戳,以版本号为例,但一个事务想要对某个数据进行写操作时,需要先去查询对应数据的版本号,在进行写操作时对比对应数据的版本号还是否是之前查询出来的版本号如果是,则能写,如果不是,则写失败,而对于读操作,乐观锁则没有任何限制。
-
JVM内存区域?
- 堆内存
- 创建的对象
- 字符串常量池
- 元空间
- 类信息,方法信息,属性信息,接口信息
- 静态变量,常量,即时编译后的代码
- 运行时常量池
- 常量池主要包括字面量和符号引用
- 线程私有空间
- 程序计数器
- 虚拟机栈
- 局部变量表:存放局部变量
- 操作数栈:存放方法执行过程
- 动态链接:将符号引用转化为直接引用
- 方法返回地址
- 本地方法栈
- 直接内存
- 堆内存
-
Http1.1相对于Http1.0有什么区别?
- 将短连接改为长链接
- 增加了大量状态码
- 优化缓存控制
- 例如可以设置缓存存活时间,缓存是否对代理服务器可见
- 优化缓存,可以请求和返回部分数据,通过一个206状态码来识别是否是部分数据
- host头的优化
- DNS允许一个ip绑定多个主机,而1.0中不会在请求中标识主机
- 而1.1中将对应主机标识在请求头的host中
-
http2.0相较于1.1的优化?
- 引入了IO多路复用
- 使用帧进行传输,减小网络开销
- 头部压缩,减小网络开销
- 服务器推送,将请求需要的资源一次性返回给客户端,避免多次请求
-
http3.0相较于2.0的改动?
- 底层依赖的协议变为QUIC协议,QUIC协议底层依赖UDP协议,提供了相较于2.0更高的安全性
- 由于依赖UDP协议,建立连接更快
- 3.0为同一个连接建立多个数据流,数据流之间互不影响,避免了头部阻塞
-
红黑树和avl的区别?
- 红黑树和avl都是自平衡的二叉搜索树,两者在插入删除数据时都需要伴随着一些旋转操作来维持数据结构
- 但是红黑树的平衡要求比AVL要低,只要求黑色节点的平衡,而非整个树的平衡
- 红黑树的要求:
- 根节点是黑色
- 每个叶子节点都是黑色的空节点
- 如果节点是红色的,那么其子节点一定是黑色的
- 一个节点到其叶子节点的任意一条路径包含的黑色节点个数相等
-
JDK源码设计模式?
- 策略模式:java集合中的各种对于集合的操作,例如对于List集合的添加操作,可以通过具体的实现类来确定添加操作的算法类型,如ArrayList基于数组实现,LinkedList基于链表实现,还有Comparator中的compare方法通过重写来确定具体的排序规则
- 装饰器模式:BufferedInputStream利用装饰器模式将InputStream装饰为一个代缓存的输入流
- 单例模式:Runtime使用了单例模式,通过getRuntime()获取唯一的Runtime对象
- 工厂模式:在Calendar类中,通过getInstance()方法获取一个实例
- 抽象工厂模式:DocumentBuildFactory的find方法使用了抽象方法模式
- 建造者模式:StringBuilder利用了建造者模式
- 适配器模式:Arrays.asList()将数组适配为list
- 代理模式:Proxy类中用到了代理模式,用于创建代理对象
- 观察者模式:Observer对象利用了观察者模式
- 迭代器模式:java中的集合都提供了迭代器
-
单例模式和工厂模式的区别?
- 单例模式是指全局只有一个这种类型的对象,可以使用立即加载,也可以使用懒加载
- 工厂模式则是将创建对象的权利交给工厂对象,利用工厂来创建对象,降低代码之间的耦合度
20240813面经背诵
最新推荐文章于 2024-08-14 23:12:09 发布