MySQL面试题(附带具体业务场景,共23题)
MySQL性能优化实战总结 总结了MySQL性能优化的核心方法: 慢查询定位:通过监控工具或慢查询日志识别性能瓶颈 执行计划分析:使用EXPLAIN查看索引使用情况、扫描方式和额外操作 索引优化: 理解B+树索引结构特点 区分聚簇索引(主键)和非聚簇索引(普通索引) 避免回表查询(使用覆盖索引) 分页优化:超大分页时先查ID再获取数据 业务场景应用:针对高并发场景如商城订单、库存查询等进行针对性优
MySQL面试题(附带具体业务场景)
文章目录
- MySQL面试题(附带具体业务场景)
-
- 1.MySQL中,如何定位慢查询?
- 2. 那这个SQL语句执行很慢,如何分析呢?
- 3. 了解过索引吗,什么是索引?
- 4.索引的底层数据结构了解过吗?
- 5. B树和B+树的区别是什么呢?
- 6.什么是聚簇索引什么是非聚簇索引
- 7.知道什么是回表查询吗
- 8.知道什么叫覆盖索引吗
- 9.MySQL超大分页怎么处理
- 10,索引创建原则有哪些
- 11,什么情况下索引会失效
- 12,SQL优化的经验有哪些
- 13.创建表的时候,你们是如何优化的呢
- 14.在使用索引的时候,是如何进行优化的。
- 15.你平时对SQL语句做了哪些优化呢
- 16. 事务的特性是什么?可以详细说一下吗?
- 17.并发事务带来哪些问题
- 18,怎么解决这些问题的
- 19.undo log 与redo log的区别是什么?
- 20.事务中的隔离性是如何保证的呢(你解释一下MVCC)
- 21,MySQL主从同步的原理是什么
- 22.你们的项目采用过MySQL的分库分表吗?
- 23.那你之前使用过MySQL的分库分表吗?
- 23.那你之前使用过MySQL的分库分表吗?
1.MySQL中,如何定位慢查询?
嗯,我们当时在做压力测试时发现有些接口响应时间非常慢,超过了2秒。因为我们的系统部署了运维监控系统 Skywalking,在它的报表展示中可以看到哪个接口慢,并且能分析出接口中哪部分耗时较多,包括具体的 SQL 执行时间,这样就能快速定位到出现问题的 SQL。
比如以前在做 商城下单 的场景时,我们发现“提交订单”接口耗时特别长。通过 Skywalking 链路追踪发现,问题出在库存校验那一步,具体是查询商品库存的 SQL 执行时间超过了 3 秒。后来分析 SQL 执行计划发现,这条语句没有命中索引,是因为 where 条件里用了函数处理字段,导致索引失效。我们优化 SQL 后,接口响应时间从 3 秒降到了 300 毫秒。

如果没有这种监控系统,其实 MySQL 自身也提供了 慢查询日志(slow query log) 功能。可以在 MySQL 的配置文件 my.cnf 中开启,比如设置:
slow_query_log = 1
slow_query_log_file = /var/log/mysql/slow.log
long_query_time = 2
这样所有执行时间超过 2 秒的 SQL 都会记录到日志文件中。
像商城下单这种高频业务,我们就可以定期分析慢查询日志,看看哪些 SQL 在高并发下执行慢,比如库存更新、订单插入、优惠券状态更新等,通过这些日志就能精准找到性能瓶颈。

2. 那这个SQL语句执行很慢,如何分析呢?
如果一条 SQL 执行得很慢,我一般会先用 EXPLAIN 去分析它的执行计划。
通过 key 和 key_len 可以看出有没有命中索引;如果命中了索引,还能看索引是否有效。
然后我会看 type 字段,它能反映扫描方式,比如是全表扫描、全索引扫描,还是只扫描部分行。
另外 Extra 这个字段也很重要,它会告诉我们有没有出现 Using filesort 或 Using temporary 等提示,像这些通常意味着 SQL 还有优化空间。
举个例子吧,比如我们在做商城下订单的时候,有一条查询商品库存的 SQL:
SELECT stock FROM product WHERE product_id = '1001';
按理说这条语句应该很快,但在压测时发现执行时间居然超过了 2 秒。
我用 EXPLAIN 看了一下,发现 type 是 ALL,说明它在做全表扫描,而 key 是 NULL,表示没走索引。
最后发现是因为开发同事在 where 条件里写了函数处理,比如:
WHERE CAST(product_id AS CHAR) = '1001';
这就导致索引失效了。我们去掉函数后重新测试,SQL 执行时间从 2 秒降到了几毫秒。
还有一次是在查订单列表时:
SELECT * FROM orders WHERE user_id = 12345 ORDER BY create_time DESC LIMIT 10;
EXPLAIN 结果里出现了 Using filesort,说明排序没有走索引。
后来我们在 (user_id, create_time) 上加了一个联合索引,优化后就不再 filesort 了,查询速度提升了一个数量级。


3. 了解过索引吗,什么是索引?
嗯,我了解索引,索引在项目里用得非常多,它其实就是数据库里的一种 数据结构,用来帮我们 快速查数据,相当于书的目录。
它的主要作用是提高 查询效率,降低数据库的 I/O 成本。除此之外,索引还能对数据进行 排序,减少排序开销,也能减轻 CPU 的负担。
打个例子,比如在商城下订单的场景:
- 用户下单的时候,我们要查商品的库存,如果没有索引,数据库就得 全表扫描,尤其是商品表有几万、几十万条记录时,这样查很慢。
- 有了索引,比如在
product_id上建了主键索引或者普通索引,查询库存时就能 直接定位到对应商品行,几乎是瞬间返回结果。 - 再比如查询某个用户的订单列表,如果我们在
(user_id, create_time)上建了联合索引,既能快速筛选出这个用户的订单,又能直接按创建时间排序,这样用户打开订单列表就非常快。
所以在业务高频操作的场景,比如下单、库存查询、订单列表展示,合理使用索引可以显著提升系统性能。
4.索引的底层数据结构了解过吗?
嗯,我了解一些。MySQL 默认的存储引擎 InnoDB 使用的索引底层结构是 B+ 树。
之所以用 B+ 树,有几个原因:
- 节点可以有很多子节点,所以树比较“矮”,查找的时候路径短,性能好。
- 磁盘读写成本低,因为非叶子节点只存键和指针,不存实际数据,叶子节点才存数据,这样可以减少 IO。
- 范围查询和扫描特别高效,因为叶子节点之间是双向链表,遍历的时候可以顺序访问,不需要回到父节点。
打个例子,比如我们商城下单时,用户查询价格在 100 到 200 元之间的商品,如果商品表有价格的索引,B+ 树可以 快速定位起点,然后顺序扫描到终点,整个过程比全表扫描快很多。
5. B树和B+树的区别是什么呢?
B树和B+树的主要区别在于:
- B树的非叶子节点和叶子节点都存放数据,而B+树的所有数据只出现在叶子节点,这使得B+树在查询时效率更稳定。
- B+树在进行范围查询时效率更高,因为所有数据都在叶子节点,并且叶子节点之间形成了双向链表。


6.什么是聚簇索引什么是非聚簇索引
嗯,我了解聚簇索引和非聚簇索引。简单说:
- 聚簇索引是数据和索引放在一起的,B+ 树的叶子节点直接存了整行数据。通常一张表只能有一个聚簇索引,一般就是主键。
- 非聚簇索引是索引和数据分开存的,叶子节点只存主键值,所以通过非聚簇索引查到的是主键,再回表去找整行数据。非聚簇索引可以有很多,一般我们自定义的索引都是非聚簇索引。
举个例子,比如商城下订单:
orders表的主键是order_id,它就是一个 聚簇索引,查询订单详情的时候,B+ 树叶子节点就直接存了整行订单数据,所以查单条订单非常快。- 假设我们想经常按
user_id查询某个用户的订单列表,我们可以在user_id上建一个 非聚簇索引。查询时,数据库先通过索引找到对应的order_id,再回表去取整行订单数据。这样既能快速找到该用户的订单,也不会占用聚簇索引的空间。
所以聚簇索引适合 快速定位单条数据,非聚簇索引适合 查询多条记录或做多条件查询
7.知道什么是回表查询吗
嗯,我知道回表查询。简单来说,回表查询就是:当我们通过 非聚簇索引 找到数据时,叶子节点里只有 主键值,数据库还得再去聚簇索引里查一次,才能拿到整行数据,这个过程就叫回表。
举个例子,比如我们商城下订单:
- 我们在
orders表的user_id上建了一个非聚簇索引,经常用来查某个用户的订单列表。 - 当用户打开订单列表时,数据库先通过
user_id索引找到了对应的order_id, - 然后再通过这些
order_id去聚簇索引里查整行订单数据,这一步就是 回表。
回表查询比直接命中聚簇索引慢一些,尤其是查多条记录时,所以在设计索引时,如果经常需要返回很多字段,尽量用 覆盖索引,这样就可以避免回表,提高查询效率。
8.知道什么叫覆盖索引吗
候选人:
嗯,我知道覆盖索引。简单来说,覆盖索引就是指 查询需要的所有列都能在索引里找到,这样数据库就不用再去回表查聚簇索引的数据了,可以直接从索引里返回结果,提高查询效率。
举个例子,比如商城下订单:
- 假设我们经常要查询某个用户的订单号和订单状态:
SELECT order_id, status FROM orders WHERE user_id = 12345;
- 如果在
(user_id, order_id, status)上建了一个联合索引,这个查询就可以 直接在索引里拿到 order_id 和 status,完全不用回表查整行数据。 - 这样一来,即使用户有上千条订单,这条查询也能很快返回,因为减少了对聚簇索引的访问。
所以覆盖索引特别适合 频繁查询部分列 的高性能场景,像订单列表展示、商品价格查询等,都可以用覆盖索引优化查询速度。
9.MySQL超大分页怎么处理
候选人:
嗯,我知道超大分页的问题。简单来说,当数据量很大时,比如订单表有几百万条记录,如果直接用 LIMIT 做分页查询,尤其是带排序的时候,效率会非常低。
解决办法之一是 先用索引查询 ID,再用子查询拿整行数据,这样可以大幅提升性能。
举个例子,还是以商城下订单为例:
- 假设我们要查看某个用户的第 1000 页订单,每页 20 条,如果直接写
SELECT * FROM orders WHERE user_id = 12345 ORDER BY create_time DESC LIMIT 19980, 20;
- 数据库会扫描前面 19980 条数据,效率很低。
优化方法是:
- 先用索引只查
order_id和create_time,这可以用覆盖索引完成分页:
SELECT order_id FROM orders WHERE user_id = 12345 ORDER BY create_time DESC LIMIT 19980, 20;
- 得到这一页的
order_id后,再用子查询或者IN去聚簇索引里拿整行数据:
SELECT * FROM orders WHERE order_id IN ( ...上一条查询得到的order_id列表... );
这样就避免了扫描大量无关数据,查询效率会明显提升。
10,索引创建原则有哪些
嗯,我了解一些索引创建的原则,主要有几个方面:
- 数据量大时才考虑索引,一般表超过十万条记录,就需要考虑建索引,否则收益不大。
- 选择查询频繁的字段建索引,比如 where 条件字段、排序字段或者 group by 字段。
- 尽量使用复合索引,如果索引里包含查询返回的字段,就可以做覆盖索引,减少回表。
- 低区分度的字段放在复合索引后面,比如性别这种只有男女两种值,放在前面没意义。
- 内容较长的字段可以用前缀索引,节省空间。
- 控制索引数量,索引虽然能加快查询,但也会增加插入、更新、删除的开销。
举个例子,还是以商城下订单为例:
- 订单表
orders很大,有几百万条记录,所以我们需要在经常查询的字段上建索引。 - 用户查询自己的订单列表时,会按
user_id查询,还按create_time排序,所以我们在(user_id, create_time)上建了复合索引,这样查询一页订单非常快,而且可以做覆盖索引避免回表。 - 对于商品表里价格区间查询,价格字段区分度高,我们也会单独建索引;但像商品状态这种低区分度字段,就不单独建索引,或者放在复合索引后面。
- 同时我们控制了索引数量,不会在每个字段上都建索引,避免影响下单、更新库存的性能。
11,什么情况下索引会失效
嗯,我知道索引在一些情况下会失效,常见的几种情况有:
- 没有遵循最左前缀原则,比如复合索引
(user_id, create_time),查询条件必须从最左边的user_id开始,否则索引可能不生效。 - 模糊查询
%在前面,比如WHERE product_name LIKE '%手机',前面加了%,索引就无法利用。 - 在索引字段上做运算或类型转换,例如
WHERE YEAR(create_time) = 2025,会导致索引失效。 - 复合索引中间用了范围查询,右边的条件可能失效,比如
(user_id, create_time)索引,如果写了WHERE user_id = 123 AND create_time > '2025-01-01' AND status = 1,status = 1可能不会走索引。
举个具体的商城下订单场景:
- 我们在
orders表的(user_id, create_time)上建了复合索引,用来查询用户的订单列表。 - 如果有人写了
WHERE create_time > '2025-01-01' AND user_id = 123,因为没遵循最左原则,索引就不会生效,全表扫描,查询会很慢。 - 再比如查询商品名含“手机”的订单:
WHERE product_name LIKE '%手机%'
前面加了 %,索引也失效。
- 还有一种情况是做运算,比如统计某个月的订单数量:
WHERE MONTH(create_time) = 10
这样也会导致索引失效,需要改写成 WHERE create_time >= '2025-10-01' AND create_time < '2025-11-01' 才能走索引。
这些都是在高并发、大数据量场景下容易导致查询变慢的典型问题,所以设计索引和写 SQL 时要特别注意。
12,SQL优化的经验有哪些
嗯,我在 SQL 优化方面有一些经验,主要可以从几个方面考虑:
-
建表时选择合适的字段类型,比如订单表里
order_id用 bigint,status用 tinyint,既节省存储,又提高查询效率。 -
使用索引,并遵循索引创建原则,比如在
orders(user_id, create_time)上建复合索引,这样查询用户订单列表就很快。 -
编写高效的 SQL,避免
SELECT *,只查询需要的字段;在合并结果集时尽量用UNION ALL代替UNION,减少排序去重开销;关联表时优先使用INNER JOIN,不要随意用LEFT JOIN。- 举例来说,查询用户的订单和对应商品信息,如果直接
SELECT *关联大表,数据量大时很慢;改成只选需要的字段,并且用索引字段关联,速度就快很多。
- 举例来说,查询用户的订单和对应商品信息,如果直接
-
读写分离,利用主从复制,把查询请求分流到从库,减轻主库压力。
- 比如商城里用户下单时,写操作走主库,订单列表展示、订单统计走从库。
-
分库分表,当订单表非常大时,可以按时间或者用户 ID 做分库分表,减少单表数据量,提高查询性能。
- 比如把订单表按月份拆分成
orders_202501、orders_202502,查询特定月份订单时只扫描一个小表,性能明显提升。

- 比如把订单表按月份拆分成
13.创建表的时候,你们是如何优化的呢
嗯,创建表的时候,我们主要会参考开发手册,并结合业务场景来选择合适的字段类型和表结构。
举个商城下订单的例子:
- 订单表里,
order_id用 BIGINT,因为订单量大,保证全局唯一; user_id用 INT,节省空间,同时满足大部分用户量;status用 TINYINT,因为订单状态值只有几个,既节省存储,又方便查询;product_name用 VARCHAR(100),长度根据实际商品名称设计,避免浪费空间;- 金额类字段用 DECIMAL(10,2),保证精度,不用浮点数类型,防止计算误差。
此外,我们还会考虑一些建表优化策略:
- 字段顺序:把经常查询的字段放在前面,能提升索引效率和缓存命中率;
- 表分区或分表:对于订单表这种每天产生大量数据的表,可以按时间或者用户 ID 做分区或拆表,避免单表过大导致查询慢;
- 默认值和非空约束:合理设置默认值和非空约束,可以减少不必要的 NULL 判断,提高查询效率。
14.在使用索引的时候,是如何进行优化的。
嗯,在使用索引的时候,我们会遵循一些优化原则,确保索引能真正提高查询性能。
- 选择查询频繁的字段建索引,比如订单表里用户经常按
user_id查询订单列表,我们就在(user_id, create_time)上建了复合索引。 - 尽量用复合索引覆盖返回字段,这样就可以做覆盖索引,避免回表查询,提高查询效率。
- 比如用户查看订单列表时,只需要
order_id和status两个字段,如果索引里已经包含这两个字段,数据库就能直接返回结果,不用再去查整行数据。
- 比如用户查看订单列表时,只需要
- 避免在索引字段上做运算或类型转换,比如不要写
WHERE YEAR(create_time) = 2025,会导致索引失效,改写成WHERE create_time >= '2025-01-01' AND create_time < '2026-01-01'才能走索引。 - 控制索引数量,索引太多会影响写操作性能,像下单、库存更新等高频写操作,要平衡查询和写入效率。
总之就是让数据库查询尽量少扫描、少回表,提高性能。
15.你平时对SQL语句做了哪些优化呢
嗯,我平时对 SQL 优化主要有几个方面:
- 明确字段名称,避免 SELECT *,这样不仅能减少返回的数据量,还能避免回表造成不必要的开销。
- 比如在商城查询用户订单列表时,我只写
SELECT order_id, status, create_time,而不是SELECT *,这样查询速度更快。
- 比如在商城查询用户订单列表时,我只写
- 避免导致索引失效的写法,比如不要在索引字段上做函数或类型转换,确保查询能走索引。
- 比如以前写过
WHERE YEAR(create_time) = 2025,改成WHERE create_time >= '2025-01-01' AND create_time < '2026-01-01'就可以走索引。
- 比如以前写过
- 聚合查询尽量用 UNION ALL 代替 UNION,避免额外排序去重开销。
- 比如统计不同类型订单的数量时,用 UNION ALL 汇总,比 UNION 快。
- 表关联优先使用 INNER JOIN,只有必要时才用 LEFT JOIN 或 RIGHT JOIN,并且让小表作为驱动表,这样能减少数据扫描量。
- 举例来说,如果要查询订单和对应的商品信息,INNER JOIN 大多数情况下就够了;如果一定要用 LEFT JOIN,我会让商品表(小表)先驱动查询,减少无效数据扫描。
16. 事务的特性是什么?可以详细说一下吗?
嗯,我了解事务,它有四个特性,通常用 ACID 来描述:
- 原子性(Atomicity):事务是最小的执行单位,要么全部成功,要么全部失败。
- 比如在商城下订单时,创建订单、扣减库存和生成支付记录,这几个操作必须一起成功,如果任何一步失败,整个事务回滚,订单就不会生成。
- 一致性(Consistency):事务执行前后,数据库必须保持一致的状态。
- 还是下订单的例子,如果用户下单 2 件商品,总库存减少 2 件,订单金额增加到待付款状态,数据库必须保持这些数据一致,不会出现库存扣减但订单未生成的情况。
- 隔离性(Isolation):事务之间互不干扰,不同事务的数据操作不会相互影响。
- 比如两个用户同时购买最后一件商品,每个事务只能看到自己操作前后的数据,不能因为另一个用户的事务还没提交就读取到中间状态。
- 持久性(Durability):事务一旦提交,数据就会永久保存,即使系统崩溃也不会丢失。
- 比如用户支付完成后,订单状态变为“已支付”,即使服务器突然宕机,数据也会被持久化到数据库,不会丢失。
17.并发事务带来哪些问题
嗯,并发事务可能会引发几种问题:脏读、不可重复读和幻读。
- 脏读(Dirty Read):一个事务读到了另一个事务还没提交的数据。
- 比如用户 A 正在修改订单状态,把订单改成“已支付”,还没提交;此时用户 B 查询同一个订单,如果能看到“已支付”,就可能导致脏读,因为 A 的事务可能最终回滚。
- 不可重复读(Non-Repeatable Read):同一个事务内多次读取同一条数据,结果不一致。
- 例如用户在查看自己的订单总金额时,第一次读取是 200 元,另一笔事务修改了订单金额,第二次再读取时变成 250 元,这就不可重复。
- 幻读(Phantom Read):事务读取到了其他事务新插入的“幻行”。
- 比如用户在查看当天所有未支付订单,第一次查询返回 5 条订单。与此同时,另一个事务插入了一条新的未支付订单,第一次事务再次查询时发现多了一条,这条新插入的记录就是“幻行”。
18,怎么解决这些问题的
嗯,要解决并发事务导致的脏读、不可重复读和幻读问题,就需要用 事务隔离。MySQL 支持四种隔离级别:
- 未提交读(READ UNCOMMITTED):事务可以读取其他事务未提交的数据,但这样脏读问题无法避免。
- 比如用户 A 下单还没提交,用户 B 看到订单状态已经是“已支付”,如果 A 回滚,就出现了错误数据。
- 读已提交(READ COMMITTED):能解决脏读问题,但不能解决不可重复读和幻读。
- 比如用户查询订单总金额时,每次读取的数据可能不同,前后不一致。
- 可重复读(REPEATABLE READ):能解决脏读和不可重复读,但不能解决幻读,这也是 MySQL 默认隔离级别。
- 在商城下订单时,如果用户查询订单详情,可重复读保证在同一事务内多次查询结果一致,不会因为别人的修改导致金额或状态变化。
- 但如果其他事务新增了新的订单记录,幻读问题可能依然存在。
- 串行化(SERIALIZABLE):可以解决所有问题,包括幻读,但性能开销大。
- 适合对数据一致性要求极高的场景,比如财务结算或大额支付系统,但在高并发的商城业务中可能影响性能。
简单说,MySQL 默认 可重复读 已经能保证大部分业务场景的数据一致性,像下订单、查询订单详情等都是安全的。如果业务对幻读敏感,才会考虑串行化或其他锁机制来保证完全隔离。
19.undo log 与redo log的区别是什么?
候选人:
嗯,我了解 undo log 和 redo log 的区别。简单来说:
- Redo log 记录的是 数据页的物理变化,主要用在 系统宕机后的恢复,保证事务的 持久性。
- 比如用户在商城下单,订单写入数据库后,如果服务器突然宕机,redo log 可以帮助数据库把已提交的订单恢复到磁盘,保证数据不丢失。
- Undo log 记录的是 逻辑日志,主要用于 事务回滚,保证事务的 原子性和一致性。
- 比如用户下单时,如果在扣减库存的过程中出现异常,事务回滚,undo log 会把库存恢复到操作前的状态,保证订单没有扣错库存。
简单说,redo log 保证提交后的数据不丢失,undo log 保证事务出问题时能回滚。在像商城下订单这种业务中,两个日志都是保证数据安全和一致性的重要机制。
20.事务中的隔离性是如何保证的呢(你解释一下MVCC)
嗯,事务的隔离性主要是通过 锁 和 多版本并发控制(MVCC) 来保证的。简单说,MVCC 是通过 维护数据的多个版本,让事务在读写时互不干扰,从而避免冲突。
它的底层实现主要包括几个部分:
- 隐藏字段:每条数据里有
trx_id(事务 ID)和roll_pointer(回滚指针),用来标记数据属于哪个事务,以及回滚用到的旧版本。 - Undo log:记录了旧版本的数据,通过
roll_pointer形成版本链,当事务需要回滚或者读取旧版本数据时可以使用。 - Read view:定义了不同事务隔离级别下的快照读,决定事务能看到哪个版本的数据。
举个商城下订单的例子:
- 用户 A 在查看自己订单列表时,MVCC 会让他看到事务开始时的订单状态,即使其他用户或系统正在修改订单,也不会影响 A 的查询。
- 用户 B 同时在下单、扣减库存,这些写操作会生成新版本数据,但不会干扰用户 A 正在读取的数据。
- 如果用户 A 在事务中多次查询自己的订单列表,每次读取的结果都是一致的(可重复读),这就是 MVCC 保证隔离性的一部分。
简单来说,MVCC 可以 提高并发性,减少读写冲突,同时保证事务隔离性和数据一致性,在商城这种高并发下单场景中非常重要。
21,MySQL主从同步的原理是什么
候选人:
嗯,我了解 MySQL 主从同步的原理,核心就是 二进制日志(Binlog)。大致流程是这样的:
- 主库记录 Binlog:当事务在主库提交时,所有数据变更会被记录到 Binlog。
- 比如用户在商城下订单时,生成订单记录、扣减库存,这些操作在主库提交时都会写到 Binlog。
- 从库读取 Binlog 并写入中继日志(Relay Log):从库会实时拉取主库的 Binlog,并写到自己的中继日志里。
- 这样从库就有了一份主库的数据操作记录,准备同步执行。
- 从库重做操作:从库根据中继日志中的事件,把变更反映到自己的数据里,保持与主库一致。
- 也就是说,从库上的订单表、库存表会和主库同步更新,用户在查询订单或库存时,不管访问主库还是从库,都能看到一致的数据。
简单来说,主库处理写操作,从库同步数据,这样既保证了数据一致性,又能把读取请求分流到从库,提高商城系统的并发性能。
22.你们的项目采用过MySQL的分库分表吗?
候选人:
嗯,我们项目是 微服务架构,每个微服务对应一个数据库,这其实就是 垂直拆分,按业务模块来分库。
举个商城下订单的例子:
- 比如订单服务、用户服务和商品服务,各自有自己的数据库:
- 订单库只存订单信息;
- 用户库存用户信息和账户数据;
- 商品库存商品信息和库存。
- 这样做的好处是不同业务的读写压力分开,不会互相影响。
- 比如用户下单时,订单库处理订单写入和库存扣减;同时用户查询商品信息的时候,不会去打扰订单库,提高系统整体性能。
简单来说,分库分表不仅可以 减小单库数据量,还能提高 系统并发处理能力,是大型商城系统常用的优化策略。
23.那你之前使用过MySQL的分库分表吗?
候选人:使用过。当时业务发展太快了,比如商城的订单表,一天就能新增上万条订单记录,几个月下来表的数据量就超过了一千万。我们一开始尝试做索引优化、SQL优化,效果都不太理想,查询订单详情和统计报表都特别慢。后来我们决定做水平分库,把订单数据按用户ID取模分到不同数据库里。比如我们部署了3台服务器、3个数据库,用户ID % 3 = 0 的订单放在第一个库,=1 的放第二个库,以此类推。
为了实现分片,我们使用了 MyCat 来做数据路由,旧数据也做了迁移,这样每个数据库都能分摊存储和读取压力,性能提升特别明显。像之前查某个用户近半年订单可能要几秒,现在基本都是秒级返回。
数据量**,还能提高 系统并发处理能力,是大型商城系统常用的优化策略。
23.那你之前使用过MySQL的分库分表吗?
候选人:使用过。当时业务发展太快了,比如商城的订单表,一天就能新增上万条订单记录,几个月下来表的数据量就超过了一千万。我们一开始尝试做索引优化、SQL优化,效果都不太理想,查询订单详情和统计报表都特别慢。后来我们决定做水平分库,把订单数据按用户ID取模分到不同数据库里。比如我们部署了3台服务器、3个数据库,用户ID % 3 = 0 的订单放在第一个库,=1 的放第二个库,以此类推。
为了实现分片,我们使用了 MyCat 来做数据路由,旧数据也做了迁移,这样每个数据库都能分摊存储和读取压力,性能提升特别明显。像之前查某个用户近半年订单可能要几秒,现在基本都是秒级返回。
更多推荐



所有评论(0)