原始面经存档
字节后端日常实习一二三面面经
一面(40 分钟)
1,自我介绍,主要介绍了一下一个 go 写的基础项目,强调了一下高并发环境下数据库/消息队列/微服务在里面的作用,后面基本都是围绕这个项目来提问的。
2,你提到了高并发,那么对于高并发环境下数据库的优化都有哪些(说了缓存/分库分表/悲观锁乐观锁和队列)
3,说说乐观锁和悲观锁的区别
4,如果我现在做一个电商下单,比如说抢购的情景,你会用什么方法实现数据库(说了乐观锁,面试官反问乐观锁合适么,我陷入思考)
5,面试官又说,比如现在有两个场景,一个是只有一件商品,有比如十万个人抢购;另一个场景是有一千个商品,还是有十万个人抢购。你都会怎么设计策略。(思考了一会,如果一件商品直接乐观锁,适用于读多写少的场景,如果一千件商品就用一个队列强行把请求变成单线程,只放一千个请求过去,其他全部返回抢购失败)
6,开始问消息队列,有什么作用(异步解耦,说了一个例子)
7,如果使用消息队列怎么解决返回消息同步性的问题(有点记不清了,这个问题想了有点久,和面试官讨论了很久,因为不知道答案说了消息队列的原理/回调,但是感觉都不是正解,后面面试官就跳过这个问题了,后面复盘感觉是在问一致性和分布式事务相关的问题,可惜当时没了解到。)
8,redis 为什么快(基于内存/单线程/key-value 而不是传统的关系型数据库)
9,还有其他的原因么(介绍基于事件的 reactor 模型,加上 I/O 部分的多线程模型)
10,代码题,中等题 53.最大子数组和,动态规划非常简单,七行代码就写完了,写完之后面试官又问了一些代码上的优化问题,动态规划的递推思想,以及极端情况有没有考虑。
11,能不能马上入职,能实习多久。
12,反问
第二天约了二面。
二面(40 分钟)
1,自我介绍
2,又开始聊这个项目,还是数据库…
3,数据库的锁都有什么类型
4,介绍一下行级锁和表级锁
5,举一个使用表级锁的场景例子(有点想不起来了,强答了一个行级锁失效的场景会使用表级锁,面试官有点无语了估计)
6,给了一道 sql 题,应该很简单,大概就是通过一个没有索引的非主键列去找一条数据并更新,但是我好久没写了,直接说不会…
7,面试官质疑那你的项目里面总会有写 sql 语句的吧,怎么完全不会了,那你知道更新的关键字是什么么(update
8,那先不用写了,你说一下这道题的过程里面,加锁的流程(回答如果没有索引需要先加表锁检索 where 条件,然后在更新时在索引上加行级锁然后更新)
9,TCP 和 UDP 的区别(终于不问数据库了)
10,TCP 握手和挥手,挥手中 TIME_WAIT 和 CLOSE_WAIT 分别在哪个阶段(CLOSE_WAIT 答错了)
11,给老师和同学设计一个校园交易系统(情景题,一开始畏畏缩缩地说,后面直接放飞自我了,感觉又把我的项目说了一遍…,面试官说你应该先考虑基础地设计再说架构,比如定义什么什么对象,赶快承认不足)
12,面试官推荐了几本书结束了
二面在周五,周一约的三面在下周,部门年底很忙。
三面(35 分钟)
1,自我介绍
2,然后开始闲聊,聊目前的研究方向,看你本科和现在都是在安全的实验室,那你对安全这个方向有什么想法,你觉得做安全有什么普遍意义,现在我们也有一些做安全的小部门,实习的话有自己想做的方向么;又聊论文的思想,你论文提出的这个方案的目的是什么,别人提出的方案又是使用什么思想,你的方案对比别人有什么优势。
3,又开始聊数据库了…
4,redis 的 RDB 持久化指令 BGSAVE 操作是 fork 一个子进程进行持久化的,为什么不创建一个子线程完成持久化。(不会)
5,mysql 的事务隔离级别(RR)
6,又给了一个 MYSQL 的情景,大约是一列主键 a,一列 b,一列 c,通过 b 读出五行 c 的数据需要进行几次磁盘 IO(被自己蠢哭,说了回表,说了 B+ 树聚簇索引最后说一次 IO…有点太紧张了。
7,问了操作系统的用户态和内核态,有什么区别
8,除了 IO 操作什么时候会访问内核态。
9,代码题另一棵树的子结构,太像另一棵树的子树了,所以我说了子树哈希和暴力法,面试官提醒使用子树哈希真的可以么,不管是前序还是中序都不能转换为子串匹配,思考了一会,用暴力法开始做,面试官说先写出主要结构就行,不用急于创建测试用例。所以就写了一个递归的子树对比 cmp 函数,然后又写了一个递归的遍历。
10,反问,只能问一个问题,不知道是表现不佳还是太忙了…
总结
基本全是基于项目的问题,数据库相关的问题占 60% 以上,第一面发挥比较好,二三面很多问题都是紧张到脑子有点乱了然后答错,经验还是欠缺。不过字节的面试官都比较热情,面试氛围还是很积极的。
年底部门非常忙,每一面基本都不超过 40 分钟,第三面完两天还没有结果,孩子心都凉了,问了 HR 说流程可能拖到年后了…感觉可能是有竞争者还没有面完,这下死了的心又悬着了,只能等年后了。
总体来说个人被问到的最多的就是数据库,MYSQL 占 80%,同时算法题也很重要。
—————————————————————
2 月 6 日更新
打电话通知三面通过了,约了 hr 面,过完年的第一个好消息,希望能顺利通过 hr 面吧,后面我会把 hr 面和结果都更新上来的。
—————————————————————
2 月 27 日更新
终于 oc 了,一月初开始的面试流程,到现在已经接近两个月了,当日常实习去面试的,结果变成了暑期实习。
总得来说面试本身没问题,但是流程太长,期间一度以为已经被挂了。
作者:Kermanrin
来源:牛客网
字节实习(已 offer)
好吧,上一个帖子发完第二天字节 oc 了,这几天 offer 了 不用抉择了~
感觉二面压力比较大,一面跟三面还好,面试体验都挺不错的,算法都意外出的很简单,主要还是围绕实习去深入,烂点评面了这么多场一次都没问过,感觉可以下架了 hhh。
字节一面
- 问实习问了很久,让我一个一个介绍,为什么这么设计
- mysql 聚簇与非聚簇索引
- 联合索引的具体结构,给了一个 sql 问能否命中联合索引 (a,b,c),select * from order where a=1 and c>2 order by b
- completableFuture 实习怎么用的
- 索引结构
- MVCC
- 行锁,表锁,间隙锁,给了一个 sql 语句问我会加上什么锁
- 行锁什么时候会升级
- 线程池怎么用的,核心参数跟任务执行流程,线程一开始就有吗?
- TCP 四次挥手的状态
- I/O 多路复用,select poll epoll
- 算法:两两反转链表
字节二面
- 讲实习做的东西(这里给自己挖了个大坑)
- 自己去设计一个配置中心的架构,写出来,基本划分为哪几个模块,怎么实现推送跟拉去轮询的,让你设计 api 会设计成什么方式,返回值跟参数有哪些,什么时候采取哪种方式,设计的时候多台服务器负载均衡怎么办,还有其他一堆问题,这里脑子已经被干傻了,没看过配置中心具体源码实现啊
- 大表治理怎么做,表空洞解决,删除大量数据的时候让你去设计怎么减少 IO 损耗
- redis 集群怎么决定命中哪一个 redis 节点的,集群通信的基本流程
- 大 key 问题解决方案
- 算法:两个 list 求交集,扩展是 list 无限容量的情况怎么办
字节三面
- 介绍实习做的东西,开始拷打实习
- 场景题设计一个广告收费系统,考虑高可用性以及流量很大的情况,削峰之后 mysql 压力依然很大怎么办,这里问的比较久
- 进程间通信方式,哪个比较快,共享内存的方式在哪里见到过,不同主机之间一般是怎么通信的
- 开放性问题,这里聊了一会
无算法,感觉三面更偏向于场景设计以及对工作的期待
作者:paradiseidle
来源:牛客网
腾讯 PCG QQ 后端一,二面凉经
一面:2 月 24 1h
八股:15min
1,问 tcpudp 的区别?
2,什么协议用 tcp,什么用 udp
3,mysql 的索引结构
4,b+ 树有什么优点
5,linux 内存模型,malloc 做了什么,堆区栈区的作用
聊实习:20min
算法:不重复的全排列
二面:3 月 3 日
聊实习:20min
三道场景题:
1,设计一个贴吧系统,某个贴吧做活动,发帖量很高怎么做
答:同步处理请求,异步落地,同步缓存发帖信息,异步 mq 落地。
2,如果某个贴吧发帖量相当高,二级消费者消费不过来阻塞其他用户发帖怎么办。
答:topic 分区,物理隔离各个贴吧。贴吧单点限流(被否定了,因为用户体验差)。然后针对消息堆积的问题,改二级消费者的事件驱动型消费为批处理消费,一次消费多条数据增加 mysql 吞吐量,同时动态扩容消费者。这题 pass 了
3,设计一个 wx 朋友圈,你能看到你朋友发的所有 pyq,按照时间排序。
答:一开始撤了半天非关系型数据库,图关系数据库,没扯到点子上。最后想了一会答的是,每个用户维护一个 zset,保存好友的 pyq 内容和时间戳,同时动态维护这个 zset,每个人发 pyq 的时候维护他的所有好友的 zset。
4,又问了,如果一个人朋友非常多怎么办,你一次更新相当多的 zset 如何保证全部更新成功或者更新失败。
答:用户发 pyq 的时候不更新 redis,只落地,同时发送异步消息更新 redis,依赖 mq 的重试机制。
5,如何做幂等?
答:zset 的天然幂等,一开始答的分为 process/done 阶段,答完之后感觉不对想起来 zset 是天然幂等的
6,如果是微博哪种朋友圈,有很多大 v 怎么办,他们发消息也会异步更新所有关注他的人吗。
答:异步更新 + 主动拉取配合。对于大 v 粉丝量很高就不异步更新 redis 了,发 pyq 的时候主动缓存到 redis,用户刷 pyq 的时候维护一个大 v 的 keyset,用户的 zset 和 keyset 做一下归并。
这个问题我觉得答的不好,虽然好像效率还可以但是 redis 内存爆炸,而且 zset 缓存条数有限,如果用户把 zset 刷完了如何高效 pull 数据没想到,不过也没问。
作者:给个 off 吧要我做什么都行
链接:https://www.nowcoder.com/?anchorPoint=comment
来源:牛客网
字节财经 二面 压力面 被拷打烂了
面试公司:字节跳动
面试岗位:后台开发
面试问题:
-
没有自我介绍,一上来面试官直接说,你是有实习经历的是吧(我简历上压根没实习…)。我说我没有实习经历,但是有解决实际需求的项目经历,于是打算把 rag 项目跟他说说。结果对方直接打断然后来一句“我们这是后台开发,你跟我讲大模型有啥用”然后指名道姓要我讲另一个 java 项目
-
简单介绍了下 java 项目,他要我说 es 的底层架构。我先讲了讲倒排索引,不满意;又说了说索引库、文档,还是不满意。硬是要我描述 es 底层是什么架构(这又不是常见面试题我两个月速成的哪有时间准备这玩意啊)最后只能道歉
-
从这里开始我就感到不对劲了,因为这个面试官不仅会频繁打断我说话,而且只听自己想听的,完全不给我回避问题的机会。
还没完,又开始拷打我雪花算法。这个我也有一些准备,就跟他说了又符号位,时间戳,机器号和序号组成,又讲了每一部分是干什么的。结果他追问:那你怎么保证全局有序性?我说时间戳只会增大不会减小,序号可以保证一毫秒内的有序性。他继续问:那你同一毫秒内机器号大的生成序号小,最后总大小反而大怎么办?我实在没辙了,他就说你这个方案根本实现不了有序性
事后复盘这个问题的时候,我在网上搜也根本找不到这个问题相关讨论。哪怕问 AI 回答的也是模棱两可,最后 AI 说雪花算法并不能严格保证全局有序😓不是哥们这种问题你问个实习生是不是有点狠了😭
-
问我项目中的服务是怎么搭的,我提到了 nginx,他就要问我 nginx 的相关原理和细节。我说了反向代理的概念和正向代理的区别,不满意,要问我具体的 nginx 命令,不会,道歉
-
我谈到顺序 io 和随机 io 的性能差异。他直接打断,说你说的那是机械盘吧。现在都用 ssd,你说说 ssd 的底层原理吧。换成 ssd 你这套论断还生效吗?(ssd 考研 os 课程里了解过一点,但是基本忘干净了,遂寄)
-
又看我写了 redis,问我 redis 集群原理。讲了一番,追问用户请求访问一个 key,服务端和 redis 发生了什么?难道要在服务端决定 key 在哪个分片吗?我说当然不是,服务端连任意一台实例即可,实例之间有信息交互,会帮你转发到正确的节点。说完对方没反馈,也没追问
-
算法题:合并 n 个有序数组,限时 20 分钟。整场面试最轻松的时刻,讲思路,写代码,自己测了一遍,最后照着代码讲明白,行云流水。最后面试官问复杂度,也答对了。
反问:
base?(北京)
面试表现(不给说)
第三轮是技术面还是 hr 面(还是技术面,哭)
总结:和一面形成鲜明对比。首先面试官会频繁打断你,不接受你的任何引导,会执意提问很深很偏的东西直到你承认自己答不上来为止。全程眉头都紧皱,全程无反馈,只有一个问题接着下一个问题。
作者:野猪不是猪🐗
链接:https://www.nowcoder.com/?anchorPoint=comment
来源:牛客网
腾讯会议部门 一面凉经
算法:64. 最小路径和
1.TCP 和 UDP 的区别是什么?
2.适用于 TCP 和 UDP 的业务场景有哪些?
3.为什么延迟低的场景使用 UDP?UDP 为什么性能会比 TCP 更好?
4.观看视频和玩游戏不需要可靠性吗?
5.如何让 UDP 变得比 TCP 更可靠?
6.如何设计一个比 TCP 更好的 UDP 方案?如何保证你设计出的 UDP 比 TCP 更好?性能更好更可靠?
7.你了解 TCP 目前使用的拥塞控制算法吗?慢启动不是从头开始的
8.TCP 如何进行重传?如何确定何时重传?要等待多久重传?不同业务重试时间都设置一样?不同网络环境超时时间都设置一样?UDP 想实现重传,又该如何实现?
9.你了解 HTTP/2 吗?为什么后端开发要使用 HTTP/2?它的性能优势是什么?
10.HTTP/2 的多路复用一条 TCP 和 HTTP/1.1 的使用多个 TCP 连接方式,哪个性能更好?
11.HTTP/2 在同一个 TCP 连接的拥塞控制使用的是同一个拥塞控制算法?HTTP 1.1 在不同 TCP 连接使用的是同一个拥塞控制算法?
12.在后台开发中,什么时候使用多进程?什么时候使用多线程?
13.你认为多进程和多线程应该如何配合使用?
14.如果一台机器有 8 核 CPU,如何充分利用?多进程和多线程结合使用(面试官说同个进程只能用 2 核 CPU?同一个进程开再多的线程也无法利用上所有 CPU 核心?)
15.你在项目中遇到的最大挑战是什么?(讲完后,面试官觉得没多难啊。不过一个在校生怎么做出什么有挑战性的事情…)
16.如何处理 Redis 热 Key 问题?
17.如何统计哪些 Key 是热 Key?
19.如何保证本地缓存的一致性?
20.如何防止缓存击穿?热 key 缓存到本地,是有时间差的,这时的击穿风险如何解决?
21.用分布式锁和限流解决缓存击穿,那对于热 key 请求访问速度不是很慢?哪怕存在一丝风险,都得解决
22.如何在突发流量下保证系统可用性?
作者:wuwuwuoow
来源:牛客网
腾讯-IEG-开发 实习面经
一面
1.自我介绍
2.手撕 LRU
3.mysql 相关 八股吟唱
索引用什么数据结构
索引设计原则 优化手段
b+ 树优势 为什么不用 b 树
三大引擎讲一下 优势 区别
nosql sql 区别
4.os
多线程同步机制
进程,线程,协程的区别是什么?
io 模型
提了一嘴 reactor proactor(面试官说 那你还挺懂哈 不问 os 了。。。。。。)
5.redis
讲 redis 的架构 单 reactor 单进程
为什么快 还是讲架构 不同版本
redis 集群 哨兵 一堆
6.jvm
垃圾回收器 等记不清了
7.性格题
做项目同事吵架了 怎么办之类的
8.反问
印象不错 面试官说期待二面
面试结束 15 分钟 电话约二面
二面
1.自我介绍
2.纯纯项目拷打
2.1 正确率提升如何知道的怎么统计
2.2 如果让你升级这个项目 从技术 产品两个维度讲讲你的看法
2.3 硬件消耗
2.4 项目做多久,还在做吗
2.5 还有好多 记不起来了
项目中穿插几个小八股
mysql 默认引擎
用过哪些其他中间件 答 es mq 等(一定要答会的 不然被追问就 g 了)等
3.分布式相关问题
3.1 服务注册怎么实现的
3.2 微服务有好处,那坏处呢
3.3 还用过哪些分布式组件
3.4 如何缓解写频繁?
答了构建缓存 不满意,运气好 想到昨天看的 RocksDB 答了 LSM 树架构的数据库
4.手撕
实现一个 k-v 存储数据库 支持 TTL 支持任意类型 value
哥们缓了好一会 参考 Redis 实现的 算是 AC 了吧
我的思路 map + 自定义 entry + 懒惰删除 + 定期任务 + 线程池
语言任选 我用 c 写不下去 换了 java 时间好赶啊 QAQ
5.非技术
加班 如何看待
工作不喜欢怎么办
5.反问
多久出结果
工作内容 性质
还有几面
面完刷新
流程显示等待 HR 面试
作者:时不时删库跑路
链接:https://www.nowcoder.com/feed/main/detail/97c550adecfa405c9f731d91f258a411?anchorPoint=comment
来源:牛客网
场景题
设计 12305,分布式高并发场景
怎么处理这么高并发?(限流,hash 切片,分区,缓存)
redis 缓存 MySQL,怎么处理写?
怎么处理脚本抢票?
了解一致性哈希吗?
讲一讲令牌桶算法?
怎么处理并发购票?
作者:牛客 257265907 号
链接:https://www.nowcoder.com/feed/main/detail/c9d471dcd17b4c97a18e882b75e3cb60?sourceSSR=users
来源:牛客网
字节跳动数据平台开发一面
下午打电话约了二面
……………………
2025/3/3 11:00 约 35min
自我介绍
个人项目询问,
介绍项目的微服务架构,询问有没有写过 rpc 之类的框架
raft 协议的规则,介绍 leader 选举的过程
引入快照作用,为什么能降低存储压力
切片存储系统,怎么切片的。
八股询问,
了解 MySQL 吗?索引有哪些?
你提到了联合索引,什么场景使用?
做过查询优化吗?有哪些方法?
MySQL 事务隔离级别怎么实现的?介绍 mvcc
算法题,
数组中和为 0 的不重复三元组
反问,
业务,面试评价
作者:牛客 257265907 号
链接:https://www.nowcoder.com/feed/main/detail/d00b341e58a44a608ace5c713989f716?sourceSSR=users
来源:牛客网
如何定位慢 SQL(场景)
- 业务场景执行时间非常久,触发网关超时
- 使用以下命令分析慢 SQL 日志:
mysqldumpslow /path/to/your/slow-query.log
优化思路
增删查改
- 对于插入可以把多个语句合并成一个语句批量处理。
- 对于删除,因为删除是假删除 (减少 B+ 树合并访问磁盘的开销),如果有太多地方没有使用,B+ 树层数虚高,增加了访问磁盘的速度,并且全表扫描也会扫描到很多无用数据,可以在数据库空闲的时候通过 alter table 来重建表使数据排列更紧凑
- 对于频繁修改的数据
- 利用最左匹配原则减少索引数量
- 如果有唯一索引可以考虑改成普通索引,避免修改时为了维护唯一性导致 change buffer 失效。
- 对于查询:
- 使用缓存,早期 mysql 开启查询缓存,mysql8.0 没有查询缓存,业务层可以使用缓存例如 redis;或者可以把一些特殊的语句定期执行然后保存,后面查保存的数据,不用执行 sql,比如我之前做的一个预测成本的功能,每月只需要预测一次,那就可以写一个定时任务每个月定时预测一次保存到另一张表,后续查询直接查这张表就可以了,就不用执行复杂 SQL 了。
- 对于大数据量的场景,可以读写分离,分库分表
分析执行计划
EXPLAIN 分析 SQL 语句的执行计划,主要关注以下几个字段
- 如果 type 为 ALL,说明进行了全表扫描,考虑是否可以通过增加索引来优化。
- 分析 possible_keys(可能使用到的索引)和 key(实际使用的索引),确保相关的列上建立适当的索引并且正确选取索引。
- 使用覆盖索引来避免回表
- 使用复合索引来提高多条件查询的性能(索引下推)。
- 利用最左匹配原则尽可能的建立更少的索引
- 分析有没有没有正确选取索引:
- 可能会错误的使用全表扫描的场景:
- 对字段使用了函数:将函数写在判断条件上面,避免对字段使用函数。
- 字段隐式类型转换(str->int, 字段使用了 utf8 但是字符是 utf8mb4),需要保证查询目标与字段类型一致
- 如果没有出现上述问题,还有一种解决思路:使用 force index 强制使用索引 | order by … limit 1。
- 因为选取索引是优化器的工作,优化器会分析选取索引的扫描行数加上回表的代价是否比主键全表扫描少,这里采用采样分析,因为全表分析代价太大,在多个事务的时候,因为是假删除而且多个事务的时候 MVCC 多版本数据在 undo-log 里面,这个时候采样分析会把已经删除的数据也考虑到总量里面去,比如实际上总量是 1000 行,考虑成了 2000 行导致考虑的扫描行数翻倍。所以采样分析针对高并发和大数量的场景是非常不准的
- MySQL 临时表,CTE 会破坏索引结构(例如 group 后使用了临时表):想办法优化掉临时表,或者减少临时表的查询、JOIN 操作
- 可能会错误的使用全表扫描的场景:
rows
字段,表示查询的结果集行数。我们要尽可能的减少 rows 的数量,以下是一些思路- 确保查询条件尽可能具体,例如在 WHERE 子句中使用更严格的条件。
- 对于确定的数量(例如只需要查询一个结果)使用 limit
- in 替换成 exists,in 是 双重匹配,exists 匹配到了一个后就会提前返回
- count 字段看可不可以替换成 count( * ), count(1)
- Extra 字段,记录一些额外信息
- 如果有 Using filesort,表示使用了文件排序。
- 可以考虑给需要排序的字段加上索引,因为索引使用的 B+ 树本来就是排序好的,可以减少排序时间。或者可以把单次排序的内存 sort_buffer_size 设置大一点,因为排序是取磁盘里的部分数据到内存进行排序最后合并,把单次排序内存设置大一点这样减少 IO 次数
- 如果有 Using Join Buffer, 说明 Join 没有使用索引。没有索引 join 会用到 Block Nested-Loop Join 算法,时间复杂度很高,可以看作两层遍历,实际上更复杂一点,考虑到数据很多不能全读到内存里,mysql 使用了 join_buffer 来存一部分数据,可能会因为 join_buffer 不够大,需要对被驱动表做多次全表扫描。
- 在需要 Join 的字段加上索引
- 如果有 Using filesort,表示使用了文件排序。
其它思路
- 对于某些语句正常执行的时候很快,偶尔执行时间会很长,很难复现。
- 这是因为触发了 flush 操作,我们应该尽可能的去减少 flush 操作触发的次数。如果频繁触发 flush 操作,可能是脏页比例过高,可以查看脏页比例,脏页比率控制策略主要与 redo-log 大小和写盘速度 (innodb_io_capacity) 有关,我们需要设置合理的 redo_log 大小以及符合实际的预期写盘速度 (可以通过 fio 这个工具来测试)。我们也可以想办法减小单次 flush 操作的时间,InnoDB 有个策略是刷某一页时发现这一页旁边的页也是脏页也会去刷旁边的页,这样连带着一片都刷进去,导致一次 flush 操作可能会耗费很长的时间,我们可以通过
innodb_flush_neighbors
来控制这个行为,值为 1 的时候会有上述的“连坐”机制,值为 0 时表示不找邻居,自己刷自己的。
- 这是因为触发了 flush 操作,我们应该尽可能的去减少 flush 操作触发的次数。如果频繁触发 flush 操作,可能是脏页比例过高,可以查看脏页比例,脏页比率控制策略主要与 redo-log 大小和写盘速度 (innodb_io_capacity) 有关,我们需要设置合理的 redo_log 大小以及符合实际的预期写盘速度 (可以通过 fio 这个工具来测试)。我们也可以想办法减小单次 flush 操作的时间,InnoDB 有个策略是刷某一页时发现这一页旁边的页也是脏页也会去刷旁边的页,这样连带着一片都刷进去,导致一次 flush 操作可能会耗费很长的时间,我们可以通过
- 设计表的时候,使索引的长度尽可能小,页的大小是固定的,根据索引长度计算 B+ 树阶数,阶数越小,每页的节点数越多,B+ 数深度越小,访问磁盘次数越少;
- 对于事务,使修改的顺序尽可能靠后,因为修改会持有行锁,会等事务提交后再释放锁,这样可能会阻塞其他事务,修改靠后就可以更晚的持有这些锁,这样就可以减少阻塞,也可以减少死锁发生的概率。
- 大数据量分页查询的优化,改成使用 id:分页的原理是查询到第一个满足条件的数据行后往后一页一页遍历,如果改成 id 的话,就可以使用索引进行优化,直接定位到需要查询的那一页
- CTE 物化问题,部分数据库(如 MySQL)将 CTE 处理为临时表时不会保留原表索引,解决方法:修改逻辑避免使用 CTE/使用临时表替换 CTE, 并在临时表上加索引(空间换时间)
CTE(Common Table Expression 公共表表达式)是一种在 SQL 查询中定义临时结果集的方法。它通过 WITH 子句创建,可以:
- 简化复杂查询的可读性
- 支持递归查询
- 多次引用同一结果集 基础语法
1 | WITH cte_name (column1, column2, ...) AS ( |
我的面试思路
一般结合一两个点来讲
比如 Join 没有使用索引,耗时很长,但是后续分析发现 Join 字段上建立了索引,为什么 Join 没有选取索引呢?最终分析发现了以下原因:
- 临时表破坏了原表的索引结构
- CTE 物化问题破坏了原表的索引结构
再针对上述问题讲解一些优化思路。
作者:Error 小志 Exception
链接:https://www.nowcoder.com/?anchorPoint=comment
来源:牛客网