当前位置: 首页 > news >正文

MySQL 进阶 面经级

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

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

文章目录

  • 分片分区
      • 分区语法
          • 范围分区 (RANGE Partitioning)
          • 列表分区(LIST Partitioning)
          • 哈希分区(HASH Partitioning)
          • 键分区(KEY Partitioning)
          • 子分区
  • 2025 美团AI面
    • 1.数据库分片sharding的概念,它有什么优势和挑战?
        • 优势
        • Sharding 挑战
    • 2. 分库分表的常见策略有哪些
        • a. 取模分片
        • b. 范围分片
        • c. 按业务
        • d. 按时间分
        • e. 混合分片
    • 3.数据库分页,千万级数据,如何解决深度分页的效率问题
        • a. 避免 OFFSET 直接跳过大量数据
        • b. 分区优化查询
        • c. 缓存分页结果
    • 4. 如果一条SQL查询变慢,你的优化步骤是什么?
        • EXPLAIN

分片分区

  • 分片 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 成为性能瓶颈

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


http://www.mrgr.cn/news/96772.html

相关文章:

  • 一起学习大语言模型-常用命令及模型介绍
  • 2023第十四届蓝桥杯大赛软件赛省赛C/C++ 大学 B 组(真题题解)(C++/Java题解)
  • 41、当你在 index.html 中引用了一个公共文件(比如 common.js),修改这个文件后,用户访问页面时仍然看到旧内容,因为浏览器缓存了旧版本
  • Kafka 4.0入门到熟练
  • 41.C++哈希6(哈希切割/分片/位图/布隆过滤器与海量数据处理场景)
  • ML 聚类算法 dbscan|| OPTICS
  • 【C++】vector常用方法总结
  • Springboot学习笔记3.28
  • JVM——模型分析、回收机制
  • 七. JAVA类和对象(二)
  • 消息中间件对比与选型指南:Kafka、ActiveMQ、RabbitMQ与RocketMQ
  • 前端界面在线excel编辑器 。node编写post接口获取文件流,使用传参替换表格内容展示、前后端一把梭。
  • LLM应用层推荐 -- 基于文档的问答tools Web UI 框架 开源向量库 -- 推荐、对比
  • 003-JMeter发起请求详解
  • Vue中将pdf文件转为图片
  • GitPython库快速应用入门
  • 【超详细】一文解决更新小米澎湃2.0后LSPose失效问题
  • 使用 Less 实现 PC 和移动端样式适配
  • pytorch模型的进阶训练和性能优化
  • uniapp -- 列表垂直方向拖拽drag组件