秋招篇—某云厂商后台开发岗一面面经(问题+答案)版
一面情况
- 面试时间:2025.12.02;
- 时长:70min左右。
自我介绍
正常模板。
问题
1. 谈谈你对RAG,AI Agent 和 MCP 的理解,日常在使用 AI 辅助编程的过程中,仅仅是停留在简单的对话模式上吗?
上来先不问技术,而是先谈到前沿技术的使用和理解,比较新颖,但是我回答的不太好,主要当时还是对这三个概念没有主动去了解过。
这里在最后的反问环节,面试官提到了要全面了解AI编程相关的前沿技术,比如MCP,AI Agent,RAG等。
RAG(Retrieval-Augmented Generation,检索增强式生成)
核心思想:模型不要光靠死记硬背的参数,而是先到外部知识库或者代码库里检索相关内容,再在此基础上生成答案。
场景:修改
chat-room服务的启动流程,我会让CodeBuddy先去读取项目里的代码和配置,比如server/application/chat-room/main.cc、chat-room.conf,包括里面用到的muduo、gRPC、Logic层 HTTP 调用这些上下文。它不是凭空瞎猜,而是先把这些文件内容检索出来作为上下文,再帮我解释HTTP 服务怎么起的、gRPC 怎么监听、房间订阅怎么初始化,然后基于这些真实代码给修改建议,这本质上就是 RAG,检索项目内部知识,再生成答案和代码。**AI Agent **
核心思想:Agent相比传统的问答,多了两个关键点,目标导向和会自己用工具、分步执行。
场景:比如我希望在Logic服务里新增一个房间历史查询功能,兼顾 MySQL 和 Redis 缓存,CodeBuddy 的 Craft Agent 会根据此目标,做出如下动作。
先列出
server/application/logic下面的目录结构;自动去看
logic/main.cc里 HTTP 路由是如何分发到api/service的;再打开
service/message_service、RoomService等相关代码,看当前是怎么查消息、怎么用Kafka和redis的;在理解现有设计的基础上,帮我完成房间历史查询功能的添加。
这整个过程,其实就是一个 Agent 在工作,它拿到一个业务目标之后,自己规划步骤、自己调用搜索/分析等工具,结合上下文做决策。
MCP(Model Context Protocol)
核心思想:MCP是Anthropic提出的,可以把它理解成一套标准化的模型插件协议,它规定了,像文件系统、数据库、HTTP 服务、命令行这类外部世界,要怎样通过一个统一的协议暴露给大模型,作为上下文资源和可调用工具。模型前面是一个客户端,后面有多个MCP server,每个MCP server都可以暴露自己的 tools、resources,模型就像调用插件一样去用。场景:在使用CodeBuddy进行AI Coding时,会读取
main.cc、读取\*.conf、搜索特定接口、执行编译或启动命令等。这些能力,在系统内部其实都被抽象成一组标准工具接口,模型通过某种协议去调用,这跟 MCP 的思想是一致的,通过一套协议,把本地代码库、配置、运行时命令,统一接到模型的上下文世界里,让模型不仅能看见代码,还能动手操作。总结
这里在后面被问到使用AI工具的时候,可以和面试官说是有了解这些比较前沿的概念的,可以说自己已经把 LLM 当成一个会用工具协作开发的同事,在后端项目开发中,它会先通过类似 RAG 的方式读我的配置项和源代码,再以 Agent 的方式调用各种工具(读文件、搜索、执行命令),在调用读文件,搜索,执行命令的过程中,其实就是使用了MCP思路。
2. 介绍一下OSI七层模型,解释一下TCP和UDP的区别,以及TCP是如何保证可靠传输的?
这里回答的比较一般吧,好像TCP的流量控制和拥塞控制忘记了,需要补充一下。
1. TCP和UDP的区别
TCP UDP 是否面向连接 面向连接:三次握手建立连接,四次挥手断开 无连接:直接发送 传输可靠性 可靠:有确认、重传、顺序控制、校验和等 尽力而为:不保证到达、不保证顺序、不负责重传 数据传输方式 字节流(Stream),无边界概念 数据报(Datagram),有消息边界 是否保证有序 保证按发送顺序交付 不保证,可能乱序、丢失、重复 流量控制 有:基于接收窗口(rwnd)的滑动窗口流量控制 无,发送端按自己节奏发 拥塞控制 有:慢启动、拥塞避免、快重传、快恢复等算法,这里有拥塞窗口的概念 无,协议层不关心网络拥塞 头部开销 较大,至少 20 字节 较小,固定 8 字节 适用场景 要求可靠、有序的场景:HTTP/HTTPS、数据库、文件传输等 要求实时、对少量丢包可容忍:语音/视频通话、直播、游戏等 连接状态维护 维护连接状态(发送/接收缓冲区、窗口、序号等) 无连接状态,协议层无状态 广播/多播支持 只支持一对一通信 支持广播、多播 2. TCP如何保证可靠传输?
从数据正确性 ==> 交付顺序 ==> 丢包处理 ==> 流量/拥塞来宏观记忆。
保证数据正确
校验和(Checksum):保证数据未损坏
- TCP 头部有 16 位校验和字段,覆盖TCP头 & 数据 & 伪首部;
- 解决的问题:比特错误 / 数据损坏。
序列号 & ACK 确认机制
每个 TCP 连接有一个 32 位序列号空间;
发送方为每个字节编号,报文段的 seq 表示本段数据的起始字节序号;
接收方用 ACK(确认号告诉发送方,我已经按序收到从起始到 N−1 的所有字节,下一个期望是 N;
特点:累计确认,ACK=N 表示“之前所有字节都收到了,可以减少 ACK 数量;接收方只对按序到达的最后一个连续字节发送 ACK。
解决的问题:知道哪些数据到了、哪些没到。
丢包处理
超时重传
发送方对每个未确认的报文段设置一个重传计时器(RTO);
若在RTO内没有收到相应ACK,则认为该报文段丢失,触发重传;
RTO不是固定值,而是依据往返时延RTT动态估计,典型算法是使用 加权移动平均 + 偏差估计 来计算RTO,使其略大于RTT;
解决的问题:丢包能被发现并重传。
滑动窗口协议
TCP 使用滑动窗口实现流水线传输和流量控制;
发送窗口:允许已发送但未确认的数据上限;
接收窗口:接收方还能接收的缓冲空间大小;
发送方在窗口范围内可以连续发送多个报文段,不必每个都等 ACK;
一旦收到 ACK,窗口右移,允许发送新的数据。
解决的问题:将ARQ(自动重传请求)从停等协议升级为连续ARQ,大幅提高吞吐量,为后面的流量控制提供基础(接收窗口控制发送方速率)。
有序交付与乱序缓存
网络中转发可能导致报文段乱序到达;
解决的问题:TCP 接收端会根据序列号将乱序段暂存于缓存,保证应用层始终是连续、有序的字节流。
3. TCP流量控制(Flow Control)
目标:不要把接收方冲爆;
接收方通过 ACK 中的窗口字段(Advertised Window,rwnd)告诉发送方,当前还能接收多少字节的数据;
发送方的实际有效发送窗口 =
min(rwnd, cwnd);当接收方缓冲快满时,会把 rwnd 调小甚至设置为 0:发送方必须减速或暂停发送。
4. TCP 拥塞控制(Congestion Control)
目标:不要把网络冲爆;
经典拥塞控制算法
cwnd(Congestion Window,拥塞窗口):发送方根据对网络拥塞的估计得出的窗口大小;
ssthresh(Slow Start Threshold,慢启动阈值):控制何时从慢启动切换到拥塞避免。
发送方实际发送窗口为:
min(rwnd, cwnd);慢启动(Slow Start)
目标:从小速率开始探测网络容量;
连接建立或发生超时重传触发慢启动算法:初始
cwnd = 1 MSS,ssthresh通常设为一个较大的值或上次的一半;每收到一个 ACK:cwnd += 1 MSS;特点:指数增长:1, 2, 4, 8, … MSS;当
cwnd >= ssthresh时,进入拥塞避免阶段。拥塞避免(Congestion Avoidance,AIMD)
- 目标:在可能接近网络极限的区域,线性增加发送速率,这避免了指数爆炸,减小了引发拥塞的概率。
超时&快重传&快恢复
丢包通常被看作网络发生了拥塞,需要降低发送速率。
情况 A:超时重传(Timeout)
最严重的拥塞信号;
处理方式:
ssthresh = cwnd / 2,cwnd重置为1MSS ,重新进入慢启动阶段。情况 B:收到 3 个重复 ACK
3 个相同ACK说明,有一个中间段丢了,但之后的段还在抵达,说明链路并未完全堵死;
快重传(Fast Retransmit):不等RTO超时,立即重传丢失的报文段;
快恢复(Fast Recovery):认为网络只是轻度拥塞,处理方式为
ssthresh = cwnd / 2,cwnd = ssthresh + 3 * MSS,每再收到一个重复 ACK:cwnd += 1 MSS。5. 一些计网简称回顾
RTT(Round-Trip Time,往返时间)
MSL(Max Segment Lifetime,最大报文段生存时间)
MSS(Maximum Segment Size,最大报文段长度)
RTO(Retransmission Timeout,重传超时时间)
3. 如何判断TCP报文段网络传输的稳定性,日常有抓包过吗,使用过什么抓包工具?
忘记了自己其实使用过Wireshark这样的抓包工具,其实拓展一下,可以说自己曾经开发过基于dpdk的用户态TCP/IP协议栈,这种网络模式对比linux内核实现的TCP/IP协议栈,具有更快的通信效率,而且可操作性高,但是编程难度较大,需要自己解析和组织TCP报文段。(如果有时间,可以复盘一下之前的dpdk程序)。
1. 如何判断 TCP 报文段网络传输的稳定性?
从抓包和指标两个维度来判断
RTT时长和抖动情况
看三次握手的 RTT、后续数据和ACK的往返时间是否稳定;
如果RTT波动很小、没有明显尖刺,说明网络时延比较平滑;RTT 经常突然拉高,说明链路有时拥塞或排队很严重。
重传率和重复ACK
- 在 Wireshark 里可以直接看到
TCP Retransmission、Fast Retransmission、Dup ACK等指标;- 偶尔有重传可以接受;如果连续超时重传、重复 ACK 非常多,就说明链路丢包、拥塞严重,传输明显不稳定。
接收窗口变化情况
看接收窗口是否频繁收缩,甚至出现“零窗口(Zero Window)”情况;
接收端窗口频繁被打满,说明对端处理不过来,从应用视角看会表现为卡顿和吞吐掉下来。
2. 一些抓包工具
- 在本机或开发环境中,使用Wireshark;
- 在服务器上更多用:
tcpdump指令:例如:tcpdump -i eth0 tcp port 8090 -w logic.pcap,然后在本地用 Wireshark 打开分析。3. dpdk用户态TCP/IP协议栈开发流程回忆
以收包,协议处理,发包三步骤为场景。
初始化 & 接管网卡
DPDK EAL 初始化,绑定网卡到 DPDK 驱动,配置 RX/TX 队列、内存池(mbuf pool);
这一层把「网卡 → 内核协议栈」的路径改成「网卡 → 用户态进程」。
轮询收包(L2/L3/L4 解析)
用户态线程用
rte_eth_rx_burst()从 RX 队列轮询收包(忙轮询,无中断);
- 对每个 mbuf 解析以太网头、IP 头、TCP 头,做基本校验和过滤(目标 IP/端口等)。
TCP/IP 状态机处理 & 用户态socket接口
- 在用户态维护 ARP 表、路由表、TCP 连接控制块(TCB);
- 实现简化版的 TCP 状态机:三次握手、四次挥手、序列号/ACK、重传、滑动窗口等;
- 对上提供类似
connect()/listen()/send()/recv()的接口或回调,业务代码直接调用这套用户态 API。发送路径:构造报文 & 发到网卡
上层调用用户态
send(),协议栈组装 TCP 段、填 IP/以太网头、计算校验和;将报文放入 mbuf,调用
rte_eth_tx_burst()发送出去(零拷贝 DMA 到网卡)。定时器 & 重传管理
用户态定时器周期扫描所有连接:处理超时重传、keepalive、连接超时回收等;
简单可以模仿 Reno/CUBIC 的 cwnd/ssthresh,或者根据场景自定义策略。
4. 用户态与内核态TCP/IP协议栈
维度 用户态 TCP/IP 协议栈(基于 DPDK) Linux 内核 TCP/IP 协议栈 协议栈 用户态进程 内核态 数据路径 网卡 → DPDK 驱动 → 用户态协议栈 → 业务 网卡 → 内核驱动 → 内核协议栈 → socket → 用户态 收包方式 轮询(poll-mode),忙轮询 RX 队列,无中断 中断驱动为主,结合 NAPI,软中断 + 内核线程处理 拷贝次数 可以做到 零拷贝:网卡 DMA → 用户态 mbuf 通常存在 内核 ↔ 用户态 拷贝(recv/send 时) 上下文切换 协议处理在用户态,无内核切换;少数系统调用 频繁在 用户态 ↔ 内核态 切换(系统调用、协议栈处理) 延迟 & 抖动 延迟极低、抖动小; 延迟略高且抖动较大,但对普通业务足够,性能平衡更好 安全性 & 稳定性 很大程度取决于自己实现;bug 可能导致进程崩溃或协议不兼容 经多年验证,稳定性、安全性、兼容性都非常成熟 开发 & 维护成本 非常高:要自己维护完整协议栈、状态机、定时器、容错、安全 由内核社区维护,业务方只需使用 socket API 适用场景 极端高性能场景:HFT、L4/L7 负载均衡器、自研网关、SDN 数据平面 绝大多数普通业务:Web 服务、数据库连接、微服务等 5. 总结
我会用Wireshark /
tcpdump等抓包工具来判断TCP连接的稳定性,看 RTT、重传、DupACK、窗口变化等指标;另外,我也尝试基于 DPDK 写用户态 TCP/IP 协议栈,对 TCP 的状态机、重传和拥塞控制有比较深入的理解(下次被问到可以直接这样回答)。
4. 30TB的数据,如何在16GB的内存上进行排序?
这个题没回答出来很炸裂啊,多路归并了解的太不熟悉了,要复习一下多路归并的具体流程了,但其实在面试过程中也把基本思路答出来了一点点。
以30TB数据为例子,每次可读取16GB数据到内存中排序,多路归并的思路如下:
第一步:先将30TB数据分成30TB/16GB,也就是1920份数据,将这1920份数据分别加入到内存中,进行快排,使其局部有序;
第二步:局部有序之后,进行多路归并,假设我们将16GB分成:15GB为输入缓冲区,1GB为输出缓冲区,我们可以对输入缓冲区15GB拆分成150份,每一份100MB,也就是做150路归并(每次从磁盘中拿150个文件,1920份可以拿13次),所以会生成13份文件;
第三步:基于第二步的13份文件,继续做13路归并,生成一份已排序的文件,完成归并。
这里需要深入思考归并过程
第一步,一定要拆分成1920份,因为尽量大的局部空间有序;
第二步:其实150路归并可以自定义,也不一定是150路,可以是其它多路,150路归并的意思是,每次将1920份中的150个局部有序的文件进行排序,所以一共可以生成13份有序的大局部文件;
第三步:做13路归并即可,很好理解,因为只有13个文件了。
为什么不使用二路归并?
如果使用二路归并,第一次1920份数据,执行一次二路归并后,生成960份,960份又进行二路归并,如此重复,会造成多次磁盘的IO,所以不合适,在IO上面非常耗时,而使用多路归并,只需要一共3次磁盘的IO。
5. 你知道bitmap这个数据结构吗,它的应用场景在哪里?
拿到这个问题比较抽象啊,我当时猜的回答应用场景是磁盘的文件存储,分为顺序存储了,链式存储和索引存储,可以使用位图标识磁盘中哪些位置是已经存储数据的(为1),哪些是不存储数据的(为0),不知道对不对。
面试的时候,回答应该是没问题的,猜对了,这里做一下小总结。
1. 什么是bitmap?
Bitmap(位图)就是一块连续的比特数组,每一个bit表示一个元素的状态(比如占用/空闲、存在/不存在等)。
2. 位图的特点
- 空间极省:一个元素只占1bit;
- 操作快:位运算可以非常高效地做
- 查询(某个bit是否为1);
- 统计(统计1的个数);
- 集合运算(按位与/或,实现交集/并集)。
3. 位图的应用
文件系统 / 内存管理中的资源分配,记录每一个磁盘块或者物理页框是否被使用;
大规模ID / 用户集合的存在性判断、去重
- 比如有上亿个用户 ID(数字型),需要快速判断“某 ID 是否出现过”,或者做去重;
- 用set/hash占内存很大,而用bitmap,只要按ID做偏移,一个 bit 表示“是否出现过”即可(一个bit位表示一个用户ID);
- 典型用法:日志去重、UV统计、黑名单/白名单标记等。
权限、特性开关、标签集合
- 一组权限feature,第0位表示是否是管理员,第1位表示是否有读权限,第2位表示是否有写权限等;
- 用一个整数就能表示一个用户的一整套权限集合,存储紧凑,判断也只需要按位与运算。
6. MySQL即使用了索引,为什么查询还是很慢的原因?
也是非常经典的问题,只有知道了查询很慢的原因,我们才能对其进行优化,这里面试的时候只说了回表查询,面试官显然不是很满意,说还有其它的原因吗,需要系统的总结一下。
这里分两种情况回答,比较有思路一点
情况一:只是偶尔sql语句执行很慢
- 数据库在刷新脏页,在数据库运行的内存中,存放了redo log,当我们执行一条更新语句的时候,数据库会在内存中把对应字段的数据更新了,但是更新之后,这些更新的字段并不会马上同步持久化到磁盘中去,而是把这些更新的记录写入到redo log日记中去,文件当数据库存在大量的更新时,redo log一下就满了,数据库会全身心来把数据同步到磁盘中去的,而这个时候,就会导致我们平时正常的SQL语句突然执行的很慢,所以说,数据库在在同步数据到磁盘的时候,就有可能导致我们的SQL语句执行的很慢;
- 当前执行的sql语句涉及到的表或者行被加锁了,只有等其它事务执行完释放锁了,当前sql语句才能继续执行下去,可以使用
show processlist命令查看是否是真的等待锁。情况二:sql语句一直执行很慢,那可能需要考虑我的sql语句书写问题了
- 字段没有索引,数据库只能全表扫描;
- 字段有索引,但是没有用上,一般是对索引字段进行了运算、函数操作或者隐式类型转换时,索引会失效,也只能全表扫描;
- 查询语句查询了索引以外的字段,会导致回表查询;
- 查询条件的字段有索引,数据库本身不使用索引查询,而是使用全表查询
- 因为系统会判断索引区分度(基数,也就是索引不同值的个数)大小,如果索引基数很小,那么数据库会选择全表扫描。
7. 你说到了回表查询的问题,那么如何避免呢?
这里当时面试的时候好像说了不要查询非主键索引以外的字段,就不会产生回表查询,大差不差吧,可以再多说一点。
回表查询的本质就是,因为我们的非主键(聚簇)索引在B+树的叶子节点中只存储了索引值和主键值,如果需要拿到非主键索引以外的值,就需要使用主键索引去拿到行数据,这个时候就导致了会出现回表查询,解决方法如下:
- 最根本的方法就是不要使用非聚簇索引去查询索引以外的字段,避免回表查询;
- 直接使用主键索引查询;
- 对于查询的字段建立复合索引。
拓展:使用
EXPLAIN检查sql语句的执行计划,查看是否真的使用了覆盖索引或回表查询。
8. MySQL事务的隔离机制有哪四种机制?
面试的时候直接说不知道,没办法当时还没复习到,也是非常经典的MySQL问题。
1. 四种隔离级别
READ UNCOMMITTED(读未提交)
- 特点:一个事务可以看到其他事务未提交的数据;
- 问题:会出现 脏读、不可重复读、幻读,基本不建议使用。
READ COMMITTED(读已提交)
- 特点:只允许读到已经提交的数据,不会读到未提交的中间状态;
- 解决:避免脏读;
- 仍可能出现:不可重复读、幻读;
- 一些数据库(如 Oracle)的默认级别就是它。
REPEATABLE READ(可重复读,InnoDB默认隔离级别)
- 特点:一个事务内,多次读取同一行,看到的数据是一致的快照(同一版本);
- 解决:避免脏读和不可重复读;
- InnoDB通过MVCC和间隙锁,在大多数场景下也能避免幻读。
SERIALIZABLE(可串行化)
- 特点:最高隔离级别,理论上相当于所有事务加锁串行执行;
- 解决:脏读 & 不可重复读 & 幻读全部避免;
- 代价:并发度极低,锁冲突严重,很少在高并发业务场景使用。
2. 拓展
脏读:读到了别人没提交的修改;
不可重复读:同一行,多次读,结果不一样;
幻读:同一条件,多次查,行的“数量 or 集合”变了,多了或少了几行。
3. 什么是MySQL的MVCC(多版本并发控制)?
一句话解释MVCC就是,给每一行保留多个版本和生成事务自己的快照视图,让大多数读操作不用加锁,就能读到一致的数据。
- MVCC出现背景?==> 没有 MVCC 时,要想实现可重复读,最直接的办法是:读的时候给行加读锁,别人不能改;写的时候给行加写锁,别人不能读,这会导致系统并发度极差,大家互相锁来锁去,吞吐量很低;
- MVCC 解决什么问题?==> 让读和写尽量互不阻塞,写,照常更新当前版本;读,读自己那个时间点看到的旧版本(快照),而不是强行锁住最新那一份。
4. InnoDB怎么实现多版本的?
InnoDB 每一行都有两个隐藏字段(简化版理解)
trx_id:最后一次修改这个行的事务 ID;
roll_pointer:指向undo log的指针,通过它能找到这个行旧版本的信息。执行
UPDATE语句
InnoDB在undo log记录旧值;
把数据页里这一行更新为新值,把
trx_id改成当前事务ID,把roll_pointer指向刚写入的undo记录;数据页里的当前行是新版本,undo链表里串着历史旧版本。
多版本存在于当前页和undo log链中。
5. 快照读是怎么挑版本的(Read View)?
当一个事务开始做快照读(普通
SELECT,不带FOR UPDATE)时,InnoDB 会为这个事务生成Read View,主要包含:
- 当前系统里活跃未提交事务的ID列表;
- 当前系统分配过的最大事务ID等。
读某一行,InnoDB会沿着当前版本和undo链往回走,找到对这个事务来说可见的那个版本
- REPEATABLE READ(可重复读,InnoDB 默认)
- 一个事务在执行过程中,多次SELECT用的是同一个 Read View;
- REPEATABLE READ看到的是事务开始那一刻的快照,即使别的事务已经提交了新的修改,它也看不到,从而避免不可重复读。
- 对于READ COMMITTED(读已提交)
- 每次SELECT都会生成新的Read View;
- READ COMMITTED看到的是别人已经提交的新版本,不会看到未提交的,解决了脏读,但允许不可重复读。
MVCC实现了同一条物理数据,不同事务、不同隔离级别下,看到的是不同版本的本质。
6. MVCC 和锁的关系
- 普通 SELECT(快照读),利用MVCC不加行锁可以读到一致性视图,读写之间的冲突减少,提高数据库并发量;
- 当前读(SELECT … FOR UPDATE / UPDATE / DELETE),操作当前最新版本的数据,会加行锁、间隙锁等,MVCC主要优化读体验,写操作需要加锁。
9. 还问了索引的问题,在查询条件where a=x and b=x;中,对a和b分别建立的索引,优先使用哪一个索引?
应该是听到了我说的最左匹配原则(完全不对啊,最左匹配原则是在复合索引下的概念),面试官深入引申了一下,后面我猜回答说是使用a。
情况一:有联合索引,不管是(a, b)还是(b, a),都优先使用联合索引,而不是单列索引
CREATE INDEX idx_a_b ON t(a, b); -- 或 CREATE INDEX idx_b_a ON t(b, a);情况二:只有单列索引
- 会根据索引的区分度大小(基数),选择区分度高的索引进行查询;
- 也有可能两个单列索引都使用,然后将结果做交集。
注:选择区分度(基数)大的索引进行查询之后,再进行回表查询,然后根据另一个字段的
where条件过滤结果行(如果没有使用两个索引做交集,不会两个索引都使用)。最左匹配原则
对于一个联合索引,比如
(a, b, c),MySQL 在进行查询匹配时,必须严格按照从左到右的顺序来使用,不能跳过中间的列。只要查询条件从最左边的列开始并且是连续的,就能利用到索引;一旦中间断开,或者遇到了范围查询,后面的列就无法再通过索引进行高效匹配了。
10. 继续上述问题,一定会使用a吗,什么情况下不使用a,而是使用b?
这里我直接说不会了,面试官进行了简单的拓展,说是如果索引a失效了,就会使用b,索引a失效的情况, 比如对索引使用了数学运算或者函数操作等?
不一定会使用索引a,以下情况会使用索引b
- 在a和b都建立了单列索引前提下,MySQL优化器计算出索引b的区分度(基数)更大,会选择使用索引b而不是索引a;
- 在索引a中使用了函数操作、数学运算或者隐式类型转换,导致索引a失效了,这个时候只能使用索引b;
- b 索引是覆盖索引;
ORDER BY/GROUP BY更契合索引b,WHERE a = x AND b = x ORDER BY b,可能用idx_b能一次完成过滤和排序,整体代价更低。
总结
MySQL,Redis,Kafka这样的中间件,如果仅仅是在使用的程度上,是不行的,需要去深入了解一些常见后端开发需要用到的知识点,只有这样,才能对整个后端的程序进行针对性的性能优化,针对面试过程也能和面试官聊起来。
更多推荐


所有评论(0)