秋招突击——8/16——字节广告业务——面经整理——二面挂

news2024/11/14 21:04:31

文章目录

    • 引言
    • 一面面试内容
      • 基础知识
        • 一、Redis为什么进行AOF重写?
        • 二、AQS和Conditon的使用
        • 三、乐观锁和分布式锁有什么差异?频繁使用乐观锁行不行?
        • 四、Java的即时编译技术
        • 五、Java中的JVM调优是如何做的?
        • 六、Java中创建对象的流程?
        • 七、Java中的反射编程,为什么慢?
        • 八、AOP的两种实现方式,有什么区别 ?
      • 手撕
        • 1、写一个SQL,实现A给B转账50
        • 2、使用Java实现一个同步机制中的wait方法
      • 结果
    • 二面(挂)
      • 基础知识
        • 1、HashMap介绍一下?是线程安全的吗?
        • 2、有其他线程安全的吗?怎么实现的?
        • 3、说一说CAS和Synchronized两种同步机制的差异
        • 4、说一下锁的自动升级?
        • 5、数据库中有哪几种类型的索引?
        • 6、数据库是如何保证持久化?数据一定不会丢失吗?在主从复制的情况下,我一点数据都不想让他让丢失,怎么办?
        • 7、数据在可重复读隔离级别下,解决了什么问题?
        • 8、怎么解决幻读问题?是否完全解决?如果不行,举一个例子?(当初看这里的时候跳过了,以为不会有一家公司会问的那么细致吧!结果,字节问到了,给我整懵了!)
        • 9、说一说B+树的具体结构?
        • 10、将所有最低分都超过80分的学生的id列出来,写一个SQL
        • 11、分析下面几个where子句是否用到了索引?
      • 算法题
    • 总结

引言

  • 今天面试字节,发现很多细节的问题并不了解,很多东西都是知道,但是具体细节就不知道了,然后深感我的知识储备,还是比较草率或者说疏忽的!
  • 下面每一章都需要好好补充,好好弄懂!都是难点!

一面面试内容

基础知识

一、Redis为什么进行AOF重写?

AOF写满了怎么办?

  • 触发AOF重写机制

AOF是什么

  • 是redis的一种持久化机制,将redis的写操作,以日志的形式记录在文件中

为什么进行AOF重写

  • 减少文件大小
    • AOF不断追加写操作日志,会包括重复或者无效命令重写以优化其性能和存储效率
  • 提高恢复速度
    • 重写之后,会去除很多重复或者无效的命令,恢复起来执行的命令就会减少,速度更快
  • 优化性能
    • AOF文件过大,会增加redis的内存消耗和CPU负载,重写的时候子进程要干的活就多了,重写之后,能够减轻负担,优化性能

重写机制

  • 主进程fork一个子进程
    • 子进程扫描Redis数据库,将每一个键值对转换为相应的写入命令,写入到一个临时文件中
      • 注意!!!,这里是直接扫描数据库,将每一个键值对转为命令
    • 主进程继续接收和处理客户端的请求,将新的写操作追加到一个重写缓冲区中。
    • 子进程完成之后,会将缓冲区的写操作追加到临时文件中
      • 通知主进程用临时文件替换旧的AOF文件

AOF重写的参数配置

  • 开启重写功能,在redis.conf文件中,设置appendonly yes参数
  • 设置重写触发条件,需要同时满足内存使用率和文件大小在进行重写
    • 内存使用率:auto-aof-rewrite-percentage 100
    • 内存的大小:auto-aof-rewrite-min-size 64mb
  • 重启redis

疏忽点

  • AOF重写并不是重写指令,是直接将某个时刻的数据库的键值对转换成指令,然后追加写入
二、AQS和Conditon的使用
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.*;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;


public class Main {
    static ReentrantLock lock = new ReentrantLock();
    static Condition condition = lock.newCondition();
    static int curNum = 0;

    static class ThreadTest implements Runnable {
        int count = 0;

        ThreadTest(int countType) {
            count = countType;
        }

        void printNum() {
            while(true) {
                lock.lock();

                while (curNum % 3 != count) {
                    try {
                        condition.await();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                if(curNum > 100) break;
                System.out.println("Thread No:" + count + " print :" + curNum++);
                condition.signalAll();
                
                lock.unlock();
            }
        }

        @Override
        public void run() {
            printNum();
        }
    }

    public static void main(String[] args) {
        Thread thread1 = new Thread(new ThreadTest(1));
        Thread thread2 = new Thread(new ThreadTest(2));
        Thread thread3 = new Thread(new ThreadTest(0));
        thread1.start();
        thread2.start();
        thread3.start();
    }
}

正常情况下,condition是可以有多个信号量的,比如说读者和写者,就是使用了多个condition的方法

三、乐观锁和分布式锁有什么差异?频繁使用乐观锁行不行?

1、乐观锁特点

  • 高并发性能
    • 并不阻塞其他事物的读取操作,只在提交的时候检查数据是否被修改适合读多写少的情况
  • 无锁操作
    • 乐观锁并不需要显示的获取锁和释放锁,减少了锁竞争和上下文切换的开销
  • 无死锁操作
    • 由于乐观所不会阻塞其他事物的访问,所以不会出现死锁的情况

2、乐观锁:如果数据被修改了会怎么样?

  • 当乐观锁提交更新时检测到数据已经被其他事物修改
    • 认为当前数据的更新操作处于过时的数据版本,会拒绝提交更新操作
      • 触发回滚操作,将事物恢复到修改前的状态,保证了数据的一致性。
      • 检测到异常之后,应用层会捕获对应异常的

3、为什么乐观锁仅仅适合读多写少的高并发情况?

  • 在读多写少的情况下,数据并发修改的概率相对较低
  • 乐观锁在并发环境下,冲突很少发生,读数据时并不需要加锁,提高读操作的并发性
  • 在高并发写频繁的环境下,乐观锁会导致大量的冲突和事物重试,降低系统的性能和吞吐量

4、批量事物处理

  • 使用批量修改,事物和事物之间发生冲突的概率就越大,整体回滚的可能性越高,所以使用批量处理的话,还是推荐使用分布式锁

5、与分布式锁的比较

  • 性能

    • 乐观锁
      • 适用于并发冲突较少的情况,性能高,大部分时间都不需要等待锁的释放
    • 分布式锁
      • 性能相对较低,增加了网络通信的开销
  • 复杂性

    • 乐观锁
      • 实现相对简单,只需要一个版本号或者时间戳字段即可,但是在冲突上处理比较复杂,需要应用层来处理回滚和重试
    • 分布式锁
      • 实现相对复杂,但是能够确保锁的可靠性和已执行,同时,还需要处理锁的超时、续期和释放等问题
  • 安全性

    • 乐观锁
      • 在并发冲突较多的场景下,乐观所可能会导致数据一致性的风险(为什么)
    • 分布式锁
      • 能够在一定程度上减少数据一致性问题,但是中心街店出现故障的话,会导致锁无法正常工作
四、Java的即时编译技术

1、简介

  • JVM虚拟机性能优化的手段,将频繁使用的热点代码翻译成高效的本地机器码,直接由硬件执行!
  • 传统编译过程
    • 源代码首先编译成JVM可执行的字节码,通过JVM逐条解释执行,翻译成机器码

2、即时编译和正常编译的区别

  • 正常编译
    • 发生在程序运行时
      • 监控程序的执行,识别出频繁执行的代码(热点代码),将这些代码动态编译成机器码。
      • 程序运行过程中,不断优化代码,适应当前的运行环境
    • 启动速度慢
      • 启动时需要花时间来编译热点代码,启动较慢
  • 即时编译
    • 发生在程序运行前
      • 将源代码一次性编译成与特定平台相关的机器码,生成可执行文件,无法修改
    • 启动速度快
      • 无需等待编译过程,直接运行

3、工作原理

  • 1、解释执行

    • 使用JVM的解释器,以字节码的形式进行解释执行
    • 收集程序运行时的统计信息
  • 2、特点探测

    • 记录频繁执行的代码是特点代码
    • 基于计数器的热点探测机制
  • 3、即时编译

    • 对热点代码进行即时编译,利用优化技术将热点代码优化,转为本地机器码
  • 4、本地代码执行

    • 优化之后的本地代码是在本地缓存,直接在CPU上执行,远快于解释执行

4、优化技术

  • 方法内联
    • 频繁调用的小型方法体,直接插入到调用点,减少方法调用的开销
  • 循环优化
    • 改进循环执行的效率,通过循环展开减少循环次数
  • 死代码消除
    • 删除不会运行到的代码
  • 逃逸分析
    • 分析对象的作用域,决定是否可以在栈上分析,不是在堆上,减少内存分配和回收开销
五、Java中的JVM调优是如何做的?

1、堆内存调优

  • 堆内存大小,避免频繁垃圾回收
  • 新生代和老年代的比例

2、垃圾回收GC调优

  • GC算法

3、线程调优

  • 线程池大小
  • 线程栈大小,控制线程的内存占用

4、JIT编译器调优

  • 选择合适的JIT编译器
  • 编译阈值等

5、内存分配调优

六、Java中创建对象的流程?

1、类加载

  • 判定对应类是否已经加载的,如果没加载,需要执行对应的类加载程序
    • 加载
    • 连接
      • 验证
      • 准备
      • 解析
    • 初始化
  • 如果类已经加载过
    • JVM方法区中已经存在该类的Class对象,不需要执行对应的加载过程。
      2、分配内存
  • 基于两种方法,在堆内存上分配对象需要的内存
    • 指针碰撞:内存规整,向高低之移动对应空间大小的距离
    • 空闲列表:内存散乱,从列表中找到可用空间分配给对象

3、初始化对象

  • 将对象的实例变量初始化为其类型的默认值

4、构造对象

  • 执行构造函数,初始化实例变量

5、引用对象

  • 新创建的对象通过引用变量被访问和使用
    • 对象存储在堆空间中
    • 引用存储在栈的局部变量中
七、Java中的反射编程,为什么慢?

反射慢的原因

  • 1、动态解析
    • 访问对象的方法需要查找类的元数据信息基于这些信息进行方法调用和字段的访问
    • 常规方法
      • 编译时已经确定,直接调用
  • 2、安全性检查
    • 使用反射,JVM会进行额外的安全性检查,确保当前线程有权访问目标类和字段
    • 安全性检查会增加开销
  • 3、方法调用开销
    • 不会直接跳转到方法的实现代码地址
    • 需要通过反射API间接调用
八、AOP的两种实现方式,有什么区别 ?
  • AOP是通过动态代理实现的,主要是基于两种动态代理机制,JDK动态代理和CGLIB动态代理

JDK动态代理

  • 实现方式
    • Java原生的动态代理机制,目标类必须实现接口,代理类通过接口代理被代理对象的方法调用
  • 适用场景
    • 目标对象必须实现一个或者多个接口
    • 代理类将实现与目标相同的接口,
  • 优点
    • JDK动态代理原生,通过反射机制生成的代理类会更快
  • 缺点
    • 目标类必须实现接口

CGLIB动态代理

  • 实现方式

    • 第三方库,直接操作字节码,生成目标类的子类,重写类的方法完成代理
  • 适用场景

    • 目标类没有实现接口时,使用CGLIB代理
  • 优点

    • 不需要实现接口,更灵活
    • 执行代理方法的效率更高,避免了反射的额外开销
  • 缺点

    • 操作字节码,生成速度慢

手撕

1、写一个SQL,实现A给B转账50

注意点

  • 原子操作
    • A账户扣款操作和B账户的收款操作应该是院子操作,不可中断
  • 是否可转账
    • A能够转账应该是A的钱是刚好够转账的,所以需要检查一下

下述代码只是应用于面试,实际开发中不会这么写

标准的SQL并不支持单个SQL查询或者命令中直接嵌套IF语句来控制事物的提交或者回滚

--开始事物--
START TRANSACTION;

UPDATE ACCOUNTS
SET BALANCE = BALANCE - 100
WHERE USER_ID = 1;

IF (SELECT BALANCE FROM ACCOUNTS WHERE USER_ID = 1) < 0 THEN
	ROLLBACK;
ELSE
	UPDATE ACCOUNTS
	SET BALANCE = BALANCE + 100
	WHERE USER_ID = 2;
	
	COMMIT;
END IF;
2、使用Java实现一个同步机制中的wait方法
  • wait方法前提
    • 何时等待锁
      • 通常是在某一个条件不满足时,等待一个资源变得可用,或者等待某一个操作的手结果
      • 通过检查一个条件变量来实现
    • 在哪里等待
      • 必须在同步快或者同步方法的内部进行
      • wait方法会释放当前线程持有的锁,导致该线程进入同步状态
    • 如何唤醒
      • 唤醒和等待通常在同一个锁上实现

这里是让实现wait方法,所以并不是调用这方法,需要对AQS有很深的理解

  • 这里将AQS内容再进一步深化,之前仅仅是浅浅地了解一下,并没有深究,现在还需要深究一下,两次学习连接如

    • 第一次粗浅地学习
    • 第二次深入学习
  • 通过第二次学习,可以知道,专门创建一个等待队列,用来保存阻塞节点,然后锁的竞争机制,创建一个同步队列,保存竞争失败的线程。

  • 升级为非公平锁

    • 在加入队列之前,先竞争锁的使用

下述是参考的百度文心一言生成的,实际上我就写了一个大概,算是过了

class Node {  
    // 线程引用  
    Thread thread;  
    // 等待状态  
    int waitStatus;  
    // 前驱节点  
    Node prev;  
    // 后继节点  
    Node next;  
  
    // 构造函数等...  
}  
  
class Lock {  
    // 同步队列的头节点  
    private volatile Node head;  
    // 同步队列的尾节点  
    private volatile Node tail;  
    // 锁的状态,0表示未锁定,1表示锁定  
    private volatile int state = 0;  
  
    // 尝试获取锁(非公平)  
    public void lock() {  
        // 尝试直接获取锁  
        if (compareAndSetState(0, 1)) {  
            // 成功获取锁  
            setExclusiveOwnerThread(Thread.currentThread());  
        } else {  
            // 竞争失败,加入同步队列  
            enqueue(addWaiter(Node.EXCLUSIVE));  
            acquireQueued(addWaiter(Node.EXCLUSIVE), true);  
        }  
    }  
  
    // 尝试释放锁  
    public void unlock() {  
        // 释放锁逻辑...  
        // 唤醒同步队列中的一个等待线程  
    }  
  
    // 等待操作(模拟)  
    public void await() {  
        // 简化处理,直接加入同步队列并阻塞当前线程  
        Node node = addWaiter(Node.SHARED);  
        // 阻塞当前线程,直到被唤醒  
        parkAndCheckInterrupt();  
    }  
  
 
    // 其他辅助方法...  
}  

结果

  • 很意外,面试面的我心惊肉跳,但是过了,可能最后那个AQS写对了吧!不过后续的二面和三面不抱太大希望了,因为我觉得字节太难了,真的太难了!

二面(挂)

基础知识

1、HashMap介绍一下?是线程安全的吗?

简介

  • 基于哈希表实现,访问速度快
    • 插入和删除的时间复杂度都是O(1)
  • 元素之间没有顺序
  • 哈希冲突的解决方式
    • Java7采用数组 + 链表的方式实现
    • Java8采用 数组 + 链表 + 红黑树 的方式实现
      • 链表的长度大于9,自动转成红黑树
  • 是否线程安全
    • 非线程安全,推荐使用concurrentHashMap
  • 数组扩容方式
    • 当前存量 和 容量 * 负载因子的比较
    • 扩容两倍的方式实现
    • 通过按位 与 的方式实现取余运算
2、有其他线程安全的吗?怎么实现的?

为什么使用ConcurrentHashMap

  • 本身不是线程安全的
  • Hashtable线程安全,但是运行效率低,底层使用synchronized加锁
    • 锁的颗粒度太高
  • ConcurrentHashMap使用分段锁,提高并发率的同时,保证线程安全
    • 将数据分段存储,每一段配一把锁,一个线程占用锁访问其中一段的时候,不影响其他线程继续访问
  • 读数据不加锁,写数据才会加锁

JDK1.7分段锁的实现

  • Segment数组将hash表分段
    • ConcurrentHashMap对象中,保存了Segment数组,将整个Hash表划分为多个分段
      • 每一个分段类似一个HashTable
      • 默认支持16个线程并发操作
  • 访问流程
    • 先根据hash算法定位到对应的Segment,对Segment加锁就行

在这里插入图片描述

JDK1.8实现

  • 实现原理
    • 数组+ 链表 + 红黑树
    • 通过CAS和Synchronized实现加锁
  • 具体加锁过程
    • 对应hash位置没有元素
      • 使用CAS插入元素
    • 对应位置已经有链表了
      • 使用Synchronized锁住槽点,防止其他线程操作

乐观锁和CAS有什么不同?

  • CAS是乐观锁的一种实现
  • 乐观锁
    • 定义
      • 假设多个线程之间发生冲突的可能性很小
        • 读取数据的时候不加锁
        • 只有在更新数据的时候才会检查是否有其他的线程已经修改了该数据。
    • 实现方式
      • 通过版本号和时间戳来实现
      • 更新数据的时候,会检查版本号或者时间戳是否和最初读取的一致
        • 如果一致说明这个阶段没有人修改数据,直接修改即可
        • 如果不一致说明这个阶段有人修改数据,放弃或者重试
  • CAS锁
    • 定义
      • 比较和替换,是一种无锁编程技术,用于实现多线程间的原子操作
    • 特点
      • 只能保证单个共享变量的原子性
3、说一说CAS和Synchronized两种同步机制的差异

锁的性质

  • CAS
    • 乐观锁
      • 假设在多线程数据处理过程中,不会发生冲突。所以读取数据的时候,不会加锁。修改数据的时候,才会去检查是否有其他线程修改了数据。
    • 非阻塞
      • CAS操作在尝试更新数据时,如果数据未被修改,直接更新;如果数据被修改了,操作失败,不会阻塞当前线程,允许器继续执行或者尝试。
  • Synchronized
    • 悲观锁
      • 假设在多线程的环境下,一定会发生冲突,所以当问数据的时候一定会加锁,知道访问资源结束。
    • 阻塞
      • 访问失败,会陷入阻塞,只当前锁被释放,其他线程唤醒。
4、说一下锁的自动升级?

无锁状态

  • 对象在创建之初,对象头的Mark Word被没有任何锁的标志位设置,自由访问

偏向锁

  • 第一个线程获取就升级为偏向锁
    • 当第一个线程尝试获取某个对象的synchronized锁时,会将对象头标记设置为偏向锁,并在对象头标记填上获取当前锁的线程ID。
  • 作用
    • 减少在单线程环境下获取锁的开销,一个线程肯定会多次获取一个锁的

轻量级锁

  • 第二个线程尝试获取偏向锁
    • 当有第二个线程尝试获取偏向锁时,偏向锁就会撤销,变为轻量级锁状态
  • 具体实现
    • 使用线程的本地的ThreadLocal变量存储锁记录,包含了锁记录的MarkWord拷贝
  • 锁竞争
    • 如果获取锁失败,会通过自旋来获取锁,超过阈值,轻量级锁膨胀为重量级锁

重量级锁

  • 自旋失败就是重量级锁
    • 如果自旋尝试失败就是重量级锁,重量级锁是通过操作系统的互斥锁实现的
    • 获取锁失败,阻塞唤醒都需要操作系统实现
5、数据库中有哪几种类型的索引?

B+树索引

  • 用途
    • 保持数据排序,并允许对索引进行高效的顺序访问和随机访问

哈希索引

  • 用途
    • 基于哈希表实现,适用于等值查询

全文索引

  • 用途
    • 用于搜索存储在数据库中的文本内容的关键字
    • 支持短语搜索、模糊搜索

复合索引

  • 用途
    • 在表的多个列上创建的索引,允许基于这些列的组合的索引查询
6、数据库是如何保证持久化?数据一定不会丢失吗?在主从复制的情况下,我一点数据都不想让他让丢失,怎么办?

在这里插入图片描述
主从复制的过程(具体见上图)

  • 主库的角度出发
    • 主库发生数据变更,并将结果写入binlog日志
    • 主库会随时开启dump线程检测到binlog日志的更改,会将修改的binlong日志发送给从库
  • 从库的接受binlog日志
    • 从库接受binlog日志,并将日志文件写入relaylog日志中,并发送复制成功的响应
    • 从库创建线程回放relaylog日志

三种主从复制模式,这里我会选择同步复制模式

  • 1、同步复制==》从库成功了,事物才成功

    • 提交事务的线程,需要的等待所有复制的从库确认复制成功的响应,才返回给客户端结果
    • 特点
      • 性能差
      • 安全性高,对于数据一点都不允许丢失的,可以使用如下方式
  • 2、半同步复制==》一部分成功了就行了

    • 提交事务的线程,只要等到一部分的从库复制成功的响应,就返回给客户端结果
    • 特点
      • 兼顾了异步的高效性,以及同步的安全性,但是是针对的多个从节点而言的
  • 3、异步复制==》不管从库,主库搞定了就行

    • 提交事务的县城,不会等待binlog同步到各个从库,立刻返回给客户端的
    • 特点
      • 安全性最差,宕机就完蛋
7、数据在可重复读隔离级别下,解决了什么问题?

完全解决了脏读、不可重复读、部分解决了幻读

脏读

  • 定义
    • 一个事务读取了另外一个事务还没有提交的数据(有可能发生回滚,数据就不存在了)

不可重复读

  • 定义
    • 同一个事务内部,多次读取同一个数据集合的时候,由于其他并发事务的提交,导致后续读取到的数据和前面的不一致。
    • 重在于修改,一开始读取性别是男的,后面就变成女的了

幻读==》眼花了吗?我记得之前没有呀?

  • 定义
    • 在一个事务内,同一查询多次执行,由于其他事务的插入操作,后续的结果集中出现了之前查询不到的记录
    • 一开始查一个班级里是42个人,结果变成了41个人,出现了幻觉!
8、怎么解决幻读问题?是否完全解决?如果不行,举一个例子?(当初看这里的时候跳过了,以为不会有一家公司会问的那么细致吧!结果,字节问到了,给我整懵了!)

可重复度隔离级别解决幻读问题

  • 快照读
    • 通过MVCC解决幻读,事务执行过程中看到的数据和事务开始之前是一致的,
      • 即使其他事务插入一条新的数据,也是一样的。
  • 当前读
    • 通过行级锁解决,通过**nextkey锁(记录锁 + 间隙锁)**解决
    • select for update:会在查询范围内插入间隙锁,其他事务无法往其中插入数据

未完全解决的幻读问题

  • 快照读的问题
    • 当前事务A更新了一条事务B插入的记录
    • 事务A前后两次查询的记录条目就不一样了
    • 发生了幻读
A:select * from table_a where id = 7;  //数据不存在,还没有结果
B:insert into table_a values( 7,"ren");  //事务B插入新数据
A:update table_a set name = "a" where id = 7;  // 更新记录7
A:select * from table_a where id = 7;  再查就能看见了
  • 当前读的问题
    • 事务开启前,使用快照读,没有使用当前读,有一个A
    • 另外一个事务执行之后,在执行当前读,for update 就会出现问题
9、说一说B+树的具体结构?

基本构成

  • 非叶子节点

    • 仅仅包含索引
    • 关键字在节点中按升序排列
  • 叶子节点

    • 所有的数据记录或指向数据记录的指针
    • 叶子节点之间通过指针相连,这些指针按照关键字的顺序排列

特点

  • 关键字冗余
    • 关键字可以在内部节点和叶子节点中重复
      • 内部节点中的关键字是分割子树的指标
      • 叶子节点中的关键字则指向数据记录
  • 非叶子节点仅仅包含索引
10、将所有最低分都超过80分的学生的id列出来,写一个SQL

注意

  • 在GROUP BY操作中,你不能直接选择非聚合列(即没有包含在聚合函数中的列),除非这些列也被包括在GROUP BY子句中。
SELECT stu_id  
FROM course_table  
GROUP BY stu_id  
HAVING MIN(score) >= 80;

进一步就是

SELECT *
FROM course_table 
WHERE stu_id in {
	SELECT stu_id  
	FROM course_table  
	GROUP BY stu_id  
	HAVING MIN(score) >= 80;
}
11、分析下面几个where子句是否用到了索引?
  • 有一个联合索引(a,b,c)
  • 然后判断下面三个语句的索引使用情况
    • where a=‘a’ and b=‘b’ and c=‘c’;
    • where a=‘a’ and b>‘b’ and c<‘c’;
    • where a=‘a’ and c=‘c’;

where a=‘a’ and b=‘b’ and c=‘c’;

  • 索引使用情况:这个查询会完全使用到联合索引(a,b,c)。

where a=‘a’ and b>‘b’ and c<‘c’;

  • 索引使用情况:这个查询会使用索引a和b。

where a=‘a’ and c=‘c’;

  • 索引使用情况:这个查询会使用索引a。

索引最左匹配的使用

  • 复合索引如果匹配到的范围查找,就不走索引了,后续会走索引下推
  • 复合索引的最左匹配原则不是说顺序,是说具体的值where a and b and c 对于索引(a,b,c)是满足最左匹配原则的,但是如果是where c and b就不满足了,因为少了一个。

索引相关学习链接

算法题

题目链接

总结

  • 最后算法题来了一道hard的题目,没写出来,就挂了!
  • 再接再厉,好好准备一下,后面还有很多其他的公司,在准备一下!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2071193.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

STM32——BKP备份寄存器RTC实时时钟

首先是理论知识Unix时间戳&#xff1a; 时间戳只显示秒&#xff0c;没有进位&#xff0c;永不进位的秒计数器&#xff0c;60秒就是60秒&#xff0c;100秒就是100秒&#xff0c;它可以和年月日/时分秒进行转换 优点&#xff1a;1、简化硬件电路&#xff08;只需要考虑秒的容量…

C语言 猜数字游戏

目录 1. 随机数⽣成 1.1 rand 1.2 srand 1.3 time 1.4 设置随机数的范围 2. 猜数字游戏实现 游戏要求&#xff1a; 1. 电脑⾃动⽣成1~100的随机数 2. 玩家猜数字&#xff0c;猜数字的过程中&#xff0c;根据猜测数据的⼤⼩给出⼤了或⼩了的反馈&#xff0c;直到猜对&a…

运行微信小程序报错:Bad attr data-event-opts with message

问题 使用uniapp 编译&#xff0c;运行微信小程序环境时&#xff0c;报错 Bad attr data-event-opts with message。&#xff08;这个错误报错原因很多&#xff0c;这里只解决一个&#xff09; 原因 原因是&#xff1a;代码中有&#xff1a; :key"swiperList i"…

猫头虎分享:Python库 Pip 的简介、安装、用法详解入门教程

猫头虎分享&#xff1a;Python库 Pip 的简介、安装、用法详解入门教程 &#x1f3af; 大家好&#xff01;今天猫头虎带您一起探索Python世界中的一个基础工具——Pip。作为一名Python开发者&#xff0c;掌握Pip的使用不仅能帮助你更有效地管理项目中的依赖&#xff0c;还能让你…

【Java】Spring Boot使用 Email 传邮件 (上手图解)

Java系列文章目录 补充内容 Windows通过SSH连接Linux 第一章 Linux基本命令的学习与Linux历史 文章目录 Java系列文章目录一、前言二、学习内容&#xff1a;三、问题描述四、解决方案&#xff1a;4.1 认识依赖4.2 发送邮件步骤4.2.1 先获取授权码4.2.1 邮件配置4.2.2 主体内容…

使用 jar-analyzer 和dbeaver 分析java

https://github.com/jar-analyzer/jar-analyzer 可以进行jar分析&#xff0c;包括method调用 分析完可以通过界面进行一些分析&#xff0c;如果复杂还可以用DbWeaver 打开数据库进行分析

Java SpringBoot+Vue实战教程:如何搭建高中素质评价档案系统?

✍✍计算机编程指导师 ⭐⭐个人介绍&#xff1a;自己非常喜欢研究技术问题&#xff01;专业做Java、Python、微信小程序、安卓、大数据、爬虫、Golang、大屏等实战项目。 ⛽⛽实战项目&#xff1a;有源码或者技术上的问题欢迎在评论区一起讨论交流&#xff01; ⚡⚡ Java实战 |…

【通俗易懂】限流、降级、熔断有什么区别?

目录 一、限流 1.1 简介 1.2 限流算法 二、降级 2.1 简介 2.2 降级的方式 延迟服务 在粒度范围内关闭服务&#xff08;片段降级或服务功能降级&#xff09; 页面异步请求降级 写降级 读降级 2.3 降级的介入方式 自动开关降级 服务超时 失败次数 发生故障 限流…

Markdown 美化 Github 个人主页

注&#xff1a;本文参考这篇博客 http://t.csdnimg.cn/KXhSw 目录 1 效果展示2 创建仓库3 编写 Markdown3.1 动态波浪图3.2 打字机动图3.3 技术栈图标3.4 项目贡献统计3.5 连续贡献统计3.6 贡献统计图3.7 代码时长统计3.8 仓库代码占比 1 效果展示 先来看看效果&#xff1a; 动…

java整合DL645-2007与Dl645-1997

注意事项: 前导字节-一般在传输帧信息前,都要有0~4个FE不等,所以这里要注意,对于主站来说,直接发送4个FE作为前导字节即可。而从站回复,就不一定了,根据厂家不同而不同,有些没有FE的,也有4个FE的,所以对于接受程序,一定要慎重传输次序-所有的数据项都是先传低字节,…

【生日视频制作】云层直升机飞机机身AE模板修改文字软件生成器教程特效素材【AE模板】

云层直升飞机生日视频制作教程AE模板修改文字特效软件生成器玩法素 怎么如何做的【生日视频制作】云层直升机飞机机身AE模板修改文字软件生成器教程特效素材【AE模板】 生日视频制作步骤&#xff1a; 安装AE软件下载AE模板把AE模板导入AE软件修改图片或文字渲染出视频

web后端(javaEE)开发——servlet

目录 一、web后端开发概述 二、web后端开发环境搭建 1.安装服务器软件 2.安装JDK 三、创建web后端项目 1.创建项目 2.修改设置 3.*在IDEA中集成Tomcat* 四、Servlet创建和应用 1.概述 2.Servlet程序创建与配置 3.分析Servlet程序结构 一、web后端开发概述 web开发&a…

Netty代码阅读

阅读Netty官方文档的时候&#xff0c;提到了Netty主要有三大核心&#xff0c;分别是buffer、channel、Event Model&#xff0c;接下来我们就从阅读Netty代码来理解这三大核心。 示例程序 先给出示例程序&#xff0c;方便自己也方便读者进行debug调试。 Server端代码 # Serv…

mysql启动报错“本地计算机上的MySQL服务启动后停止。某些服务在未由其他服务或程序使用时将自动停止”

我删除&#xff08;手动删除&#xff09;完 binlog 文件后&#xff0c;重新启动mysql服务报错如下&#xff1a; 查看错误日志可以看到 某个 binlog 文件找不到 打开 binlog.index 可以看到里面引用的正是这个文件 解决方法&#xff1a; 要么手动修改 binlog.index 文件&#…

【C++ Primer Plus习题】4.6

问题: 解答: #include <iostream> using namespace std;typedef struct _CandyBar {string brand;float weight;int calorie; }CandyBar;int main() {CandyBar snack[3] { {"德芙",2.1,20},{"箭牌",2.2,16},{"阿尔卑斯",2.3,18}};for (i…

【GNSS接收机】开源导航接收机

Pocket SDR Pocket SDR是一款基于软件无线电&#xff08;SDR&#xff09;技术的开源GNSS&#xff08;全球导航卫星系统&#xff09;接收机。它由名为“Pocket SDR FE”的RF前端设备、设备的一些实用程序以及用Python、C和C编写的GNSS-SDR AP&#xff08;应用程序&#xff09;组…

linux死锁问题和cpu使用率过高问题排查

1、问题共同点 死锁问题和cpu使用率过高都是需要我们找出对应的问题线程。 死锁问题需要我们找出哪两个线程出现了死锁情况。 cpu使用率过高需要我们找出哪个或哪些线程占用了大量的cpu。 2、命令排查 2.1、查看机器上的Java进程 jcmd或 jps2.2、查看对应Java进程的线程级别…

全文发布|SmartX 金融行业跑批类业务场景探索与实践合集

经过多年在⾦融⾏业的积累和发展&#xff0c;SmartX 已经赢得了 300 多家⾦融⽤户的信任。覆盖了银⾏、保险、证券、基⾦、期货和信托等主要⾦融细分领域。在这个过程中&#xff0c;我们从最初的单⼀超融合⼚商&#xff08;⼩规模起步/快速交付/按需灵活扩容/降低总拥有成本&am…

【Hot100】LeetCode—236. 二叉树的最近公共祖先

目录 1- 思路递归 自底向上 2- 实现⭐236. 二叉树的最近公共祖先——题解思路 3- ACM 实现 题目连接&#xff1a;236. 二叉树的最近公共祖先 1- 思路 递归 自底向上 ① 自底向上的逻辑的话 需要采用后续遍历的方式&#xff0c;最后处理中间结点 ② 递归 2.1 参数和返回值…

Verilog刷题笔记60

题目&#xff1a; Exams/2013 q2bfsm Consider a finite state machine that is used to control some type of motor. The FSM has inputs x and y, which come from the motor, and produces outputs f and g, which control the motor. There is also a clock input called …