今天我将那些腾讯面试过的 MySQL 场景问题给大家整理出来,本文将跟大家一起来探讨如何回答这些问题。
1.一个 6 亿的表 a,一个 3 亿的表 b,通过外间 tid 关联,你如何最快的查询出满足条件的第 50000 到第 50200 中的这 200 条数据记录?
2.一条 sql 执行过长的时间,你如何优化,从哪些方面入手?
3.索引已经建好了,那我再插入一条数据,索引会有哪些变化?
4.mysql 的是怎么解决并发问题的?
5.MySQL 两个线程的 update 语句同时处理一条数据,会不会有阻塞?
6.两条 update 语句处理一张表的不同的主键范围的记录,一个 < 10,另一个 > 15,会不会遇到阻塞?
7.如果 Explain 用到的索引不正确的话,有什么办法干预吗?
8.给你张表,发现查询速度很慢,你有哪些解决方案?
9.关心过业务系统里面的 sql 耗时吗?统计过慢查询吗?对慢查询都怎么优化过?(explain)?
一个 6 亿的表 a,一个 3 亿的表 b,通过外间 tid 关联,你如何最快的查询出满足条件的第 50000 到第 50200 中的这 200 条数据记录?
这是一道腾讯的面试题,其实这个问题和上面是同一个问题,都是超大分页的问题,这就像读书的时候做数学题一样,上面是公式、定理,下面是题目,所以要学会举一反三。
- 如果 A 表 TID 是自增长,并且是连续的,B 表的 ID 为索引
select * from a,b where a.tid = b.id and a.tid>500000 limit 200;
- 如果 A 表的 TID 不是连续的,那么就需要使用覆盖索引.TID 要么是主键,要么是辅助索引,B 表 ID 也需要有索引。
select * from b , (select tid from a limit 50000,200) a where b.id = a .tid;
一条 sql 执行过长的时间,你如何优化,从哪些方面入手?
查看是否涉及多表和子查询,优化 Sql 结构,如去除冗余字段,是否可拆表等
优化索引结构,看是否可以适当添加索引
数量大的表,可以考虑进行分离/分表(如交易流水表)
数据库主从分离,读写分离
explain 分析 sql 语句,查看执行计划,优化 sql
查看 Mysql 执行日志,分析是否有其他方面的问题
索引已经建好了,那我再插入一条数据,索引会有哪些变化?
插入新数据可能导致 B+树结构的调整和索引信息的更新,以保持 B+树的平衡性和正确性,这些变化通常由数据库系统自动处理,确保数据的一致性和索引的有效性。
如果插入的数据导致叶子节点已满,可能会触发叶子节点的分裂操作,以保持 B+树的平衡性。
mysql 的是怎么解决并发问题的?
锁机制:Mysql 提供了多种锁机制来保证数据的一致性,包括行级锁、表级锁、页级锁等。通过锁机制,可以在读写操作时对数据进行加锁,确保同时只有一个操作能够访问或修改数据。
事务隔离级别:Mysql 提供了多种事务隔离级别,包括读未提交、读已提交、可重复读和串行化。通过设置合适的事务隔离级别,可以在多个事务并发执行时,控制事务之间的隔离程度,以避免数据不一致的问题。
MVCC(多版本并发控制):Mysql 使用 MVCC 来管理并发访问,它通过在数据库中保存不同版本的数据来实现不同事务之间的隔离。在读取数据时,Mysql 会根据事务的隔离级别来选择合适的数据版本,从而保证数据的一致性。
MySQL 两个线程的 update 语句同时处理一条数据,会不会有阻塞?
如果是两个事务同时更新了 id = 1,比如 update ... where id = 1
,那么是会阻塞的。因为 InnoDB 存储引擎实现了行级锁。
当 A 事务对 id =1 这行记录进行更新时,会对主键 id 为 1 的记录加 X 类型的记录锁,这样第二事务对 id = 1 进行更新时,发现已经有记录锁了,就会陷入阻塞状态。
两条 update 语句处理一张表的不同的主键范围的记录,一个 < 10,另一个 > 15,会不会遇到阻塞?
不会,因为锁住的范围不一样,不会形成冲突。(当然前提是,没有其他事务干预 且 使用索引没有进行全表扫描)
第一条 update sql 的话( id<10),锁住的范围是(-♾️,10);
第二条 update sql 的话(id >15),锁住的范围是(15,+♾️)。
追加问题,如果 2 个范围不是主键或索引?还会阻塞吗?
如果 2 个范围查询的字段不是索引的话,那就代表 update 没有用到索引,这时候触发了全表扫描,全部索引都会加行级锁,这时候第二条 update 执行的时候,就会阻塞了。
因为如果 update 没有用到索引,在扫描过程中会对索引加锁,所以全表扫描的场景下,所有记录都会被加锁,也就是这条 update 语句产生了 4 个记录锁和 5 个间隙锁,相当于锁住了全表。
如果 Explain 用到的索引不正确的话,有什么办法干预吗?
可以使用 force index,强制走索引。
explain select name,price
from products
force index (idx_price)
where price between 10 and 80
orderby by price;
给你张表,发现查询速度很慢,你有哪些解决方案?
如果面试遇到了这样相似的问题,如优化查询速度,可以选择下面的几条来回答。
分析查询语句:使用 explain 命令分析 sql 执行计划,找出慢查询的原因,比如是否使用了全表扫描,是否存在索引未被使用的情况等,并根据相应情况对索引进行适当修改。
创建或优化索引:根据查询条件创建合适的索引,特别是经常用于 where 子句的字段、orderby 排序字段、join 连表查询的字典、group by 的字段,并且如果查询中经常涉及多个字段,考虑创建联合索引,使用联合索引要符合最左匹配原则,不然会索引失效
避免索引失效:比如不要用左模糊匹配、函数计算、表达式计算等等
查询优化:避免使用 select *,只查询真正需要的列;使用覆盖索引,即索引包含所有查询的字段;连表查询最好要以小表驱动大表,并且被驱动表的字段要有索引,当然最好通过冗余字段的设计,彼岸连表查询。
分页优化:针对 limit n,m 深分页的查询优化,可以把 limit 查询转换成某个位置的查询:select * from product where id> 20000 limit 10
,该方案适用于主键自增的表
优化数据库表:如果单表的数据超过了千万级别,考虑是否需要将大表拆分为小表,减轻单个表的查询压力。也可以将字段多的表分解成多个表,有些字段使用频率高,有些低,数据量大时,会由于使用频率低的存在而变慢,可以考虑分开。
使用缓存技术:引入缓存层,如 redis,存储热点数据和频繁查询的结果,但是考虑缓存一致性的问题,对于读请求会选择旁路缓存策略,对于写请求会选择先更新数据库,再删除缓存的策略。
关心过业务系统里面的 sql 耗时吗?统计过慢查询吗?对慢查询都怎么优化过?(explain)?
在业务系统中,除了使用主键进行的查询,其他的我都会在测试库上测试其耗时,慢查询的统计主要由运维在做,会定期将业务中的慢查询反馈给我们。
慢查询的优化首先要搞明白慢的原因是什么? 是查询条件没有命中索引?是 load 了不需要的数据列?还是数据量太大?
所以优化也是针对这三个方向来的,
首先分析语句,看看是否 load 了额外的数据,可能是查询了多余的行并且抛弃掉了,可能是加载了许多结果中并不需要的列,对语句进行分析以及重写。
分析语句的执行计划(explain),然后获得其使用索引的情况,之后修改语句或者修改索引,使得语句可以尽可能的命中索引。
如果对语句的优化已经无法进行,可以考虑表中的数据量是否太大,如果是的话可以进行横向或者纵向的分表。
就业陪跑训练营学员投稿
欢迎关注 ❤
我们搞了一个免费的面试真题共享群,互通有无,一起刷题进步。
没准能让你能刷到自己意向公司的最新面试题呢。
感兴趣的朋友们可以加我微信:wangzhongyang1993,备注:面试群。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。