MySQL面试的基础知识

MySQL数据库

一、索引问题

1. 索引的定义

索引是数据库表中一列或多列的值进行排序的一种数据结构,类似于书籍的目录。

可以通过索引直接定位数据,无需全表扫描,减少I/O操作;也可以通过索引的排序结构快速找到符合条件的记录,从而显著提高数据库的查询效率。

2. 索引的原理

MySQL索引的核心原理基于树状数据结构(如 B+树)或哈希表。以下是常见索引类型的工作原理:

B + 树索引(最常用)

结构特点:

每个节点可以有多个子节点(扇出大),形成平衡的多路搜索树。

叶子节点包含实际数据或指向数据的指针,非叶子节点仅存储索引键和指针。

所有叶子节点通过指针相连,形成有序链表,支持范围查询。

工作流程:

查询时:从根节点开始,通过比较索引键快速定位到叶子节点。

插入 / 删除时:自动调整树结构保持平衡,确保查询效率稳定。

适用场景:

范围查询(如WHERE age > 20)。

排序(如ORDER BY)。

等值查询(如WHERE name = 'Alice')。

哈希索引

结构特点:

使用哈希函数将索引键映射到哈希表中,直接定位数据。

仅支持等值查询(如WHERE id = 1),不支持范围查询。

工作流程:

查询时:计算索引键的哈希值,直接访问对应槽位。

冲突处理:若多个键哈希值相同,通过链表或开放寻址解决。

适用场景:

内存表(Memory引擎)默认使用哈希索引。

缓存系统(如 Redis)中的快速查找。

3. 聚簇 索引 VS 聚簇 索引

聚簇索引

索引的叶子节点直接存储数据行(数据即索引),找到了索引就找到了需要的数据,每个表只能有一个聚集索引(通常是主键)。

示例:InnoDB 存储引擎的主键索引就是聚集索引。

非聚簇索引

索引的存储和数据的存储是分离的,查询时需先通过索引找到主键,再通过主键回表查询数据。

示例:二级索引(如普通索引)属于非聚集索引。

4. 索引优缺点

优点:

大幅提高查询速度。

减少排序和分组操作的时间。

支持唯一性约束(如UNIQUE索引)。

缺点:

占用额外存储空间。

插入 / 更新 / 删除操作变慢(需维护索引结构)。

设计不当可能导致索引失效(如使用函数或模糊查询)。

5. 索引的使用建议

创建索引的时机:

经常用于WHERE、JOIN、ORDER BY的字段。

高基数(重复值少)的字段(如用户 ID、邮箱)。

避免创建索引的情况:

频繁更新的字段。

低基数字段(如性别、状态码)。

表数据量较小(全表扫描更快)。

  1. 示例:创建索引

sql

-- 创建普通索引CREATE INDEX idx_name ON users (name);

-- 创建唯一索引CREATE UNIQUE INDEX idx_email ON users (email);

-- 创建复合索引(多列索引)CREATE INDEX idx_name_age ON users (name, age);

总结

MySQL 索引通过树状结构(如 B + 树)或哈希表实现快速数据定位,显著提升查询效率。合理设计索引需要根据业务场景权衡查询性能和维护成本,避免过度索引。理解索引的底层原理是优化数据库性能的关键。

B树索引和B+树索引的区别是什么?

B 树(B-Tree)和 B + 树(B+ Tree)是数据库索引中常用的两种数据结构,它们的主要区别体现在结构设计和应用场景上。以下是具体对比:

  1. 结构差异

B 树(B-Tree)

节点结构:每个节点包含键值(key)和数据(data),非叶子节点也可能包含数据。

叶子节点关系:叶子节点之间无指针连接,不形成有序链表。

数据分布:所有节点都可能存储数据,查询可能在非叶子节点终止。

B + 树(B+ Tree)

节点结构:非叶子节点仅存储键值和指针,数据只存在于叶子节点。

叶子节点关系:所有叶子节点通过指针相连,形成有序链表。

数据分布:数据仅存在于叶子节点,所有查询最终都要到达叶子节点。

  1. 图示对比

plaintext

B树结构示例:

3, 7

/ | \

1,2\] \[4,5,6\] \[8,9

B+树结构示例:

3, 7

/ \

1,2,3 -> 4,5,6,7,8,9 (叶子节点通过指针相连)

  1. 查询效率

B 树:

单次查询可能在非叶子节点结束,平均查询效率略高。

但每个节点存储数据,导致节点容量变小,树的高度可能更高。

B + 树:

所有查询必须到达叶子节点,单次查询效率可能略低。

叶子节点存储全部数据,节点容量更大,树的高度更低,减少 I/O 次数。

优势:支持范围查询,可通过叶子节点的链表快速遍历。

  1. 插入 / 删除操作

B 树:

插入 / 删除可能导致非叶子节点的结构调整,操作复杂度较高。

每个节点都可能存储数据,维护成本更高。

B + 树:

插入 / 删除仅在叶子节点进行,操作更简单。

叶子节点之间通过指针相连,分裂时无需调整上层节点。

  1. 应用场景

B 树:

适用于随机查询为主的场景(如文件系统索引)。

不适合范围查询,因为叶子节点无链表连接。

B + 树:

数据库索引的主流选择(如 MySQL InnoDB)。

支持高效的范围查询和排序(如ORDER BY)。

磁盘读写更友好,因为节点容量大,减少 I/O 次数。

  1. 总结对比表

|--------|-------------|-------------|
| 特性 | B 树 | B + 树 |
| 数据存储位置 | 所有节点都可能存储数据 | 仅叶子节点存储数据 |
| 叶子节点连接 | 无指针连接 | 通过链表有序连接 |
| 范围查询效率 | 低(需重复遍历树) | 高(通过链表直接遍历) |
| 节点容量 | 较小(需存储数据) | 较大(仅存储键值) |
| 适用场景 | 文件系统、随机查询 | 数据库索引、范围查询 |

为什么 MySQL 选择 B + 树?

范围查询:B + 树的叶子节点链表支持高效的范围扫描(如WHERE age BETWEEN 20 AND 30)。

磁盘友好:节点容量大,树的高度低,减少磁盘 I/O。

稳定性:插入 / 删除操作仅影响叶子节点,减少树的调整频率。

B + 树通过牺牲部分随机查询效率,换取了更稳定的插入 / 删除性能和高效的范围查询能力,更适合数据库的应用场景。

MySQL的数据类型:

一、数字类型:

1、int:整数(4字节)id/序号/自增列

2、bigint:大整数(8字节)超大计数

3、decimal(M,D):定点数(精准小数)M总位数,D小数位,精准无误差,金额/汇率。

二、字符串类型:

1、char(N):定长字符串(N为长度),短固定长度(手机号码)

2、varchar(N):变长字符串(N为最大长度),名称/地址/描述

3、text:长文本(最大65535个字符),文章内容/备注

三、日期时间类型:

1、date:日期(年月日);格式:YYYY-MM-DD;生日/下单日期

2、time:时间(时分秒);格式:HH:MM:SS;具体时间/打卡时间

3、datetime:日期+时间;格式:YYYY-MM-DD HH:MM:SS;创建时间、更新时间(最常用)

4、timestamp:时间戳,记录时间(自动更新),受时区的影响,不建议使用。

四、布尔类型:

1、BOOLEAN:TRUE/FLASE

创建表的SQL语句

CREATE TABLE `order_db`.`user_info` (

`id` int unsigned NOT NULL AUTO_INCREMENT COMMENT '主键ID(自增)',

`user_id` varchar(10) NOT NULL COMMENT '用户ID唯一索引',

`user_name` varchar(50) NOT NULL COMMENT '用户姓名',

`user_sex` char(2) DEFAULT NULL COMMENT '用户性别',

`user_phone` char(11) DEFAULT NULL COMMENT '用户手机号码,11位,可为null',

`user_age` int unsigned NOT NULL COMMENT '用户年龄(非负)',

`birthday` date DEFAULT NULL COMMENT '生日(仅年月日)',

`address` varchar(255) DEFAULT NULL COMMENT '用户地址',

`create_date` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '注册时间(默认当前时间)',

`update_date` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间(默认当前时间,更新时自动刷新)',

`flag` int NOT NULL DEFAULT '1' COMMENT '是否有效:1=有效,0=无效',

PRIMARY KEY (`id`),

UNIQUE KEY `uk_user_info_use_id` (`user_id`)

) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='用户信息表';

  • 字段的增删改的SQL,以及索引的增删的SQL

alter table user_info add column test1 varchar(10);

alter table user_info add column test2 varchar(10);

alter table user_info add column test3 varchar(10);

alter table user_info drop column test3;

create index index_user_info_create_date on user_info(create_date);

alter table user_info add index index_user_info_update_date(update_date);

  • 字符串函数

|-------------|------------|--------------------------------|------------|
| 函数 | 说明 | 示例 | 结果 |
| CONCAT() | 拼接字符串 | CONCAT('Hello', 'MySQL') | HelloMySQL |
| LENGTH() | 获取字符串长度 | length('MySQL') | 5 |
| SUBSTRING() | 截取字符串 | substring('Hello, Kitty', 1,5) | Hello |
| TRIM() | 去除字符串首尾的空格 | trim(' MySQL ') | MySQL |
| REPLACE() | 替换字符串 | replace('MySQL', 'SQL', 'DB') | MyDB |

  • jion表的关联 where和on后面关联关系的区别

左表的谓词放在where后面有效,右表的谓词放在on后面有效。

都放在on后面,因为left join的特性,左表的数据全部显示,右表过滤后再关联。

左表的谓词放在on后面,右表的谓词放在where,先过滤右表,然后左右表因为t1.id = t2.id左右表的关联关系,导致左关联关系变成了内关联关系。

左表的谓词放在where,右表的谓词放在on后面,左右表先过滤,然后再关联,显示左表过滤之后所有的数据。

左表和右表都放在where后面,左右表先过滤,然后因为t1.id = t2.id的左右表的关联关系,导致左关联关系变成了内关联关系。

  • 子查询

EXISTS的核心是判断子查询是否有结果行,只返回 TRUE/FALSE,不关心子查询的具体返回值;

EXISTS常与关联子查询配合使用,是查询 "存在性" 场景的最优选择,大数据量下性能优于IN;

NOT EXISTS是反向判断,用于查询 "不存在某类记录" 的场景,逻辑清晰且高效。

子查询的优化方法

1、优先使用join代替子查询

2、大数据量的使用exists,减少读取数据的次数。

3、在关联字段,查询字段增加索引

4、避免多层嵌套子查询

5、使用explain查看执行计划

  • 窗口函数

开窗函数使用场景

1、求某个分组下的最大/最小值/TOP n值对应信息,如年级中每个班级的第一名,大区中销售额最高城市,此处用排序函数 row_number(),需用 order by 排序。

2、对某个分组求和/个数/均值,如城市历史截至昨天累积销售额/营业天数/平均销售额,此处用sum()/count()/avg(),需用 order by 默认的定位框架。

3、相邻时间求时间差,如用户复购时间周期,此处用lag(),需用 order by 排序。

4、计算产品销售的趋势/排名/占比,以及销售目标达成分析,此处需要用到 lag()/sum()/avg()/row_number()。

  • sql优化,执行计划explain
  • 留存率问题
  • 11
相关推荐
MXsoft6181 小时前
**配置自动备份与变更告警:杜绝“黑变更”风险**
网络·数据库
骑士雄师1 小时前
19.3 langgraph的工作节点和路由函数
java·前端·数据库
梓䈑1 小时前
C++ 接入 SQLite 数据库:环境搭建、API 详解 与 两种执行方式对比
数据库·c++·sqlite
曹牧1 小时前
Oracle:CHR
数据库·oracle
TechWayfarer1 小时前
IP精准定位服务在保险行业的接入实践:区域需求洞察与精准服务
数据库·python·tcp/ip·flask
KKKlucifer1 小时前
数据分类分级产品排名解析:场景定制、规则联动、增量更新成核心能力
大数据·数据库·人工智能
minji...1 小时前
MySQL数据库 (七) MySQL表的基本查询(上),insert、replace、select、where、order by
数据库·mysql·select·replace·insert·order by·where
金融RPA机器人丨实在智能1 小时前
数据库运维Agent比价指南:国产自研产品适配国产数据库兼容性更好吗?
运维·数据库·人工智能·ai
IT策士1 小时前
Redis 从入门到精通:持久化RDB 与 AOF
数据库·redis·缓存
gerrywhu2 小时前
【应用实践】PostGIS实现NDVI计算与植被覆盖分级统计分析-以武汉市2025年为例
数据库·postgis·栅格数据分析·st_mapalgebra·ndvi计算·植被覆盖分级统计·植被覆盖计算