MySQL 面试题系列(二)

在这里插入图片描述

目录

      • 1: SQL 中常见的 JOIN 类型有哪些?请分别说明其连接逻辑和适用场景。
      • 2: UNION 和 UNION ALL 有什么区别?它们各自的适用场景是什么?
      • 3: 什么是视图 (View)?它的作用和优缺点是什么?
      • 4: 什么是索引 (Index)?它的作用是什么?MySQL 中有哪些常见的索引类型?
      • 5: 索引的优缺点是什么?在什么情况下适合创建索引,什么情况下不适合?
      • 6: 什么是事务 (Transaction)?及其四大特性 (ACID) 的具体含义是什么?
      • 7: 事务的隔离级别有哪些?每种隔离级别解决了哪些并发问题?
      • 8: MySQL 存储引擎 InnoDB 和 MyISAM 的主要区别是什么?它们各自的适用场景是什么?
      • 9: SQL 注入是什么?如何防止 SQL 注入攻击?
      • 10: 什么是数据库范式 (Normal Forms)?请简述 1NF, 2NF, 3NF 的概念和目的。


1: SQL 中常见的 JOIN 类型有哪些?请分别说明其连接逻辑和适用场景。

重点讲解
JOIN 子句用于根据两个或多个表中的相关列,将这些表的行组合起来。

  1. INNER JOIN (内连接)

    • 逻辑:只返回两个表中都存在匹配关系的行。
    • 特点:匹配失败的行不出现在结果集中。
    • 场景:查询需要同时满足两个表关联条件的数据,如查询有订单的用户信息。
    • 示例
      SELECT u.username, o.order_id
      FROM users u
      INNER JOIN orders o ON u.id = o.user_id;
      
  2. LEFT JOIN (左连接,或 LEFT OUTER JOIN)

    • 逻辑:返回左表中的所有行,以及右表中与左表匹配的行。如果右表中没有匹配,则右表列显示 NULL
    • 特点:以左表为基准,保留左表所有数据。
    • 场景:查询某表的所有数据,并尝试关联另一表的数据,例如查询所有用户及其订单信息(即使有些用户没有订单)。
    • 示例
      SELECT u.username, o.order_id
      FROM users u
      LEFT JOIN orders o ON u.id = o.user_id;
      
  3. RIGHT JOIN (右连接,或 RIGHT OUTER JOIN)

    • 逻辑:返回右表中的所有行,以及左表中与右表匹配的行。如果左表中没有匹配,则左表列显示 NULL
    • 特点:以右表为基准,保留右表所有数据。
    • 场景:查询第二表的所有数据,并尝试关联第一表的数据。在实际中,RIGHT JOIN 通常可以用 LEFT JOIN 调换左右表位置来替代。
    • 示例
      SELECT u.username, o.order_id
      FROM users u
      RIGHT JOIN orders o ON u.id = o.user_id;
      
  4. FULL JOIN (全连接,或 FULL OUTER JOIN)

    • 逻辑:返回左表和右表中的所有行。如果左表中没有匹配的右表行,右表列显示 NULL;如果右表中没有匹配的左表行,左表列显示 NULL
    • 特点:合并所有数据,不强制匹配。
    • 场景:需要查看两个表中所有可能的数据组合,即使没有直接关联。MySQL 目前不支持 FULL OUTER JOIN 语法,通常通过 LEFT JOINRIGHT JOINUNION 组合来实现。
    • 模拟示例 (MySQL)
      SELECT u.username, o.order_id
      FROM users u LEFT JOIN orders o ON u.id = o.user_id
      UNION
      SELECT u.username, o.order_id
      FROM users u RIGHT JOIN orders o ON u.id = o.user_id
      WHERE u.id IS NULL; -- 排除左连接中已包含的匹配项
      

核心对比

  • INNER JOIN:取交集。
  • LEFT JOIN:保留左表所有,右表不足补 NULL
  • RIGHT JOIN:保留右表所有,左表不足补 NULL
  • FULL JOIN:保留两表所有,不足互补 NULL

实践建议

  • 明确连接条件 (ON),避免笛卡尔积。
  • 根据业务需求选择合适的 JOIN 类型。LEFT JOININNER JOIN 是最常用的。
  • JOIN 列建立索引是性能优化的关键。

2: UNION 和 UNION ALL 有什么区别?它们各自的适用场景是什么?

重点讲解
UNIONUNION ALL 都用于合并两个或多个 SELECT 语句的结果集。

  1. UNION

    • 逻辑:合并结果集,并自动去除重复行
    • 特点:会进行去重操作,因此性能开销相对较大。
    • 场景:当你需要合并来自不同表或不同查询条件的结果,并且确保结果集中没有重复项时使用。例如,获取两个表中所有不同的用户ID。
    • 示例
      SELECT city FROM customers
      UNION
      SELECT city FROM suppliers; -- 如果customers和suppliers都有 'New York',结果中只会出现一次
      
  2. UNION ALL

    • 逻辑:合并结果集,保留所有行,包括重复行
    • 特点:不进行去重操作,因此性能开销较小,效率更高。
    • 场景:当你确信结果集中不会有重复行,或者即使有重复行也需要全部保留时使用。例如,从不同分区或历史表中合并日志数据。
    • 示例
      SELECT city FROM customers
      UNION ALL
      SELECT city FROM suppliers; -- 如果customers和suppliers都有 'New York',结果中会根据原始表各出现一次
      

核心对比

  • UNION:去重,性能开销大。
  • UNION ALL:不去重,性能开销小。

使用要求

  • 所有 SELECT 语句中的列数必须相同。
  • 对应列的数据类型必须兼容。
  • 列的顺序通常要一致。

实践建议

  • 优先使用 UNION ALL:除非你明确需要去除重复行,否则为了性能考虑,总是优先选择 UNION ALL
  • 在Java应用中,当需要合并不同业务逻辑下的数据列表时,可以考虑使用 UNION ALL 在数据库层面直接获取结果,减少应用层的合并和去重逻辑。

3: 什么是视图 (View)?它的作用和优缺点是什么?

重点讲解

定义:视图是一个虚拟表,其内容由查询定义。它不存储实际的数据,而是存储查询语句。每次查询视图时,都会执行其定义中的SQL查询来获取数据。

作用

  1. 简化复杂查询:将一个复杂的 JOIN 或子查询封装成一个简单的视图,用户可以直接查询视图而无需了解底层表的复杂结构。
  2. 数据安全和权限控制:可以只暴露部分列或行给特定用户,从而限制用户访问底层敏感数据,提高安全性。用户只能查询视图中定义的数据,而不是整个表。
  3. 数据抽象和逻辑独立性:当底层表的结构发生变化时,如果视图定义不变,基于视图的应用程序通常不需要修改。视图提供了一个稳定的接口。
  4. 提供自定义数据展示:将不同表的数据逻辑上整合,以满足特定业务需求的数据展示。

优点

  • 简化SQL操作:用户无需编写复杂SQL,直接查询视图即可。
  • 提高安全性:精细化权限管理,只授权视图访问权限。
  • 数据逻辑独立性:对基表的修改可能不影响视图用户。
  • 提高可维护性:复杂逻辑集中在视图定义中。

缺点

  • 性能开销:每次查询视图都会执行底层的SQL,如果视图定义复杂,可能会影响查询性能。尤其是嵌套视图会层层解析。
  • DML操作限制:某些复杂的视图(如包含 GROUP BYUNIONDISTINCT 或多表 JOIN 的视图)可能不支持 INSERT, UPDATE, DELETE 操作。
  • 难以调试:当视图查询出现性能问题时,排查底层SQL可能比较复杂。
  • 维护成本:如果基表结构频繁变化,可能需要同步更新视图定义。

示例

-- 创建一个视图,显示活跃用户的用户名、邮箱和创建时间
CREATE VIEW active_users_view AS
SELECT username, email, created_at
FROM users
WHERE status = 1;-- 查询视图 (如同查询普通表)
SELECT username, email FROM active_users_view WHERE created_at > '2023-01-01';

实践建议

  • 主要用于复杂的查询简化和安全控制。
  • 对于性能敏感的场景,应谨慎使用复杂视图,或考虑将视图结果定期物化到实际表中。
  • 在Java应用中,视图常用于报表统计和权限隔离。

4: 什么是索引 (Index)?它的作用是什么?MySQL 中有哪些常见的索引类型?

重点讲解

定义:索引是一种特殊的文件(或数据结构),它存储了表中特定列的值,并对这些值进行排序,以加快查询速度。它类似于书籍的目录。

作用

  1. 显著提高数据检索速度:通过快速定位到包含查询条件的数据行,避免全表扫描。
  2. 加快 ORDER BYGROUP BY 操作:索引中的数据是有序的,可以直接用于排序和分组,减少额外的排序开销。
  3. 保证数据完整性:如 PRIMARY KEYUNIQUE 约束,它们底层都是通过唯一索引来实现的。

常见的索引类型

  1. PRIMARY KEY (主键索引)

    • 特点:一个表只能有一个,值必须唯一且非空。MySQL会自动为主键创建聚集索引(InnoDB)。
    • 作用:唯一标识记录,是检索最快的方式。
  2. UNIQUE INDEX (唯一索引)

    • 特点:索引列的值必须唯一,但允许有多个 NULL 值(每个 NULL 被视为不同的值)。
    • 作用:保证数据唯一性,并提高检索速度。
  3. NORMAL INDEX (普通索引 / 非唯一索引)

    • 特点:最基本的索引,没有任何限制,允许重复值。
    • 作用:提高查询效率。
  4. FULLTEXT INDEX (全文索引)

    • 特点:用于对文本内容进行模糊匹配搜索,如文章标题、新闻内容。
    • 作用:优化文本搜索性能。传统 LIKE '%keyword%' 无法使用普通索引,但全文索引可以。
    • 引擎限制:MyISAM 和 InnoDB(MySQL 5.6+)支持。
  5. COMPOSITE INDEX (复合索引 / 联合索引)

    • 特点:在多个列上创建的索引,遵循“最左前缀原则”。
    • 作用:当查询条件包含复合索引的左边列时,索引才能生效。
    • 示例INDEX (col1, col2, col3),查询 WHERE col1=?WHERE col1=? AND col2=? 会使用到索引,但 WHERE col2=? 则不会。

InnoDB 存储引擎的索引实现

  • 聚集索引 (Clustered Index):InnoDB表的数据是依据主键聚集存储的。聚集索引的叶子节点存储的就是整行记录。每个表只能有一个聚集索引(通常就是主键)。
  • 辅助索引 (Secondary Index / 非聚集索引):叶子节点不存储整行数据,而是存储指向对应行主键值的指针。通过辅助索引查询数据时,需要先查到主键,再通过主键到聚集索引中查找整行数据(这个过程称为回表)。

示例

-- 创建普通索引
CREATE INDEX idx_username ON users (username);-- 创建唯一索引
CREATE UNIQUE INDEX uk_email ON users (email);-- 创建复合索引
CREATE INDEX idx_category_price ON products (category, price);-- 创建全文索引
CREATE FULLTEXT INDEX ft_name_description ON articles (title, content);

5: 索引的优缺点是什么?在什么情况下适合创建索引,什么情况下不适合?

重点讲解

优点

  1. 大大提高数据检索速度:这是索引最核心和最重要的优点,能将全表扫描变为快速定位。
  2. 加快排序和分组操作:当 ORDER BYGROUP BY 子句中的列有索引时,可以避免额外的排序开销。
  3. 约束数据完整性:主键和唯一索引强制列值的唯一性。
  4. 提高JOIN操作的效率:连接列上有索引可以显著加速关联查询。

缺点

  1. 占用磁盘空间:索引本身是数据结构,需要额外的存储空间。
  2. 降低DML操作性能:当对表进行 INSERT, UPDATE, DELETE 操作时,除了修改数据本身,还需要同时更新索引,这会增加维护成本和时间。
  3. 性能选择开销:MySQL在处理查询时,需要评估是否使用索引以及使用哪个索引,这本身也有成本。

适合创建索引的场景

  1. 在大表上经常进行查询且 WHERE 条件中频繁使用的列:如用户ID、订单号、商品名称。
  2. 作为主键的列:强制唯一性,并提供最快的查找。
  3. 需要在 JOIN 子句中连接的列:加快表之间的连接速度。
  4. ORDER BYGROUP BY 子句中频繁使用的列:提高排序和分组效率。
  5. 筛选选择性高的列:即列中不同值的数量很多(重复值少)。例如,性别这种只有两三个值的列选择性很低,不适合单独建立索引。
  6. 需要使用 DISTINCT 关键字的列:索引可以帮助实现快速去重。

不适合创建索引的场景

  1. 表的数据量很小:全表扫描可能比使用索引更快或差不多。
  2. 经常进行 INSERT, UPDATE, DELETE 操作的表:索引维护成本高,可能抵消查询带来的好处。
  3. 列中都是重复值,选择性很低:例如性别、布尔值类型。索引无法有效缩小搜索范围。
  4. 不常在 WHEREORDER BYGROUP BYJOIN 中使用的列:建立了也用不上,白白增加存储和维护成本。
  5. 数据类型是大文本 (如 TEXT, BLOB) 的列:虽然可以创建前缀索引,但通常不直接对整个列创建,或者考虑全文索引。
  6. 过多的索引:每个索引都会增加写操作的开销和存储空间,过多的索引可能适得其反,导致优化器选择困难。

实践建议

  • "空间换时间"的策略:用磁盘空间和写操作性能的牺牲来换取查询性能的提升。
  • 平衡原则:根据实际业务的读写比例来决定是否创建索引。读操作远多于写操作的表更适合索引。
  • 定期审查和优化:通过 EXPLAIN 分析SQL语句,检查索引使用情况,删除无效或冗余索引。
  • 复合索引的“最左前缀原则”:优化索引设计的重要依据。

6: 什么是事务 (Transaction)?及其四大特性 (ACID) 的具体含义是什么?

重点讲解

定义:事务是一个操作序列,这些操作被视为一个逻辑工作单元。它要么全部成功提交(Commit),要么全部失败回滚(Rollback)。

四大特性 (ACID)

  1. 原子性 (Atomicity)

    • 含义:事务是一个不可分割的最小工作单元,其中的所有操作要么全部完成,要么全部不完成。如果事务中的任何一个操作失败,那么整个事务都会被回滚到事务开始前的状态,已完成的操作也会被撤销。
    • 例子:银行转账,从A账户扣钱和给B账户加钱必须同时成功或同时失败。如果扣钱成功但加钱失败,则扣钱操作也应回滚。
  2. 一致性 (Consistency)

    • 含义:事务执行前后,数据库从一个合法状态(consistent state)转换到另一个合法状态。这意味着事务必须遵守所有的预定义规则和约束(如主键唯一性、外键参照完整性、CHECK约束等)。
    • 例子:转账前后,总金额不变;插入数据后,表的主键仍然是唯一的。
  3. 隔离性 (Isolation)

    • 含义:并发执行的各个事务之间互不干扰,一个事务的中间状态对其他事务是不可见的。从并发事务分离的角度看,就好像各个事务是按顺序(串行)执行的。
    • 例子:A、B两人同时查询银行账户余额,无论他们查询的顺序如何,他们看到的数据都应该是事务开始时或结束时的有效状态,而不是某个事务执行一半的中间状态。
  4. 持久性 (Durability)

    • 含义:一旦事务成功提交,其对数据库数据的改变就是永久性的,即使系统发生故障(如电源中断、系统崩溃),这些改变也不会丢失。
    • 例子:银行转账成功并提交后,即使银行系统立即崩溃,转账记录依然存在,不会丢失。通常通过写入日志文件(redo log)和数据文件来保证。

实践建议

  • 理解ACID特性是正确设计和实现数据库业务逻辑的基础。
  • 在Java应用中,通常通过Spring的 @Transactional 注解或手动管理事务来确保ACID特性,特别是A, C, D。隔离性则通过数据库的隔离级别和应用层的锁机制来保证。

7: 事务的隔离级别有哪些?每种隔离级别解决了哪些并发问题?

重点讲解

事务的隔离级别定义了多个并发事务同时访问相同数据时,一个事务对另一个事务可见的程度,以及可能产生的并发问题。ANSI/ISO SQL标准定义了四种隔离级别。

并发问题

  1. 脏读 (Dirty Read):一个事务读取了另一个事务尚未提交的数据。如果后者回滚,则前者读取的数据是无效的。
  2. 不可重复读 (Non-Repeatable Read):一个事务在不同时间读取同一数据,但两次读取的结果有所不同,因为另一个已提交的事务修改了该数据。
  3. 幻读 (Phantom Read):一个事务在不同时间查询同一范围的数据,但两次查询结果的行数不同,因为另一个已提交的事务插入或删除了该范围内的行。

四种隔离级别

  1. READ UNCOMMITTED (读未提交)

    • 特点:最低隔离级别。允许读取其他事务尚未提交的数据。
    • 解决问题:无(所有并发问题都可能发生)。
    • 可能发生:脏读、不可重复读、幻读。
    • 性能:最高。
    • 适用场景:极少在生产环境使用,因为数据一致性极差。
  2. READ COMMITTED (读已提交)

    • 特点:只能读取其他事务已提交的数据。
    • 解决问题:解决了脏读问题。
    • 可能发生:不可重复读、幻读。
    • 性能:较高。
    • 适用场景:大多数数据库(如Oracle、SQL Server的默认隔离级别)的默认选择,但在MySQL中不是。可以接受事务内多次查询结果不一致的场景。
  3. REPEATABLE READ (可重复读)

    • 特点:保证在一个事务中,多次读取同一数据(包括范围查询),结果始终一致。它通过**MVCC(多版本并发控制)**实现。
    • 解决问题:解决了脏读不可重复读问题。
    • 可能发生幻读(在严格意义的标准中仍可能,但在MySQL的InnoDB引擎中,通过Next-Key Locks也解决了幻读)。
    • 性能:中等。
    • 适用场景MySQL InnoDB 存储引擎的默认隔离级别。适用于对数据一致性要求较高,且能接受并发插入/删除操作导致幻读的场景(如果不是InnoDB的Next-Key Lock)。对于InnoDB,此级别已足够安全。
  4. SERIALIZABLE (串行化)

    • 特点:最高隔离级别。所有事务都像串行执行一样,彻底避免所有并发问题。通常通过对读写操作加锁来实现。
    • 解决问题:解决了脏读不可重复读幻读所有并发问题。
    • 可能发生:无。
    • 性能:最低(并发性最差),因为可能导致大量的超时和锁竞争。
    • 适用场景:对数据一致性要求极高,且并发量极低的场景。极少在生产环境中使用。

MySQL InnoDB 对幻读的解决
REPEATABLE READ 隔离级别下,InnoDB通过间隙锁 (Gap Locks)Next-Key Locks(记录锁+间隙锁的组合)来防止幻读的发生。当事务执行范围查询时,不仅锁定存在的记录,还会锁定记录之间的“间隙”,防止其他事务在此间隙插入新数据。

实践建议

  • 理解默认级别:了解你使用的数据库引擎的默认隔离级别(MySQL InnoDB是REPEATABLE READ)。
  • 根据需求选择:大多数Web应用使用 READ COMMITTEDREPEATABLE READ 就足够。READ UNCOMMITTEDSERIALIZABLE 应谨慎使用。
  • Spring Boot/Cloud 默认:Java应用通过Spring管理事务时,默认隔离级别通常取决于数据库,但也可以在 @Transactional 中显式指定。

8: MySQL 存储引擎 InnoDB 和 MyISAM 的主要区别是什么?它们各自的适用场景是什么?

重点讲解

MySQL 拥有多种存储引擎,最常用的是 InnoDB 和 MyISAM。它们在特性、性能和适用场景上存在显著差异。

特性InnoDBMyISAM
事务支持支持 (ACID)不支持
行级锁支持,提高了并发性能不支持,只有表级锁
外键支持支持,维护参照完整性不支持
B树索引聚集索引 (数据即索引),辅助索引存主键非聚集索引 (索引和数据文件分离)
全文本搜索MySQL 5.6+ 支持早有支持
表崩溃恢复支持 (通过 redo/undo log)不支持,容易损坏,恢复困难
MVCC支持 (多版本并发控制)不支持
缓冲池缓存数据和索引,大量内存使用只有索引缓存,数据依赖OS缓存
表空间既可以存放在共享表空间,也可以独立文件存储每张表存储在独立的 .MYD (数据) 和 .MYI (索引) 文件
计数(COUNT(*) )需要全表扫描有一个计数器,SELECT COUNT(*) 效率高

适用场景

  1. InnoDB (推荐)

    • 适用场景
      • 绝大多数OLTP (联机事务处理) 应用:需要事务支持、高并发读写、数据完整性(外键)。
      • 对数据一致性、完整性有严格要求的业务,如电商订单、金融交易、在线支付等。
      • 需要灾难恢复能力、支持行级锁以提高并发的场景。
    • 总结:默认且首选的存储引擎,适用于需要高并发、事务和数据安全性的场景。
  2. MyISAM

    • 适用场景
      • 读密集型应用:表很少有写操作,并且以查找和浏览为主。
      • 对事务、数据完整性要求不高,例如日志表、非关键应用的统计数据表。
      • 一些早期或特殊场景的全文本搜索。
      • SELECT COUNT(*) 性能至关重要的场景。
    • 总结:在现代应用中已基本被淘汰,由于不支持事务和行级锁,并发性能差,恢复性差。仅在极少数特殊读密集型场景(如早期CMS应用的流量统计)还可能被考虑。

实践建议

  • 默认使用 InnoDB:除非有非常明确的理由和考量,否则都应该选择 InnoDB。
  • 在Java Web应用开发中,几乎总是使用 InnoDB。Spring事务管理、JPA/Hibernate等都严重依赖事务特性。

9: SQL 注入是什么?如何防止 SQL 注入攻击?

重点讲解

SQL 注入 (SQL Injection)

  • 定义:SQL 注入是一种代码注入技术,攻击者通过在Web表单或URL参数中输入恶意的SQL命令,欺骗数据库服务器执行非预期的操作。
  • 危害
    • 绕过身份验证,以管理员身份登录系统。
    • 窃取、修改或删除数据库中的敏感数据。
    • 获取数据库结构信息。
    • 执行系统命令(在某些配置下),完全控制服务器。

攻击原理
当应用程序将用户输入直接拼接成SQL语句,并且没有对输入进行适当验证和转义时,攻击者可以通过构造特殊的输入字符串改变原始SQL语句的执行逻辑

例如,原始SQL:SELECT * FROM users WHERE username = 'admin' AND password = 'password';
攻击者输入 username = ' OR 1=1 --
拼接后:SELECT * FROM users WHERE username = '' OR 1=1 --' AND password = 'password';
其中 -- 是SQL注释符,' AND password = 'password' 被注释掉,OR 1=1 永远为真,导致无需密码即可登录。

如何防止 SQL 注入攻击

  1. 使用预编译语句 (Prepared Statements) 和参数化查询 (Parameterized Queries)(首选且最重要)

    • 原理:预编译语句将SQL语句的结构与用户输入的数据分开。数据库会先编译SQL语句的骨架,然后将用户输入作为参数传入,而不是作为SQL代码的一部分进行解析。这样,无论用户输入什么,都会被视为普通数据值,而不会影响SQL语句本身的结构。
    • 实现
      • JDBCPreparedStatement
      • ORM框架 (如 Hibernate, MyBatis):它们内部通常就是使用预编译语句,或提供了参数化的API。
    • 示例 (JDBC)
      String sql = "SELECT * FROM users WHERE username = ? AND password = ?";
      try (PreparedStatement stmt = connection.prepareStatement(sql)) {stmt.setString(1, username);stmt.setString(2, password);try (ResultSet rs = stmt.executeQuery()) {// ... 处理结果}
      }
      
  2. 严格的用户输入验证和过滤

    • 原理:在接收用户输入时,对数据的类型、长度、格式、内容进行严格的检查。只允许合法字符,禁止特殊字符。
    • 实现
      • 白名单验证:只允许预期的数据格式(如数字、字母,不允许特殊符号)。
      • 黑名单过滤(不推荐作为唯一手段):过滤掉常见的SQL关键字和特殊字符(如 ', --, ;, OR, AND 等),但黑名单容易被绕过。
    • 注意:这是一种辅助手段,不能替代预编译语句。
  3. 最小权限原则 (Least Privilege)

    • 原理:数据库用户应该只拥有执行其任务所必需的最小权限。不要使用 root 或具有 ALL PRIVILEGES 的用户账户连接应用程序。
    • 实现:为应用创建独立的数据库用户,并只授予 SELECT, INSERT, UPDATE, DELETE 等所需权限,禁止 DROP TABLE, GRANT 等高危权限。
  4. 错误信息隐藏

    • 原理:不要在生产环境中显示详细的数据库错误信息给用户。攻击者可以利用这些信息来推断数据库的结构和漏洞。
    • 实现:捕获异常,显示通用的错误消息,并将详细错误记录在日志文件中。

实践建议

  • SQL注入是后端安全最常见的也是最危险的漏洞之一PreparedStatement 是防止其最有效和最直接的方法,必须时刻牢记并使用
  • 结合输入验证、最小权限原则和错误信息隐藏,构建多层次的防御体系。

10: 什么是数据库范式 (Normal Forms)?请简述 1NF, 2NF, 3NF 的概念和目的。

重点讲解

定义:数据库范式是关系型数据库设计的一组规则,旨在减少数据冗余,消除异常数据,并确保数据完整性。主要有第一范式(1NF)、第二范式(2NF)、第三范式(3NF)等。

目的

  • 减少数据冗余:避免相同数据在多处存储,节省空间。
  • 消除更新异常:在更新数据时,只需更新一处。
  • 消除插入异常:无需插入不相关的数据即可插入某条数据。
  • 消除删除异常:删除一条数据不会意外删除其他相关数据。
  • 提高数据完整性:通过规范化,使得数据保持一致和准确。
  1. 第一范式 (1NF - First Normal Form)

    • 概念:要求数据库表中的所有列都是原子性的,即不可再分。每个列都不能包含复合值或多值。
    • 目的:确保每个字段的值都是单一的、不可分割的最小单元。
    • 示例 (不符合1NF)
      OrderIDItemDetails
      1“Pen:10, Paper:20”
    • 示例 (符合1NF)
      OrderIDItemNameQuantity
      1Pen10
      1Paper20
  2. 第二范式 (2NF - Second Normal Form)

    • 概念
      1. 先满足1NF
      2. 非主键列必须完全依赖于整个主键,而不是主键的某个部分。
    • 目的:消除部分函数依赖,进一步减少冗余。通常当主键是复合主键时才需要考虑2NF。
    • 示例 (不符合2NF)
      OrderDetails (OrderID, ProductID, ProductName, Quantity)
      • 复合主键:(OrderID, ProductID)
      • ProductName 依赖于 ProductID (主键的一部分),而不是整个复合主键。这就是部分函数依赖。
    • 示例 (符合2NF):拆分成两个表
      Orders (OrderID, ...)
      OrderItems (OrderID, ProductID, Quantity)
      Products (ProductID, ProductName, ...)
  3. 第三范式 (3NF - Third Normal Form)

    • 概念
      1. 先满足2NF
      2. 非主键列之间不存在传递函数依赖。也就是说,非主键列不能依赖于另一个非主键列。
    • 目的:消除传递函数依赖,彻底消除冗余。
    • 示例 (不符合3NF)
      Employees (EmployeeID, EmployeeName, DepartmentID, DepartmentName)
      • 主键:EmployeeID
      • DepartmentName 依赖于 DepartmentID,而 DepartmentID 又依赖于 EmployeeID
        -> EmployeeID -> DepartmentID -> DepartmentName (传递依赖)
    • 示例 (符合3NF):拆分成两个表
      Employees (EmployeeID, EmployeeName, DepartmentID)
      Departments (DepartmentID, DepartmentName)

反范式化 (Denormalization)
虽然范式化是数据库设计的重要原则,但在实际应用中,为了提高查询性能,有时会刻意违反范式规则,进行反范式化。例如,在订单表中冗余存储商品名称,以避免查询时频繁 JOIN 商品表。这通常是“以空间换时间”的优化策略,但会增加数据一致性的维护成本。

实践建议

  • 在设计数据库时,通常建议至少满足 3NF
  • 理解范式有助于设计出清晰、高效、易于维护的数据库结构。
  • 过度范式化(如BNCF或更高级范式)可能导致表过多,JOIN 操作频繁,反而降低查询性能。实际工作中,通常在满足3NF的基础上,根据业务需求和性能瓶颈考虑适当的反范式化。
  • 在Java应用中,ORM框架(如Hibernate)会自动处理多表关联,减轻了部分范式化带来的复杂性。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/web/94447.shtml
繁体地址,请注明出处:http://hk.pswp.cn/web/94447.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

PostgreSQL诊断系列(2/6):锁问题排查全攻略——揪出“阻塞元凶”

🔗 接上一篇《PostgreSQL全方位体检指南》,今天我们深入数据库的“神经系统”——锁机制,解决最令人头疼的“卡顿”问题。 你是否经历过: 某个SQL执行着就不动了?应用界面卡在“加载中”?UPDATE 语句迟迟不…

crc16是什么算法

核心概念​CRC16​ 是一种循环冗余校验算法,属于哈希函数的一种。它的核心目的是检测数据的错误,通常用于数字网络和存储设备中,来验证数据在传输或存储后是否依然完整、无误。你可以把它想象成一个数据的“指纹”或“摘要”。发送方计算出一…

Day8--HOT100--160. 相交链表,206. 反转链表,234. 回文链表,876. 链表的中间结点

Day8–HOT100–160. 相交链表,206. 反转链表,234. 回文链表,876. 链表的中间结点 每日刷题系列。今天的题目是力扣HOT100题单。 链表题目。 160. 相交链表 思路【我】: 1,计算链表长度 2,令A为较短链&am…

Rust面试题及详细答案120道(58-65)-- 集合类型

《前后端面试题》专栏集合了前后端各个知识模块的面试题,包括html,javascript,css,vue,react,java,Openlayers,leaflet,cesium,mapboxGL,threejs&…

Horse3D游戏引擎研发笔记(八):在QtOpenGL环境下,按需加载彩虹四边形的顶点属性 (Unity、Unreal Engine、Three.js与Godot)

在上一篇博客中,我们探讨了如何在QtOpenGL环境下使用改进的Uniform变量管理方式绘制多彩四边形。本文将延续这一主题,深入探讨如何在QtOpenGL环境下按需加载彩虹四边形的顶点属性。这一功能是Horse3D引擎渲染系统的重要组成部分,旨在实现灵活…

模块化设计+微米级精度,GelSight Modulus 触觉型3D轮廓仪深入检测“盲区”

当航空航天工程师在精密舱体中搜寻微米级缺陷,汽车检查员在车间复杂结构里排查隐患,能源领域创新者尝试突破检测边界时,深耕视触觉 3D 显微技术的企业——GelSight,正以全新研发的GelSight Modulus触觉型3D轮廓仪(简称…

Pytorch安装详细步骤

第一步:检查显卡支持的的CUDA版本 1.打开NVIDIA控制面板 首先鼠标右击桌面-显示更多选项-NVIDIA控制面板-点击弹出界面右上角的(系统信息)-点击弹出界面的(组件) 2.查看驱动版本 打开系统信息 点击组件,查看 以观测到红色方框内的信息可以看到(NVIDIA CUDA 13.0.…

2025职场进阶:低门槛技能实用手册

每到年初,都会有人问:如果只能投入有限的时间与预算,先考哪一两本证书更划算?本文把近两年的岗位需求、学习可获得性与花费周期做了综合权衡,给出一个以“先提升通用能力,再叠加行业资质”为主线的组合方案…

SDC命令详解:使用set_timing_derate命令进行约束

相关阅读 SDC命令详解https://blog.csdn.net/weixin_45791458/category_12931432.html?spm1001.2014.3001.5482 目录 指定降额比例 指定降额对象列表/集合 指定沿 指定最大、最小条件 指定早、晚条件 指定路径的类型 指定降额类型 指定约束 指定增量 写在最后 由于制造…

C++语言程序设计——03 进制ASCII码

目录一、进制表示与转换(一)不同进制表示(二)进制转换方法二、ASCII 码(一)ASCII 码表(二)ASCII 码转换(三)大小写英文字母转换【总结:如何记忆AS…

AtCoder Beginner Contest 420-Toggle Maze

题目描述 有一个 H行 W 列的网格。用 (i,j) 表示位于第 i 行(从上往下数)第 j 列(从左往右数)的格子。每个格子的状态用字符 Ai,j表示,含义如下: . :空格子。 #’ :障碍格子。 S &am…

20、DMA----释放CPU压力,加快传输

1、DMA介绍DMA,全称为:Direct Memory Access,即直接存储器访问。DMA传输方式无需CPU直接控制传输,也没有中断处理方式那样保留现场和恢复现场的过程,通过硬件为RAM与I/O设备开辟一条直接传送数据的通路,能使…

深入OpenHarmony OTA硬核升级

技术背景 OpenHarmony OTA(Over-The-Air)升级子系统为设备提供了远程升级能力,通过统一的升级接口屏蔽底层芯片差异,支持轻量系统、小型系统和标准系统的全量升级、差分升级和变分区升级。 核心特性 跨系统支持:覆盖轻量系统(Hi3861)、小型系统(Hi3516DV300)、标准系…

华为iVS1800接入SVMSPro平台

华为iVS1800接入SVMSPro平台 ** 华为好望Huawei HolosensIVS1800智能视频云平台采用首款昇腾310加持的嵌入式系统智能微边缘,独俱普惠AI鸿力。一台融合存储、计算、检索功能,满足小型园区、社区、银行网点、超市等场景安防需求,小机大智。 …

《异形战机2》v2.0.4数字豪华版,3D横版射击再临,机体武器海量升级

[游戏名称]: 《异形战机2》v2.0.4数字豪华版 [软件大小]: 17.7 GB [软件大小]: 夸克网盘 | 百度网盘 游戏介绍 《异形战机:最终版2》续作震撼登场!经典横版射击全面升级:3D 画面炫目、关卡与机体海量扩充,只为带来酣畅淋漓的灭…

Java 异常(Throwable)

1. Throwable Throwable: 所有异常和错误的根类。实现 Throwable 或其子类的对象才能被 throw 或 catch。 Error: 表示严重的系统级问题,通常不应该被捕获或处理,程序通常无法从中恢复。 Exception: 表示程序可以处理的问题。分为 运行时异常、 受检异常…

rocketmq常用命令

官方文档 https://rocketmq.apache.org/zh/docs/ https://rocketmq.apache.org/zh/docs/domainModel/02topic/ https://rocketmq.apache.org/zh/docs/4.x/deployment/02admintool 集群配置管理 https://mp.weixin.qq.com/s/688wNSwZPraGvAnr0K7hRw RocketMQ运维管理命令mqadm…

【C++详解】哈希表概念与实现 开放定址法和链地址法、处理哈希冲突、哈希函数介绍

文章目录一、unordered系列的使用unordered_set类的介绍unordered_set和set的使⽤差异unordered_map和map的使⽤差异unordered_xxx的哈希相关接⼝二、哈希表实现哈希概念直接定址法哈希冲突负载因⼦将关键字转为整数哈希函数除法散列法/除留余数法乘法散列法处理哈希冲突开放定…

电影感人文街拍摆摊纪实摄影后期Lr调色教程,手机滤镜PS+Lightroom预设下载!

调色介绍电影感人文街拍摆摊纪实摄影后期 Lr 调色是一种专注于捕捉街头生活烟火气的摄影风格,通过 Lightroom 后期调色赋予画面电影般的叙事感和情感深度。这种风格以摆摊小贩、市井行人、街头场景为主体,强调真实、自然的生活瞬间。调色核心在于低饱和暖…

【数据分享】298个地级市人工智能企业数量(1990-2023)

数据介绍引言人工智能产业作为数字经济的核心驱动力,其发展规模与分布格局深刻反映区域科技创新活力与产业升级潜力。为助力相关研究,本文分享一份涵盖全国 298 个地级市 1990-2023 年的人工智能企业核心数据,包含人工智能企业存量和人工智能…