MySQL 进阶 面经级

会用数据库,找大厂工作是远远不够的。

本人2025美团暑期AI面试好几个MySQL场景问题不会答,已脏面评。遂在此整理学习!

文章目录

  • 分片分区
      • 分区语法
          • [范围分区 (RANGE Partitioning)](#范围分区 (RANGE Partitioning))
          • [列表分区(LIST Partitioning)](#列表分区(LIST Partitioning))
          • [哈希分区(HASH Partitioning)](#哈希分区(HASH Partitioning))
          • [键分区(KEY Partitioning)](#键分区(KEY Partitioning))
          • 子分区
  • [2025 美团AI面](#2025 美团AI面)

分片分区

  • 分片 Sharding 是跨多个物理机器,把数据拆分到不同的服务器上

  • 分区 Partitioning 是在单个数据库内部,把一张大表拆成多个物理存储的分区。

    对用户仍然表现为一张表,查询时数据库自动优化查询范围。

分区语法

PARTITION BY

范围分区 (RANGE Partitioning)
复制代码
-- 创建一个按范围分区的表
CREATE TABLE sales (
    id INT,
    sale_date DATE,
    amount DECIMAL(10, 2)
)
PARTITION BY RANGE (YEAR(sale_date)) (
    PARTITION p2020 VALUES LESS THAN (2021),
    PARTITION p2021 VALUES LESS THAN (2022),
    PARTITION p2022 VALUES LESS THAN (2023),
    PARTITION p2023 VALUES LESS THAN (2024),
    PARTITION p2024 VALUES LESS THAN (2025),
    PARTITION p_other VALUES LESS THAN MAXVALUE
);
列表分区(LIST Partitioning)

根据指定列是否为特定值,分区

复制代码
-- 创建一个按列表分区的表
CREATE TABLE products (
    id INT,
    category VARCHAR(50),
    price DECIMAL(10, 2)
)
PARTITION BY LIST (category) (
    PARTITION p_electronics VALUES IN ('Laptop', 'Smartphone', 'Tablet'),
    PARTITION p_clothing VALUES IN ('T-Shirt', 'Jeans', 'Dress'),
    PARTITION p_home VALUES IN ('Furniture', 'Appliance')
);
哈希分区(HASH Partitioning)

适用于数值类型

不强制要求主键或索引

复制代码
-- 创建一个按哈希分区的表
CREATE TABLE orders (
    id INT,
    order_date DATE,
    total_amount DECIMAL(10, 2)
)
PARTITION BY HASH (id)
PARTITIONS 4;
键分区(KEY Partitioning)

使用的 MySQL 内部的哈希函数,适用于任何数据类型(VARCHAR),允许 多个列组合 作为 KEY。

MySQL 要求分区键是主键或唯一索引

(经过分析,必要性只体现在数据分布均匀和查询效率上。)

复制代码
-- 创建一个按键分区的表
CREATE TABLE customers (
    id INT,
    name VARCHAR(100),
    email VARCHAR(100)
)
PARTITION BY KEY (id)
PARTITIONS 3;
子分区

SUBPARTITION

先分一步,再分第二步

复制代码
-- 创建一个带有子分区的表
CREATE TABLE events (
    id INT,
    event_date DATE,
    event_type VARCHAR(50)
)
PARTITION BY RANGE (YEAR(event_date))
SUBPARTITION BY HASH (MONTH(event_date))
SUBPARTITIONS 2 (
    PARTITION p2023 VALUES LESS THAN (2024),
    PARTITION p2024 VALUES LESS THAN (2025)
);

2025 美团AI面

1.数据库分片sharding的概念,它有什么优势和挑战?

我当时甚至不清楚分片啥意思------其实就是分布式数据库,将数据拆分到多个数据库节点上。

每个数据库节点存储数据的一个子集,被称为分片(Shard)。

优势
  1. 水平扩展,能够支持海量数据

  2. 提高性能:

  • 多个数据库节点可以并行处理查询和写入请求,减少单个数据库的负载。
  • 每个分片只存储部分数据,索引体积更小,提高查询效率。
  1. 隔离
    单个分片出现故障,不会影响其他分片的数据
Sharding 挑战
  1. 怎么分?
    需要选择合适的分片键(Shard Key),否则:

数据倾斜:部分分片存储的数据量过大,导致查询压力集中,影响性能。

查询跨分片:如果查询涉及多个分片(如 JOIN、GROUP BY),可能导致性能下降。

  1. 维护

随着数据增长,可能需要重新分片。数据迁移过程复杂,可能影响在线业务。

需要额外的工具监控各个分片的健康状况,防止单点瓶颈。

  1. 跨分片问题

联合只能在应用层。

跨分片事务,需要引入两阶段提交(2PC)等机制。而且要保证数据一致性。

2. 分库分表的常见策略有哪些

延续上一个问题了,,

a. 取模分片

num % 3 == 0/1/2

✅ 数据均匀

❌ 拓展困难,模数想跳转只能重新计算。

范围查询表现不佳

b. 范围分片

每10W个编号分到一个数据库中

✅ 支持数据查询,扩展方便

❌ 数据倾斜风险:可能部分连续数据访问量大,分片压力大

c. 按业务

常规,不要宽列

d. 按时间分

日志,订单等

e. 混合分片

先分用户表,再对其取模分片,再按时间分

3.数据库分页,千万级数据,如何解决深度分页的效率问题

a. 避免 OFFSET 直接跳过大量数据

假设 id 有索引,获取 id 1000000 ~ 1000020

复制代码
SELECT id, name, age FROM users 
ORDER BY id LIMIT 1000000, 20;

这里即使跳过了前100万行,仍需扫描其他列,导致类似回表的性能开销。

(除非这三列是联合索引)

利用子查询索引加速分页:

复制代码
SELECT id, name, age FROM users 
WHERE id > (SELECT id FROM users ORDER BY id LIMIT 1000000, 1)
ORDER BY id LIMIT 20;

子查询 SELECT id FROM users ORDER BY id LIMIT 1000000, 1 仅需访问主键索引(覆盖索引),无需回表。

如果 id 是递增,可以不使用 OFFSET:

复制代码
SELECT * FROM users 
WHERE id > 5000000  -- 这个值从前一页查询获取
ORDER BY id 
LIMIT 20;
b. 分区优化查询

(分区不是分片,见1.)

PARTITION BY RANGE (created_at) 指定了按 created_at 进行范围分区

CREATE ... PARTITION OF [table] FOR VALUES FROM

复制代码
CREATE TABLE users (
    id BIGINT NOT NULL,
    name VARCHAR(255),
    age INT,
    created_at TIMESTAMP,
    PRIMARY KEY (id, created_at)
) PARTITION BY RANGE (created_at);

CREATE TABLE users_2024 PARTITION OF users FOR VALUES FROM ('2024-01-01') TO ('2025-01-01');
c. 缓存分页结果

适用于只读或更新较少的数据。

CREATE ... AS

复制代码
CREATE TABLE user_pagination_cache AS
SELECT id FROM users ORDER BY id LIMIT 10000000;

4. 如果一条SQL查询变慢,你的优化步骤是什么?

保存 复现语句,看是特定查询慢还是整个库慢

EXPLAIN

EXPLAIN 关键字可用于分析 SQL 查询的执行计划,了解数据库是如何执行查询的:表的访问顺序、使用的索引、数据扫描方式

复制代码
EXPLAIN SELECT * FROM users WHERE age > 25;
  • 优化查询语句,在多表连接查询中,合理安排表的连接顺序,让数据库先连接小表,减少中间结果集的大小。

  • 避免在查询条件中使用函数或表达式,因为这可能会导致索引失效。

    -- 不好的写法,索引可能失效
    SELECT * FROM users WHERE YEAR(birth_date) = 1990;
    -- 好的写法,可使用索引
    SELECT * FROM users WHERE birth_date BETWEEN '1990-01-01' AND '1990-12-31';

  • 确保数据库的数据文件和日志文件存储在高性能的磁盘上,避免磁盘 I/O 成为性能瓶颈

  • 确保表的结构合理,避免数据冗余和过度规范化

相关推荐
王强你强2 分钟前
MySQL 高级查询:JOIN、子查询、窗口函数
数据库·mysql
草巾冒小子3 分钟前
brew 安装mysql,启动,停止,重启
数据库·mysql
用户6279947182629 分钟前
南大通用GBase 8c分布式版本gha_ctl 命令-HI参数详解
数据库
斯汤雷18 分钟前
Matlab绘图案例,设置图片大小,坐标轴比例为黄金比
数据库·人工智能·算法·matlab·信息可视化
SQLplusDB25 分钟前
Oracle 23ai Vector Search 系列之3 集成嵌入生成模型(Embedding Model)到数据库示例,以及常见错误
数据库·oracle·embedding
喝醉酒的小白1 小时前
SQL Server 可用性组自动种子设定失败问题
数据库
chem41111 小时前
Conmon lisp Demo
服务器·数据库·lisp
m0_555762901 小时前
QT 动态布局实现(待完善)
服务器·数据库·qt
孪生质数-2 小时前
SQL server 2022和SSMS的使用案例1
网络·数据库·后端·科技·架构
振鹏Dong2 小时前
MySQL 事务底层和高可用原理
数据库·mysql