SQL牛客面经八股

B+树(B+ Tree)  B+树(B+树)

定义:一种多路平衡查找树,只有叶子节点存储真实数据(如数据库表中的行记录),内部节点仅存储键值(Key)和子节点指针。

红黑树(Red-Black Tree)

定义:一种二叉搜索树,每个节点要么是红色,要么是黑色;红色节点的子节点必须是黑色(红黑性质)。插入/删除时通过左旋、右旋和变色操作调整树结构,保证树的高度不超过2*log₂(n+1)。

  1. 什么是索引?索引有哪些分类?

索引是一种用于加速数据库查询的特殊数据结构,通过在表的列上创建索引,可以显著提高数据检索速度。
索引的分类包括主键索引、唯一索引、普通索引、全文索引和组合索引。选择合适的索引类型可以优化查询性能,但过多的索引可能影响数据写入速度。

  1. Hash 索引与 BTree 索引有什么区别?

Hash 索引和 BTree 索引在实现和使用场景上有显著区别。
Hash 索引基于哈希表实现,适合等值查询,查询速度快,但不支持范围查询和排序操作;而 BTree 索引基于平衡树结构,支持等值查询、范围查询和排序操作,适合大多数查询场景。

  1. 为什么 MySQL 采用 B+ 树作为索引?

MySQL 采用 B+ 树作为索引,因为它支持高效的范围查询、顺序访问和磁盘读写优化。B+ 树的叶子节点链表结构支持顺序访问和范围查询,树的高度较低,减少了磁盘 I/O 次数,适合处理大规模数据集,且能够有效支持等值查询和范围查询。

  1. B+ 树查询数据的全过程?

B+ 树查询数据的过程从根节点开始,逐层向下遍历树结构。每个节点存储键值和指向子节点的指针,查询时根据键值大小选择合适的子节点,直到到达叶子节点。叶子节点包含所有数据记录的指针,最终通过这些指针访问实际数据。

  1. 三层 B+ 树能存多少数据?

三层 B+ 树的存储能力取决于每个节点的分支因子(即每个节点能存储的键值数)。
假设每个节点可以存储 mm 个键值,那么根节点有 mm 个子节点,第二层有 m2m2 个子节点,叶子节点有 m3m3 个数据指针。因此,三层 B+ 树可以存储 m3m3 条数据记录。具体的存储量还需根据实际的节点大小和键值大小来计算。

  1. 聚簇索引与非聚簇索引的区别?

聚簇索引与非聚簇索引的区别在于数据存储方式和访问效率

聚簇索引将数据行存储在叶子节点,数据的物理顺序与索引顺序一致,适合范围查询和排序操作;

而非聚簇索引的叶子节点存储的是数据行的指针,数据的物理顺序与索引顺序无关,适合快速查找特定值。

聚簇索引通常只能有一个,而非聚簇索引可以有多个

  1. 联合索引的存储结构与最左前缀原则

联合索引的存储结构是将多个列的值组合在一起形成一个复合键,按照字典序进行排序存储。
最左前缀原则指的是在使用联合索引时,查询条件必须从索引的最左列开始,才能有效利用索引进行加速查询。
只有满足最左前缀的查询条件,才能充分发挥联合索引的性能优势。

  1. 在 SELECT IN / 模糊查询中如何使用索引?

在 SELECT IN查询中,索引可以通过将IN列表中的值与索引列进行匹配来加速查询。

对于模糊查询,使用索引的效果取决于查询模式

如果使用前缀匹配(如LIKE 'abc%'),索引可以有效加速查询;

但如果使用通配符开头(如LIKE '%abc'),索引通常无法使用,因为需要扫描整个表。

优化模糊查询时,可以考虑使用全文索引或重构查询条件以提高性能。

  1. 建索引时需注意哪些事项?

首先,选择合适的列进行索引,优先考虑经常用于查询条件、排序和连接的列;

其次,避免在频繁更新的列上建立索引,以减少维护开销;

此外,控制索引的数量,过多的索引会影响写入性能;

同时,注意索引的选择性,选择性高的索引能更有效地过滤数据;

最后,定期分析和优化索引,以适应数据和查询模式的变化

  1. 如何评估 / 判断索引是否生效?常见索引失效场景有哪些?

评估索引是否生效需“三看”:

看执行计划是否命中索引(EXPLAIN)

看扫描行数是否骤降(rows)

看查询耗时是否锐减(性能监控)

失效常因“破坏索引结构”或“优化器弃用”(如函数计算、隐式转换、前导通配符等)

  1. 索引失效后怎么办?

当索引失效时,

首先需要分析查询语句,检查是否有不符合索引使用条件的部分,如函数操作、隐式类型转换或不满足最左前缀原则等。

其次,考虑重构查询语句,使其符合索引使用条件。

此外,可以通过分析执行计划来识别问题所在,并根据需要调整索引策略或添加新的索引

最后,定期维护和优化数据库索引,以确保其在不断变化的查询模式下保持有效。

  1. 数据库索引重构过程了解吗?

数据库索引重构是指对现有索引进行分析、优化和调整的过程,通过重建索引消除数据碎片和结构变形,恢复索引的快速导航能力。

重构过程包括:

首先,使用执行计划分析工具识别低效或未使用的索引

其次,评估索引的选择性和覆盖率,确保索引能有效过滤数据;

然后,删除冗余或影响性能的索引,添加新的索引(可选择在线或离线)以适应查询模式的变化;

最后,定期监控和维护索引,确保其在不断变化的数据库环境中保持高效。

通过索引重构,可以显著提升数据库的查询效率和整体性能。

  1. 数据库为什么使用B+树而不使用红黑树?

数据库使用 B+ 树而不使用红黑树,主要是因为 B+ 树更适合磁盘存储和范围查询。B+ 树的节点包含多个键值,减少了树的高度,从而减少了磁盘 I/O 次数,提高了查询效率。此外,B+ 树的叶子节点通过链表连接,支持高效的顺序和范围查询,而红黑树是二叉树,节点高度较高,适合内存中的快速查找,但不如 B+ 树在磁盘存储和批量数据处理上的性能优越。

  1. 数据库分页的实现方式?

数据库分页通常通过LIMIT和OFFSET子句实现,LIMIT指定返回的记录数,OFFSET指定起始位置,从而实现数据的分段提取。这种方式简单易用,但在大数据集上性能可能较差。为提高性能,可以使用基于索引的分页,通过记录上次查询的最后一个主键值来获取下一页数据,避免使用OFFSET。这种方法减少了不必要的记录扫描,提高了分页查询的效率。

  1. LIMIT 100000000,10 与 LIMIT 10 性能差异?

LIMIT 100000000,10的性能远低于LIMIT 10,因为前者需要跳过大量记录,导致更高的计算和 I/O 开销。

  1. 如何使用 EXPLAIN 分析查询?关注哪些列?

使用EXPLAIN分析查询时,关键列包括:

id(执行顺序)、

select_type(查询类型)、

table(涉及的表)、

type(访问类型,指示查询效率)、

possible_keys(可能使用的索引)、

key(实际使用的索引)、

key_len(索引长度)、

ref(索引引用)、

rows(估计读取的行数)和

Extra(额外信息,如是否使用临时表或文件排序)。

  1. COUNT(*)、COUNT(1)、COUNT(列) 有啥区别?

COUNT(*)和COUNT(1)统计所有行数,包括NULL,

而COUNT(列)只统计指定列中非NULL的行数。

  1. SQL 聚合函数有哪些?

SQL 聚合函数包括COUNT、SUM、AVG、MIN、MAX等,用于对数据集进行汇总和统计分析。

  1. WHERE 与 HAVING 的区别?

WHERE 在分组前过滤原始数据行(不可用聚合函数),

HAVING 在分组后过滤分组结果(可用聚合函数),二者执行时机和适用场景有本质差异

  1. EXISTS 与 IN 的区别?

EXISTS和IN都用于子查询,

但EXISTS通过逐行检测子查询是否存在匹配(适合外表小/内表大),

IN通过预加载子查询结果集进行匹配(适合内表小/外表大),

二者在驱动顺序、NULL处理及性能优化上存在本质差异。

  1. 谈谈 SQL 注入及防范

SQL 注入是一种通过插入恶意 SQL 代码来攻击数据库的技术,

防范措施包括使用参数化查询、输入验证和最小权限原则。

  1. 将一张表部分数据更新到另一张表的写法?

将表A的部分数据更新到表B的核心方法是使用 UPDATE JOIN 或子查询,通过关联条件锁定目标行,用源表数据覆盖目标表字段,需注意数据库语法差异及性能优化。

  1. 如何将行转成列(行列转换)?

行转列(行列转换)通常通过条件聚合(如CASE WHENMAX(IF()))或PIVOT操作实现,将多行数据按照某一字段的值展开为多列,常用于报表统计和数据透视。

  1. 表之间如何关联?

表之间的关联主要通过外键和 JOIN 操作实现,用于将多张表的数据按照某些字段进行关联和整合,常见的关联方式有内连接、左连接、右连接和全连接

  1. INNER / LEFT / RIGHT JOIN 区别?

INNER JOIN只返回两表中匹配的记录,

LEFT JOIN返回左表所有记录及其匹配的右表记录,

RIGHT JOIN返回右表所有记录及其匹配的左表记录,未匹配部分用NULL补齐。

  1. 为什么不推荐多表 JOIN?

不推荐多表JOIN是因为它可能导致复杂的查询计划、性能下降和维护困难,尤其在大数据集和不当索引情况下,会显著影响查询性能和响应时间

  1. SQL 调优常见方法有哪些?

1. 合理使用索引

创建高效索引:在查询条件、排序、分组和连接字段上建立合适的索引。

避免冗余和低效索引:定期清理无用或重复的索引,防止写入性能下降。

覆盖索引:让索引包含查询所需的所有字段,减少回表操作。

2. 优化查询语句结构

简化 SQL 语句:避免不必要的嵌套和复杂子查询。

只查需要的字段:用SELECT 字段替代SELECT *,减少数据传输。

合理使用 JOIN:避免多表复杂 JOIN,优先考虑业务需求。

3. 减少数据扫描量

加过滤条件:在 WHERE 子句中尽量多用过滤条件,减少全表扫描。

分区表/分表:将大表拆分为多个小表,提高查询效率。

使用 LIMIT:限制返回结果的数量,避免一次性拉取大量数据。

4. 利用缓存机制

数据库查询缓存:开启并合理配置数据库的查询缓存功能。

应用层缓存:对热点数据在应用层做缓存,减少数据库压力。

5. 分析执行计划

使用 EXPLAIN:分析 SQL 的执行计划,找出性能瓶颈。

根据反馈优化:根据执行计划调整索引和 SQL 结构。

  1. 如何监控并优化慢 SQL?

慢 SQL 是指执行时间较长的 SQL 查询,可能影响数据库性能。以下是监控和优化慢 SQL 的方法:

启用慢查询日志,在数据库中启用慢查询日志,记录执行时间超过指定阈值的查询。

分析查询计划使用EXPLAIN分析慢查询的执行计划,识别性能瓶颈。

优化索引为慢查询涉及的列创建或优化索引,减少全表扫描。

调整查询结构重写复杂查询,简化逻辑,减少不必要的计算。

方法:使用子查询代替嵌套查询,减少数据处理量。

优化数据库配置,调整数据库参数,如内存分配、连接池大小等。

工具:使用数据库自带的性能监控工具,分析瓶颈。

使用缓存,缓存常用查询结果,减少数据库负载。

  1. 如何高效批量插入数据?

使用批量插入语句,使用INSERT INTO ... VALUES语句一次插入多行数据。

禁用索引,在插入大量数据前暂时禁用索引,插入完成后再重建索引。

注意:确保在插入后重新启用索引。

调整事务设置将多个插入操作放在一个事务中,减少事务提交的开销。

调整网络设置在网络传输中使用批量插入,减少网络往返次数。

  1. 大表(千万级)查询 / 维护该怎么办?

索引优化为常用查询的列创建合适的索引,避免全表扫描。

注意:避免过多索引,增加维护开销。

SQL语句调优

拒绝SELECT *:明确指定所需字段,减少I/O开销。

深度分页优化:用游标替代LIMIT offset, N(如WHERE id > last_id LIMIT 10),避免扫描前N条数据。

拆分复杂查询:将大查询拆为多个小查询,减少锁竞争。

表分区,将大表按某个字段(如日期)分区,减少每次查询的数据量。

分表,将大表拆分为多个小表,按某个逻辑(如用户 ID)分割。

批量操作,在进行大数据量更新或删除时,使用批量操作减少锁定时间。

数据库配置调整调整数据库参数,如内存分配、连接池大小等,优化性能。

  1. 删除(DELETE)、截断(TRUNCATE)、丢弃(DROP)区别?

DELETE删除数据,

TRUNCATE清空数据,保留表结构

DROP删除整个表结构

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐