后端开发 每天六道面试题之打卡第一天
MySQL索引失效怎么办
首先排查一下索引失效的原因
1.字符串字段未使用索引前缀
在创建索引的时候应该使用字符串字段的前缀
错误:SELECT * FROM TABLE WHERE NAME LIKE %KEYWORD%
正确:SELECT * FROM TABLE WHERE NAME LIKE KEYWORD%
2.OR操作符使用多列索引
将多列查询条件应该拆分为单列查询 分别使用索引
错误示例:SELECT * FROM table WHERE col1 = 'value1' OR col2 = 'value2'; 正确示例:SELECT * FROM table WHERE col1 = 'value1'; 或 SELECT * FROM table WHERE col2 = 'value2';
3.索引列上使用了函数
我们应该避免在索引列上使用函数 或者去使用函数表达式索引
错误:SELECT * FROM table WHERE YEAR(date_column) = 2021;
正确:SELECT * FROM table WHERE date_column >= '2021-01-01' AND date_column < '2022-01-01';
4.隐式数据类型转换
查询条件的数据类型和索引字段的数据类型不一致
应该调整为一致
错误:SELECT * FROM table WHERE id = '1';
正确:SELECT * FROM table WHERE id = 1;
5.查询条件中的字段顺序与索引字段顺序不一致
应该调整为一致
错误:ELECT * FROM table WHERE name = 'John' AND age = 30
正确:SELECT * FROM table WHERE age = 30 AND name = 'John';
6.使用运算符 NOT操作符号 NULL符号 空值 重复值
改掉
7.未遵循最左原则
这是因为数据库管理系统(DBMS)通过索引的最左侧列来定位数据行。如果查询条件没有从最左侧开始,DBMS就无法直接利用索引来定位记录,从而可能需要执行全表扫描或部分扫描。
我们要调整查询顺序 创建合适的索引 使用覆盖索引
MySQL的主键索引和唯一索引区别
主键索引
一个表只能有一个主键
主键列的数值必须是唯一的 不能为空的
主键索引可以成为其他表的外键 建立与其他表的关系
实际上主键索引是每一行数据的唯一标识 表中的数据是按照主键的顺序进行存储的
主键索引查询很快
聚簇索引
PRIMARY KEY
唯一索引
一张表可以有很多个唯一索引
唯一索引保证索引列的数值是唯一的 但是可以为null
非聚簇索引
UNIQUE
唯一索引可以有一个确定的名称 便于管理和识别
数据库死锁是怎么解决的
数据库的死锁的发生原因
多个事务试图同时访问相同的资源,如数据库表、行、页或锁。但是它们请求资源的顺序不同,导致互相等待。
事务在使用完资源后未及时释放资源,导致其他事务无法获得所需的资源。这可能是由于程序中的错误或异常情况引起的。
如果一个事务在获取资源后执行速度很慢,而其他事务需要等待该事务释放资源,那么可能会导致其他事务超时,从而发生死锁。
操作的数据量过大:在持有锁的同时,又请求获取更多的锁,导致互相等待
一般上会回滚事物释放资源 超时释放资源 熔断系统服务
1.减少锁的数量 RC代替RR避免因为gap锁和next-key锁带来的死锁
2.减少锁的时长 加快事物的执行速度 降低执行时间
3.固定访问顺序 事物应该以相同的顺序拿到锁
4.减少事物操作的数据量 减少事物的持有时间
Jstack命令导出线程的dump日志
jstack是java虚拟机自带的一种堆栈跟踪工具。
线程出现停顿的时候通过jstack来查看各个线程的调用堆栈,就可以知道没有响应的线程在后台做什么事,或者等待什么资源。
使用top -Hp 29938 查看进程里面占用资源最多的线程。
使用jstack 29938 | grep -20 79e1命令查询该线程阻塞的地方。(其中的20表示20行)
Java中重载和覆盖
重载是在一个类中多态性的一种表现,是指在一个类中定义了多个同名的方法,它们或有不同的参数个数或有不同的参数类型。
覆盖是指派生类函数覆盖基类函数。覆盖一个方法并对其重写,以达到不同的作用。
覆盖时返回值类型 参数类型 函数名 抛出的异常都要和父类一致
如果是private关键字 派生类都是定义了一个同名的函数而已
1.覆盖是子类和父类之间的关系,是垂直关系;重载是同一个类中方法之间的关系,是水平关系。
2.覆盖只能由一个方法或只能由一对方法产生关系;重载是多个方法之间的关系。
3.覆盖要求参数列表相同;重载要求参数列表不同。
4.覆盖关系中,调用方法体是根据对象的类型(对象对应存储空间类型)来决定;而重载中关系是根据调用时的实参表和形参表来选择方法体的。
Java OOM
代码层面优化
内存溢出
一次性申请的对象太多了 要尝试分页查询
释放进程 扩大数据库连接池
JVM参数调整
调整服务的堆内存 通过-Xmx参数增加JVM最大堆内存的大小
选择合适的垃圾回收器(如G1、CMS)并调整其参数,以优化内存分配和回收。
内存分析
使用内存分析工具:使用VisualVM、MAT、JProfiler等工具来分析内存使用情况,找出内存泄漏和内存占用过高的原因。 监控内存使用:在应用程序中添加日志和监控,实时监控内存使用情况。
使用内存池
使用内存池管理:对于频繁创建和销毁的对象,可以使用内存池来减少内存分配和回收的开销。
优化数据访问
减少数据库访问:优化数据库查询,减少数据检索次数。 使用批量操作:在数据库操作中使用批量更新或插入,减少单个操作的内存消耗。
Java内存模型
每个线程
每个线程都有自己独立的存储空间
申请变量是在主内存里面
每个线程都把主内存里面的数据拿到自己的存储空间里面进行处理
堆内存
在java中,所有实例域、静态域和数组元素存储在堆内存中,堆内存在线程之间共享。局部变量(Local variables),方法定义参数(java语言规范称之为formal method parameters)和异常处理器参数(exception handler parameters)不会在线程之间共享,它们不会有内存可见性问题,也不受内存模型的影响。
虚拟机
java虚拟机的结构主要分为四大块:类加载子系统、垃圾回收器、运行时数据区、字节码加载子系统。
其他
-
线程私有
-
程序计数器
-
虚拟机栈
-
本地方法栈
-
-
线程共享
-
堆
-
元空间(以前叫方法区)
-