一、前端面试题

1)vue的生命周期(八个钩子函数)
  1. beforeCreate:创建vue示例之前;

  2. created:创建实例完成,实现数据的异步请求;

  3. beforeMount:渲染DOM之前;

  4. mounted:渲染DOM完成,加载组件第一次渲染;

  5. beforeUpdate:重新渲染DOM之前,数据更新的操作;

  6. updated:重新渲染DOM完成;

  7. beforeDestroy:销毁之前;

  8. destroyed:销毁完成;

2)watch和computed区别
  1. computed:

    • data中没有直接声明要计算的变量,也可以直接在computed中写入;

    • 支持缓存,只有依赖数据发生改变,才会重新进行计算;

    • 不支持异步,当computed内有异步操作时无效,无法监听数据的变化;

    • computed是计算属性,也就是依赖某个值或者props通过计算得来的数据;

    • computed的值是在getter执行之后进行缓存的,只有在它依赖的数据发生变化(依赖的数据可以是单个,也可以是多个)时,会重新调用getter来计算;

  2. watch:

    • 如果data中没有相应的属性的话,是不能watch的;

    • 不支持缓存,数据变,直接会触发相应的操作;

    • 支持异步操作;

    • watch是监听器,可以监听某一个数据,然后执行相应的操作;

    • 监听的函数接收两个参数,第一个参数是最新的值;第二个参数是输入之前的值;

  3. 总结:

    • 当多个属性影响一个属性的时候,建议用computed;

    • 当一个值发生变化之后,会引起一系列的操作(改变其他属性值),这种情况就适合用watch;


    • 如果一个数据需要经过复杂计算就用 computed;

    • 如果在数据变化时执行异步或开销较大的操作时就用 watch;

3)路由跳转有哪几种方式
  • HTML标签:

    <router-link to="/home">Home</router-link>

  • JS对象:

    // 直接跳转
    this.$router.push('/home');
    // 替换当前路由记录,而不是添加新的记录
    this.$router.replace('/home');
    // 后退一步
    this.$router.go(-1);
    // 前进一步
    this.$router.go(1);

4) v-if和v-for的优先级
  1. VUE2:v-for优先于v-if;

  2. VUE3:v-if优先于v-for;

  3. 注意:同时使用 v-ifv-for不推荐的,因为这样二者的优先级不明显。

5)v-if和v-show的区别
  • v-if:条件渲染,当条件为假时,元素及其子组件不会被渲染或销毁。适用于频繁切换不显示的情况,有较高的渲染和销毁开销。

  • v-show:条件显示,元素始终被渲染,只是通过CSS display属性切换显示或隐藏。适用于频繁切换显示状态的情况,有较低的开销。

简单来说,v-if 控制元素的存在与否,而 v-show 控制元素的显示与隐藏。

二、后端面试题

(一)java基础

1)线程池的四种创建方式
  1. newCacheThreadPool:创建一个带缓存的线程池,池的长度可配置;

  2. newFixedThreadPool:创建一个固定大小的线程池;

  3. newScheduleThreadPool:创建一个定时执行的线程池;

  4. newSingleThreadPool:创建一个单线程的线程池;

2)线程池的五个参数
  1. corePoolSize:核心线程池的大小;

  2. maximumPoolSize:线程池能创建线程的最大个数;

  3. keepAliveTime:空闲线程存活时间,到期销毁;

  4. workQueue:阻塞队列,用于保存任务的阻塞队列;

  5. handler:饱和策略(拒绝策略);

3)synchronized底层原理

底层依赖一对 monitor 指令实现的,分别为 monitorentermonitorexit 进行控制,当执行 monitorenter 时,内部的计数器自增1,执行 monitorexit 指令时,计数器自减1,计数器为0则说明锁释放。本质上就是监听对象头中的 MarkWord 对象的内容, MarkWord 由64位字节码组成,锁占用三位,偏向锁占用一位,锁类型两位(无锁、偏向锁、轻量级锁、重量级锁);

  • 普通方法:锁的是当前的对象 this,谁调用谁就是锁;

  • 静态方法:锁的是当前类的Class对象,全局唯一;

  • 同步代码块:既可以锁对象,也可以锁类Class;

4)ThreadLocal底层原理
  • 内部由一个ThreadLocalMap实现,key 存的是当前 ThreadLocal 对象,value 为存储的值。

  • 属于空间换时间。使用后必须调用 remove 删除 Entry 对象,否则有内存泄漏的风险;

    • 使用线程池的情况下,使用后未进行清除 Entry 操作;

    • 由于 key 使用的是弱引用,在进行Full GC时,会回收弱引用的对象,因此,如果未删除,则会导致 key 回收后,value 无法回收且无法访问,最终引起内存泄漏。

5)CAS底层原理及ABA问题
  • 全称是 compareAndSwap,即比较和交换。它是通过处理器指令,实现程序的原子性。

  • 内部涉及三个变量:

    • V:变量内存地址;

    • A:原始值,修改前;

    • B:修改后的值;

  • 当执行CAS指令时,会先判断V内存中的值是否等于A,只有等于的时候才会修改为B;

  • ABA问题

    • 在CAS更新的过程中,当读取到的值是A,然后准备赋值的时候仍然是 A,但是实际上有可能A的值被改成了B,然后又被改回了A,这个CAS更新的漏洞就叫做ABA;

    • 可以通过增加版本号的方式解决,修改前先判断版本号,再进行CAS操作;Java中有AtomicStampedReference 来解决这个问题,他加入了预期标志和更新后标志两个字段, 更新时不光检查值,还要检查当前的标志是否等于预期标志,全部相等的话才会更新。

6)AQS是什么?
  • 全称是 AbstractQueueSynchroner,即抽象队列同步器。它是java在第二种对外提供的锁的实现,位于 java.util.current.lock 包下,属于JUC的核心。

  • AQS定义了对双向队列所有的操作,而只开放了 tryLock 和 tryRelease 方法给开发者使用,开发者可以根据自己重写 tryLock 和 tryRelease 方法,实现自己的并发功能。

7)集合概述
  • List集合:有序、有索引、可重复;

    • ArrayList:底层由数组实现,线程不安全,增删慢,查改快。

    • LinkedList:底层由链表实现,线程不安全,增删快,查改慢。

    • Vector:底层由数组实现,线程安全。每个方法添加有 synchronized 锁;

  • Set集合:无序、无索引、不可重复;

    • HashSet:底层由哈希算法实现,内部依赖 HashMap,存储的所有 value 为一个Object对象;

    • TreeSet:底层由二叉树实现,内部依赖 TreeMap,存储的所有 value 为一个Object对象;

  • Map集合:双列集合;

    • HashMap:底层由数组 + 链表 + 红黑树实现,首先根据key的哈希值确定存储的下标,之后根据 equals 方法判断链表的下标位置,相等进行覆盖,不相等插入在所在链表末尾的位置。当数组长度大于64,且链表长度大于8时,链表会转换为红黑树,链表长度小于6时,红黑树转换为链表,目的是为了提升查找的性能;

    • TreeMap:底层由二叉树 + 比较器实现,首先判断根节点是否有值,之后根据compare方法比较值的大小,小的存储在根节点左边,大的存储在右边。每次修改都会进行排序;

    • HashTable:与HashMap的区别:

      • HashTable不能存储null键和null值;

      • HashTable是线程安全的,内部方法都添加了synchronized锁;

8)forEach原理
  • 迭代器的forEach:使用的是 Itrator 接口的方法,底层使用增强for循环实现;

  • stream流的forEach:底层调用方法获取对应的 Spliterator 子类对象,每个集合都有自己的实现方式,内部为 do...while 循环实现;

9)重写和重载的区别
  • 方法重写:发生在子父类关系中,子类可以重写父类的方法,方法名必须相同,修饰符只能更大,异常只能更小,返回值只能更小;

  • 方法重载:发生在同一个类中,方法名相同,方法类型不同、方法参数不同、方法参数顺序不同;

(二)常用框架

1)简述Spring框架
  • IOC:控制反转,反转的是创建对象的权力;

    • DI:依赖注入,是控制反转的一种实现方式。容器中的Bean的属性由IOC容器进行注入;

  • AOP:面向切面编程,将不同的对象建立关系,在程序运行期间进行动态结合;

    • jdk动态代理:实现接口。

    • cglib动态代理:继承父类,父类不可被final关键字修饰。

2)AOP的五种通知类型
  • 前置通知:@Before,在连接点之前执行通知;

  • 后置通知:@After,在连接点之后执行,不论方法是否执行成功都进行通知;

  • 环绕通知:@Around,在连接点前后都会执行通知;

  • 返回后通知:@AfterReturn,方法正常执行结束时通知,抛异常不通知;

  • 抛异常通知:@AfterThrowing,方法抛出异常时进行通知;

3)Mybatis中 #{}${} 的区别
  • #{}:预编译处理;程序运行时,将 #{} 替换为 ? 进行SQL语句的保存,并解析内部的OGNL表达式,最终执行 PreparedStatement 的方法时,使用set方法,将 ? 替换为 #{} 中OGNL表达式的值;

  • ${}:字符串替换;程序运行时,将 ${} 替换为内部的值,不进行OGNL的解析;

4)SpringBoot启动步骤(暂无)
5)描述@SpringBootApplication注解

添加此注解的类,表示为SpringBoot的启动类,内部包含三个注解:

  • @SpringBootConfiguration:本质为 @Configuration 注解,扫描当前包及其子包下的配置类;

  • @ComponentScan:扫描当前包及其子包下的所有Bean注入容器;

  • @EnableAutoConfiguration:开启Spring自动配置类,将符合条件的配置类注入容器;

    • 内部包含一个 @Import 注解,作用是导入一个扫描器类,自动扫描 spring.factories 文件,此文件记录了SpringBoot支持的所有自动配置类,并判断哪些配置类符合自动配置的条件并注入容器;

6)SpringBoot自动配置原理
  • Spring Boot 自动配置通过扫描类路径中的依赖项和配置文件,基于条件注解(如@ConditionalOnClass@ConditionalOnMissingBean)自动配置Spring应用上下文的Bean。它使用spring.factories文件定义自动配置类,通过@EnableAutoConfiguration注解启用,简化开发人员的配置工作,提升开发效率。@EnableAutoConfiguration 注解存在于springboot的启动类 @SpringBootApplication 注解中。

7)SpringBoot Starter原理
  1. 自动配置:Spring Boot Starter通常会提供一组默认的自动配置,这些自动配置可以根据类路径上的依赖自动配置Spring应用程序的各个组件。自动配置通过条件注解和条件匹配器来确定是否需要应用某个配置。

  2. 依赖管理:Spring Boot Starter会管理一组相关的依赖,以确保它们的版本兼容性和稳定性。通过引入Spring Boot Starter,你无需手动管理这些依赖的版本,Spring Boot会自动为你解决版本冲突和依赖关系。

  3. 提供默认配置:Spring Boot Starter还可以提供一组默认的配置属性,这些属性可以在应用程序中进行自定义配置。通过这些配置属性,你可以修改默认行为,以满足你的需求。

  4. 简化开发:Spring Boot Starter的目标是简化开发过程,使开发者能够更专注于业务逻辑而非繁琐的配置。通过引入适当的Starter,你可以快速搭建起一个可运行的Spring应用程序,并且可以根据需要选择性地添加其他Starter。

8)OpenFeign原理
  1. 定义接口:首先,你需要定义一个Java接口来描述要调用的远程服务的API。在接口上使用@FeignClient注解指定要调用的服务名称,并使用@RequestMapping等注解定义具体的API方法。

  2. 生成代理:当应用启动时,OpenFeign会扫描带有@FeignClient注解的接口,并生成该接口的代理对象。代理对象封装了底层的HTTP请求逻辑。

  3. 发起请求:当你在代码中调用接口的方法时,实际上是在调用代理对象的方法。代理对象会根据方法的注解信息生成对应的HTTP请求。

  4. 处理请求:代理对象将生成的HTTP请求发送到目标服务,并等待响应。在发送请求之前,OpenFeign会根据配置的负载均衡策略选择一个可用的服务实例。

  5. 解析响应:一旦接收到响应,OpenFeign会将响应解析成Java对象,并返回给调用方。你可以使用@ResponseBody注解指定响应体的解析方式,比如JSON、XML等。

9)Nacos注册中心原理

微服务启动时,检查是否启用nacos的服务发现,如果开启了此配置,将会把当前微服务的微服务名称、IP地址 + 端口号等信息发送至Nacos注册中心,Nacos注册中心采用一个Map进行保存,key为微服务的名称,value维护了一个集合,内部存储了多个节点的微服务信息。

微服务调用时,采用负载均衡算法进行查找对应的微服务IP端口号进行返回。

10)Nacos配置中心原理(暂无)
11)SpringSecurity与Shiro如何使用
  • SpringSecurity

    • 创建配置类,重写 WebSecurityConfigurerAdapter 类的两个configure方法

      • 认证:用户鉴权,接口认证拦截;

      • 授权:权限管理,拦截器与处理器的注册;

    • 注解开启全局方法安全开关,对所有方法使用注解进行鉴权;

  • Shiro

    • Subject:存储当前用户,或与当前应用交互的对象;

    • SecurityManger:Shiro的核心,管理所有的Subject,与安全有关的操作都会与安全管理器交互;

    • Realm:数据访问控制,获取用户的角色、权限,验证用户身份时需要从Realm获取数据;

12)分布式事务:
  • 名词解释:

    • TMTransaction Manager,事务管理者。定义全局事务的范围,开始全局事务、提交或回滚;

    • RMResource Manager,资源管理者。管理分支事务处理的资源,与 TC 交谈以注册分支事务和报告分支事务的状态,并驱动分支事务提交或回滚;

    • TCTransaction Coordinator,事务协调者。维护全局和分支事务的状态,驱动全局事务提交或回滚;

  • 四种事务模式:

    • XA模式:事务提交至事务协调者TC,由TC统一决定是否提交事务;

    • AT模式:事务直接提交,并记录 undo_log 日志(SQL执行前后各一条),异常后根据日志回滚;

    • TCC模式:自行决定事务的提交回滚策略,指定执行的方法;

    • Saga模式:长事务解决方案,一种分布式异步事务。分两种实现:

      • 状态机引擎:通过事件驱动的方法异步执行提高系统吞吐,可以实现服务编排需求;

      • 基于注解和拦截器:开发简单、学习成本低;

    模式 一致性 隔离性 侵入性 性能 场景
    XA 强一致 完全隔离 对一致性、隔离性有高要求的业务
    AT 弱一致 依赖全局锁隔离 基于关系型数据库的大多数分布式事务场景
    TCC 弱一致 资源预留隔离 prepare commit cancel 需编写三个接口 对性能要求较高的事务。 有非关系型数据库要参与的事务
    Saga 最终一致 需编写状态机、 补偿业务 业务流程长、业务流程多, 参与者包含其它公司遗留系统服务, 无法提供 TCC 模式要求的三个接口

  • 设计问题处理:

    • 脏写:事务回滚前,需校验数据库与记录日志是否相同,如果不同,说明出现了脏写,需人工处理;

    • 允许空回滚:Try拥堵或其它原因未执行,Cancel执行了;

    • 防悬挂控制:Cancel比Try先执行了,即允许空回滚,但要拒绝空回滚后的Try操作;

    • 幂等控制:Try、Commit、Cancel要保证幂等性,即一次请求和多次请求对系统资源的影响是一致的;

13)POI与EasyExcel区别
  1. 功能和用途:

    • Apache POI是一个功能强大的Java库,用于读取、写入和操作Microsoft Office格式的文件,包括Excel、Word和PowerPoint等。它提供了广泛的API,可以实现对Excel文件的各种操作,如读取、写入、格式化、样式设置、图表生成等。

    • EasyExcel是一个基于POI封装的简单易用的Java库,专注于Excel文件的读写操作。它提供了简洁的API,使得开发者可以更方便地进行Excel文件的读取和写入。

  2. 简易性:

    • EasyExcel相对于POI来说更加简单易用,它提供了一些简化的API和注解,使得开发者可以更快速地进行Excel文件的读写操作。EasyExcel还支持将Java对象直接映射到Excel的行列中,简化了数据的转换和处理过程。

  3. 性能:

    • 由于EasyExcel是基于POI进行封装的,因此在性能上两者可能没有明显的差异。但是EasyExcel在一些性能优化方面进行了改进,例如使用缓存、批量写入等,可以提高处理大量数据时的效率。

  4. 社区支持和更新频率:

    • Apache POI是一个成熟的开源项目,拥有广泛的用户群体和活跃的社区支持。它经过多年的发展和更新,具有稳定性和可靠性。

    • EasyExcel是一个相对较新的项目,但也有一定的用户群体和社区支持。它的更新频率可能相对较高,可以更快地适应一些新的需求和变化。

总的来说,如果你需要进行复杂的Excel文件处理,包括读取、写入、格式化、样式设置等,那么POI是一个更全面和强大的选择。而如果你只需要进行简单的Excel文件读写操作,并且希望有更简洁易用的API,那么EasyExcel是一个更好的选择。

(三)设计模式

1)单例模式:有且仅有一个实例
2)代理模式:AOP切面编程
3)模板模式:针对复杂API进行一系列的、有规律的封装
4)工厂模式:创建不同的对象的工厂
5)适配器模式:抽象类实现接口,子类继承抽象类,仅需重写需要的方法即可
6)装饰者模式:装饰一个基础类,使其已有的功能更强大
7)责任链模式:一次请求贯穿所有处理器
8)策略模式:减少大量重复性的判断逻辑
9)委托模式:委托他人代替执行某些事情,无需考虑执行逻辑

(四)中间件

1)redis的几种数据结构及时间复杂度(暂无)
2)redis持久化方式
  • rbd形式:默认方式。存储的是对应的二进制文件,占用内存小,恢复快,数据易丢失;

  • aof形式:存储的是redis命令,占用内存大,恢复慢,数据不易丢失;

3)redis缓存淘汰策略
  • redis采用定期删除 + 惰性删除 + 内存淘汰策略;

    • 定期删除:每隔100ms,随机抽取数据检查;

    • 惰性删除:当获取key时,redis将检查此key是否过期;

    • 内存淘汰:当前两种情况不会删除全部的过期数据,导致内存占满,此时实施内存淘汰机制;

      • noeviction:进行报错;

      • allkeys-lru:移除最少使用的key;

      • allkeys-random:随机移除key;

      • volatile-lru:从设置过期时间的key中,移除最少使用的key;

      • volatile-random:从设置过期时间的key中,随机移除key;

      • volatile-ttl:从设置过期时间的key中,移除最先过期的key;

4)redis的缓存穿透、缓存雪崩
  • 缓存穿透:大量请求查询缓存中不存在的数据,导致所有请求打入数据库,导致数据库异常;

    • 互斥锁:查询数据库时,需要排队获取锁进行查询;

    • 布隆过滤器:维护一系列有效的的key,查询其他的key时直接返回;

    • 异步更新:无论key是否取到都进行返回,使用异步线程去维护key的有效性;

  • 缓存雪崩:大量缓存同时失效,导致所有请求打入数据库,导致数据库异常;

    • 随机过期:为每一个key设置随机失效时间,而不是同时失效;

    • 双缓存:一个设置失效时间,一个不设置。获取数据依次获取,异步维护key的有效性;

5)RabbitMQ原理
  1. 消息生产者(Producer)将消息发送到RabbitMQ的交换机(Exchange)上。消息可以是任何形式的数据,例如文本、JSON、图像等。

  2. 交换机根据预定义的路由规则,将消息路由到一个或多个消息队列(Queue)中。路由规则可以根据消息的特性进行匹配,例如消息的标签、类型等。

  3. 消息队列存储着消息,等待消费者(Consumer)来处理。消费者可以通过订阅特定的队列来接收消息。

  4. 消费者从队列中获取消息,并对消息进行处理。处理可以是任何业务逻辑,例如存储到数据库、发送邮件、执行计算等。

  5. 一旦消息被消费者处理完成,RabbitMQ会将消息从队列中删除。

6)Kafka基本原理
  1. 主题(Topic):数据被发布到Kafka的主题中。主题是消息的逻辑容器,可以理解为数据的分类。

  2. 分区(Partition):每个主题可以被分为多个分区,每个分区是一个有序的、不可变的消息序列。分区可以在多个服务器上进行复制,以实现冗余和容错性。

  3. 生产者(Producer):生产者将消息发布到指定的主题中。生产者可以选择将消息发布到特定的分区,也可以让Kafka自动选择分区。

  4. 消费者(Consumer):消费者订阅一个或多个主题,并从分区中读取消息。消费者可以以不同的方式读取消息,例如按照时间顺序、按照偏移量、按照消息键等。

  5. 消费者组(Consumer Group):多个消费者可以组成一个消费者组,共同消费一个主题的消息。每个分区只能被消费者组中的一个消费者消费,这样可以实现负载均衡和并行处理。

  6. 偏移量(Offset):每个消息在分区中都有一个唯一的偏移量,用于标识消息在分区中的位置。消费者可以通过指定偏移量来读取特定位置的消息。

7)ElasticSearch倒排索引

(五)大数据(大数据一点不会啊)

1)百万级数据批量导出

2)上亿数据去除重复
  • 使用Redis的BitMap

3)Samza转换Flink

三、数据库面试题

1)事务的四大特性(ACID)
  • 原子性:事务只能是同时成功,或者同时失败;

  • 一致性:执行结果必须是从一个一致性状态到另一个一致性状态;

  • 隔离性:事务之间相互独立,互不影响;

  • 持久性:事务执行结束后,数据将保存在数据库中;

2)ABC联合索引:最左匹配原则

Mysql从左到右的使用索引中的字段,一个查询可以只使用索引中的一部份,但只能是最左侧部分。例如索引是key index (a,b,c)。 可以支持a | a,b| a,b,c 3种组合进行查找,但不支持 b,c 进行查找。当最左侧字段是常量引用时,索引就十分有效。

  1. where a=3 and b=5 and c=4;:正序查询,索引生效;

  2. where c=4 and b=6 and a=3;:倒序查询,索引生效;

  3. where a=3 and c=7;:a 走索引,b没有用,所以 c 不走索引;

  4. where b=3 and c=4;:a 没用到,所以 bc 都不走索引;

3)SQL优化技巧

数据库优化三大方案:

  • 数据库服务器内核优化;

  • my.cfg 配置文件,搭配压力测试;

  • SQL语句调优:

    1. 使用缓存,相同的查询结果进行缓存;

    2. 建立索引,多表联查,根据连接条件建立索引;

    3. 使用 explain 关键字进行SQL调优,检查是否命中索引;

    4. 明确一条查询结果时,添加 limit 1,查到结果立即返回;

    5. 数据库字段类型,使用小的类型,提升读取速度;

    6. 避免使用 select *,尽量明确字段,当修改表时,返回字段会变化,产生不必要的查询结果;

    7. 数据量过大时,进行分库分表,垂直分割或水平分割;

      • 垂直分割:一张大表,分为多张小表;

      • 水平分割:建立多张表,表名规律,使用相应算法进行增删查改;

    8. 选择正确的数据库引擎:MyIsam、InnoDb;

4)InnoDb索引与MyIsam索引的区别
  1. 存储方式:InnoDB使用聚簇索引(Clustered Index),而MyISAM使用非聚簇索引(Non-Clustered Index)。

  2. 数据文件:InnoDB的数据文件本身就是按照主键顺序进行组织的,因此表数据和索引数据存储在同一个文件中。而MyISAM的数据文件和索引文件是分开存储的。

  3. 主键索引:InnoDB要求每个表必须有主键,如果没有显式指定,InnoDB会自动创建一个6字节的隐藏主键。而MyISAM对主键没有特殊要求,如果没有显式指定,会使用一个内部的行号作为主键。

  4. 二级索引:InnoDB的二级索引(非主键索引)的叶子节点存储了主键值,因此在通过二级索引查询时,需要先通过二级索引找到主键值,再通过主键值找到对应的数据行。而MyISAM的二级索引的叶子节点存储了指向数据行的物理地址。

  5. 并发性能:InnoDB支持行级锁定,可以提供更好的并发性能,多个事务可以同时读写不同的行。而MyISAM只支持表级锁定,当一个事务对表进行修改时,其他事务无法同时对同一表进行写操作。

  6. 容灾恢复:InnoDB支持事务和崩溃恢复,具备更好的容灾性和可靠性。而MyISAM不支持事务和崩溃恢复,容易出现数据损坏。

综上所述,InnoDB适合于需要高并发性能、事务支持和数据可靠性的场景,而MyISAM适合于读操作较多、对事务支持要求不高的场景。

5)聚簇索引与非聚簇索引的区别
  1. 数据存储方式:聚簇索引决定了数据在磁盘上的物理存储顺序,而非聚簇索引则是独立于数据存储的。聚簇索引将表的行存储在物理上相邻的位置,而非聚簇索引则是将索引的键值和对应的行指针存储在一起。

  2. 唯一性:一个表只能有一个聚簇索引,而可以有多个非聚簇索引。聚簇索引通常是基于主键或唯一约束创建的,因此它们的键值是唯一的。非聚簇索引可以是唯一或非唯一的。

  3. 查询性能:由于聚簇索引决定了数据的物理存储顺序,因此当使用聚簇索引进行范围查询或顺序访问时,性能通常较好。而非聚簇索引需要通过索引来查找行的位置,然后再根据行指针找到实际的数据行,所以在范围查询或顺序访问时性能可能较差。

  4. 数据插入和更新性能:由于聚簇索引决定了数据的物理存储顺序,插入新数据时可能需要移动已有的数据行,因此插入和更新性能可能较低。而非聚簇索引只需要插入索引键值和行指针,所以插入和更新性能通常较好。

6)BTree索引与Hash索引的区别
  1. 数据结构:BTree索引使用B树(或B+树)数据结构,而Hash索引使用哈希表数据结构。

  2. 查询方式:BTree索引支持范围查询,可以高效地处理范围查询和排序操作。而Hash索引仅支持精确匹配查询,对于范围查询和排序操作效率较低。

  3. 内存使用:BTree索引可以有效利用内存,适用于大数据集的索引。Hash索引需要将全部索引数据加载到内存中,适用于较小的数据集。

  4. 唯一性:BTree索引可以处理重复键值,支持非唯一索引。而Hash索引要求键值是唯一的,不支持重复键值。

  5. 插入和更新性能:BTree索引在插入和更新操作时需要维护索引的平衡性,性能相对较低。而Hash索引在插入和更新操作时直接计算哈希值,性能较高。

基于以上区别,BTree索引适用于需要范围查询、排序或非唯一索引的场景,比如在关系型数据库中常用于处理SQL查询。而Hash索引适用于需要快速精确匹配查询、唯一键值的场景,比如在内存数据库或缓存中常用于快速查找操作。

7)简述一下binlog、redolog、undolog
  • binlog:数据归档。记录数据修改之后的值。

  • redolog:数据恢复。数据更新后,先写入redolog,再做最终的修改;

  • undolog:数据回滚。记录数据修改之前的值。默认存储在全局表空间内,即写undolog时,也会写入redolog中;

  • 总结

    1. Buffer Pool 是MySQL进程管理的一块内存空间,有减少磁盘IO次数的作用。

    2. redo log 是InnoDB存储引擎的一种日志,主要作用是崩溃恢复,三种刷盘策略如下:

      • innodb_flush_log_at_trx_commit=0:延迟写,延迟刷,效率高,丢数据几率高;

      • innodb_flush_log_at_trx_commit=1:实时写,实时刷,效率低,丢数据几率低;

      • innodb_flush_log_at_trx_commit=2:实时写,延迟刷,效率较高,丢数据几率较低(推荐);

    3. undo log 是InnoDB存储引擎的一种日志,主要作用是回滚。

    4. bin log 是MySQL Server层的一种日志,主要作用是归档。

    5. MySQL挂了有两种情况:

      • 操作系统挂了MySQL进程跟着挂了;

      • 操作系统没挂,但是MySQL进程挂了。

Logo

欢迎加入西安开发者社区!我们致力于为西安地区的开发者提供学习、合作和成长的机会。参与我们的活动,与专家分享最新技术趋势,解决挑战,探索创新。加入我们,共同打造技术社区!

更多推荐