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

MySQL数据库面试高频问题及解析

以下是汇总一份全面且针对性强的数据库(以 MySQL 为主)问题清单与答案解析。


一、SQL 基础与查询

1. 什么是主键、外键、唯一索引?它们有什么区别?

概念作用是否允许NULL一张表数量
主键唯一标识一条记录,保证实体完整性不允许一个
外键建立和加强两个表数据之间的链接,保证参照完整性允许(除非被引用列是主键)多个
唯一索引保证数据的唯一性,提高查询速度允许(但只能有一个NULL)多个

核心答案:主键是唯一的标识符,不允许重复和NULL;外键是关联另一张表主键的字段;唯一索引是保证字段值唯一的索引。主键是一种特殊的唯一索引。

2. WHERE 和 HAVING 子句的区别是什么?

  • WHERE:在分组前(GROUP BY) 过滤数据,它后面不能跟聚合函数。它作用于原始数据行

  • HAVING:在分组后(GROUP BY) 过滤数据,它后面通常跟聚合函数(如 COUNTSUM)。它作用于分组后的结果集

示例:找出平均分数大于80分的学生ID。

SELECT student_id, AVG(score) as avg_score
FROM scores
GROUP BY student_id
HAVING AVG(score) > 80; -- HAVING在分组后过滤,可以使用聚合函数

3. INNER JOINLEFT JOINRIGHT JOIN 和 FULL JOIN 的区别?

这是一个必考题,用韦恩图来理解最直观。

  • INNER JOIN(内连接):只返回两个表中连接条件匹配的记录。交集

  • LEFT JOIN(左连接):返回左表的全部记录,以及右表中连接条件匹配的记录。如果右表无匹配,则右表字段为NULL。

  • RIGHT JOIN(右连接):与左连接相反,返回右表的全部记录。

  • FULL JOIN(全连接):返回左右两表的全部记录。只要其中某个表存在匹配,就返回行。不匹配的部分用NULL填充。(MySQL不直接支持,但可用 UNION 实现)


二、索引

1. 为什么索引能提高查询速度?

核心答案:索引就像一本书的目录。没有索引(全表扫描)就像一页一页地翻书找内容,速度极慢。而通过索引(目录),数据库可以快速定位到数据所在的数据页,极大地减少了需要扫描的数据量。

2. 哈希索引和B+树索引的区别?

特性哈希索引B+树索引
结构哈希表多路平衡搜索树
查询效率等值查询极快 O(1)等值查询和范围查询都很快 O(log n)
是否有序无序有序(叶子节点链表)
支持排序不支持支持
适用场景仅等值查询(如内存表)绝大多数数据库场景

结论:数据库(如MySQL的InnoDB)默认使用B+树索引,因为它完美支持了数据库最常用的等值查询范围查询

3. 什么情况下索引会失效?

这是一个非常实战化的问题。

  1. 在索引列上使用函数或计算WHERE YEAR(create_time) = 2023 (失效) vs WHERE create_time BETWEEN '2023-01-01' AND '2023-12-31' (有效)。

  2. 使用 != 或 <> 操作符

  3. 使用 OR 连接条件,如果OR的某一侧没有索引,可能导致全表扫描。

  4. 对索引列使用 LIKE 并以通配符 % 开头WHERE name LIKE '%伟' (失效)vs WHERE name LIKE '张%' (有效,叫“前缀匹配”)。

  5. 字符串索引未使用引号,会导致类型转换,索引失效。

  6. 复合索引未使用最左前缀。例如索引是 (a, b, c),查询条件只有 b = 1 和 c = 1 则无法使用该索引。


三、事务

1. 谈谈数据库事务的ACID特性。

这是事务的基石,必须烂熟于心。

  • A - 原子性:事务是一个不可分割的工作单位,事务中的操作要么全部成功,要么全部失败回滚。通过 Undo Log 实现。

  • C - 一致性:事务执行前后,数据库都必须从一个一致性状态转变到另一个一致性状态(不违反任何完整性约束)。这是事务的最终目的,由其他三大特性共同保证。

  • I - 隔离性:并发事务之间相互隔离,不应互相干扰。通过锁机制和 MVCC 实现。

  • D - 持久性:事务一旦提交,它对数据库的改变就是永久性的。通过 Redo Log 实现。

2. 事务的隔离级别有哪些?分别解决了哪些并发问题?

隔离级别脏读不可重复读幻读
读未提交❌ 可能发生❌ 可能发生❌ 可能发生
读已提交✅ 解决❌ 可能发生❌ 可能发生
可重复读✅ 解决✅ 解决❌ 可能发生
串行化✅ 解决✅ 解决✅ 解决
  • 脏读:读到了另一个未提交事务修改的数据。

  • 不可重复读:在同一个事务中,两次读取同一条数据,结果不一样(被其他已提交事务修改删除)。

  • 幻读:在同一个事务中,两次执行相同的查询,返回的记录数不一样(被其他已提交事务插入了新数据)。

注意:MySQL的InnoDB引擎在可重复读级别下,通过 Next-Key Lock 机制在很大程度上避免了幻读。


四、锁

1. 乐观锁和悲观锁的区别?

  • 悲观锁悲观地认为数据在修改时一定会发生冲突。因此在操作数据之前,会先加锁(如行锁、表锁)。SELECT ... FOR UPDATE 就是典型的悲观锁。数据库原生支持

  • 乐观锁乐观地认为数据在修改时不会冲突。因此不会加锁,而是在更新时去判断此期间数据是否被其他线程修改过。通常通过版本号时间戳实现。需要应用层自己实现

适用场景

  • 悲观锁:写操作多,冲突概率高的场景。

  • 乐观锁:读操作多,冲突概率低的场景,能大大提高吞吐量。

2. 行级锁和表级锁的区别?

  • 表级锁:开销小,加锁快;不会出现死锁;锁定粒度大,发生锁冲突的概率最高,并发度最低。(如MyISAM引擎)

  • 行级锁:开销大,加锁慢;会出现死锁;锁定粒度最小,发生锁冲突的概率最低,并发度最高。(如InnoDB引擎)

结论:InnoDB的行级锁是现代高并发应用的首选。


五、数据库设计

1. 数据库三大范式是什么?

  • 第一范式:每个字段都是原子性的,不可再分。

  • 第二范式:满足第一范式,且非主键字段必须完全依赖于整个主键,而不是部分主键。(主要针对复合主键)

  • 第三范式:满足第二范式,且非主键字段之间不能有传递依赖,即所有非主键字段必须直接依赖于主键。

简单理解:范式是为了减少数据冗余,保持数据一致性。但并非范式越高越好,有时为了查询性能(减少JOIN),会故意设计反范式的表。


六、实战与场景题

1. 如何定位和优化一条慢SQL查询?

这是一个考察综合能力的问题。

  1. 定位:使用MySQL的慢查询日志 或 SHOW PROCESSLIST 命令找到执行慢的SQL。

  2. 分析:使用 EXPLAIN 命令分析SQL的执行计划。重点关注:

    • type:访问类型,从好到坏有 consteq_refrefrangeindexALL(全表扫描)。

    • key:实际使用的索引。

    • rows:预估需要扫描的行数。

    • Extra:额外信息,如 Using filesort(需要额外排序),Using temporary(使用临时表)都是需要优化的信号。

  3. 优化

    • 为 WHERE 条件和 ORDER BY / GROUP BY 的列创建合适的索引。

    • 优化SQL语句本身(避免 SELECT *,避免使用 OR 等)。

    • 考虑重构表结构或业务逻辑。

2. DROPDELETE 和 TRUNCATE 的区别?

操作类型是否可回滚是否触发触发器速度
DELETEDML可回滚会触发慢(一行行删除)
TRUNCATEDDL不可回滚不会触发快(直接删除数据页)
DROPDDL不可回滚不会触发最快(删除整个表)


下面让我们专注于 SQL 语句本身。这里为你梳理从基础到高级的各种常用 SQL 语句,并附上解释和示例。

一、数据定义语言(DDL)- 定义和管理结构

用于定义、修改和删除数据库、表、索引等对象的结构。

1. CREATE - 创建

创建数据库:

CREATE DATABASE my_shop;

创建表:

CREATE TABLE users (id INT AUTO_INCREMENT PRIMARY KEY,      -- 自增主键username VARCHAR(50) NOT NULL UNIQUE,   -- 非空且唯一email VARCHAR(100),age INT CHECK (age >= 0),               -- 检查约束created_at DATETIME DEFAULT CURRENT_TIMESTAMP -- 默认值
);

创建索引:

-- 在users表的email字段上创建索引,加快基于邮箱的查询
CREATE INDEX idx_email ON users(email);-- 创建联合索引
CREATE INDEX idx_name_age ON users(username, age);
2. ALTER - 修改

添加列:

ALTER TABLE users ADD COLUMN phone_number VARCHAR(20);

修改列数据类型:

ALTER TABLE users MODIFY COLUMN email VARCHAR(150); -- 修改长度

删除列:

ALTER TABLE users DROP COLUMN age;

添加主键/外键:

-- 添加主键(如果建表时没加)
ALTER TABLE users ADD PRIMARY KEY (id);-- 添加外键 (orders表的user_id引用users表的id)
ALTER TABLE orders ADD CONSTRAINT fk_user
FOREIGN KEY (user_id) REFERENCES users(id);
3. DROP - 删除

删除表:

DROP TABLE users; -- 谨慎使用!表和数据都会消失

删除数据库:

DROP DATABASE my_shop; -- 更加谨慎!

删除索引:

DROP INDEX idx_email ON users;
4. TRUNCATE - 清空表
TRUNCATE TABLE logs; -- 删除表内所有数据,但保留表结构。不可回滚,速度快。

二、数据操作语言(DML)- 操作数据本身

用于对表中的数据进行增、删、改操作。

1. INSERT - 插入数据

插入单行:

INSERT INTO users (username, email, age)
VALUES ('john_doe', 'john@example.com', 25);

插入多行:

INSERT INTO users (username, email, age) VALUES
('alice', 'alice@example.com', 30),
('bob', 'bob@example.com', 28);

从另一张表插入:

INSERT INTO user_archive (username, email)
SELECT username, email FROM users WHERE created_at < '2020-01-01';
2. UPDATE - 更新数据

更新特定行:

UPDATE users
SET email = 'new_email@example.com', age = 26
WHERE username = 'john_doe'; -- WHERE子句至关重要!否则会更新所有行。

基于子查询更新:

UPDATE products
SET price = price * 0.9 -- 打九折
WHERE category_id IN (SELECT id FROM categories WHERE name = 'Clearance');
3. DELETE - 删除数据

删除特定行:

DELETE FROM users
WHERE username = 'inactive_user'; -- WHERE子句至关重要!否则会清空整个表。

清空表(与TRUNCATE对比):

DELETE FROM users; -- 逐行删除,可回滚,速度慢,会触发触发器。

三、数据查询语言(DQL)- 检索数据

核心是 SELECT 语句,用于从表中查询数据。

1. 基础查询

查询所有列:

SELECT * FROM users;

查询特定列:

SELECT username, email FROM users;

使用别名:

SELECT username AS ‘用户名‘,email AS ‘邮箱‘
FROM users;
2. WHERE - 条件过滤

基本运算符:

SELECT * FROM products WHERE price > 100;
SELECT * FROM users WHERE age BETWEEN 18 AND 65;
SELECT * FROM users WHERE username LIKE 'A%'; -- 以A开头
SELECT * FROM users WHERE email IS NOT NULL;

多条件组合:

SELECT * FROM users 
WHERE age > 18 AND (country = 'USA' OR country = 'Canada')AND username NOT LIKE '%admin%';
3. ORDER BY - 排序
SELECT * FROM products 
ORDER BY price DESC; -- 按价格降序SELECT * FROM users 
ORDER BY created_at ASC, username DESC; -- 先按创建时间升序,同时间再按用户名降序
4. GROUP BY 与聚合函数

常用聚合函数: COUNT()SUM()AVG()MAX()MIN()

-- 统计每个国家的用户数量
SELECT country, COUNT(*) AS user_count
FROM users
GROUP BY country;-- 找出每个分类的平均价格和最高价格
SELECT category_id, AVG(price) AS avg_price,MAX(price) AS max_price
FROM products
GROUP BY category_id;-- HAVING子句用于过滤分组后的结果
SELECT category_id, AVG(price) AS avg_price
FROM products
GROUP BY category_id
HAVING AVG(price) > 50; -- 筛选出平均价格大于50的分类
5. JOIN - 连接表

内连接:

-- 获取所有订单及其对应的用户信息(只返回有用户的订单)
SELECT o.order_id, o.amount, u.username
FROM orders o
INNER JOIN users u ON o.user_id = u.id;

左外连接:

-- 获取所有用户及其订单(即使用户没有订单也会显示)
SELECT u.username, o.order_id
FROM users u
LEFT JOIN orders o ON u.id = o.user_id;

自连接:

-- 在员工表中查找每个员工及其经理的名字
SELECT e.name AS employee_name, m.name AS manager_name
FROM employees e
LEFT JOIN employees m ON e.manager_id = m.id;
6. 子查询

在WHERE中:

-- 找出价格高于平均价格的产品
SELECT * FROM products
WHERE price > (SELECT AVG(price) FROM products);

在FROM中(派生表):

-- 找出每个分类中价格最高的产品
SELECT p.category_id, p.name, p.price
FROM products p
INNER JOIN (SELECT category_id, MAX(price) as max_priceFROM productsGROUP BY category_id
) AS max_prices ON p.category_id = max_prices.category_id AND p.price = max_prices.max_price;

四、其他关键语句和子句

1. LIMIT / OFFSET - 分页
-- 获取前10条最贵的商品
SELECT * FROM products ORDER BY price DESC LIMIT 10;-- 分页:获取第6到第10条记录(跳过前5条)
SELECT * FROM products ORDER BY id LIMIT 5 OFFSET 5;
-- 或者简写为: LIMIT 5, 5
2. UNION - 合并结果集
-- 合并来自两个表的用户名,并去重
SELECT username FROM active_users
UNION
SELECT username FROM inactive_users;-- UNION ALL 不去重,性能更高
SELECT city FROM suppliers
UNION ALL
SELECT city FROM customers;
3. CASE - 条件逻辑
-- 根据价格区间给产品打标签
SELECT name, price,CASE WHEN price < 50 THEN 'Cheap'WHEN price BETWEEN 50 AND 200 THEN 'Moderate'ELSE 'Expensive'END AS price_category
FROM products;
4. DISTINCT - 去重
-- 找出所有不同的国家
SELECT DISTINCT country FROM users;-- 统计有多少个不同的国家
SELECT COUNT(DISTINCT country) FROM users;
http://www.dtcms.com/a/471529.html

相关文章:

  • 怎么用自己的电脑做网站服务器爱企业工商信息查询系统
  • 无锡游戏网站建设公司作文生成器网站
  • .概述网站建设的基本流程哪个网站可以做鸟瞰图
  • 做网站要学云南免费网站建设
  • 杨浦专业做网站互联网服务平台待备案机动车
  • 购物网站设计模版自定义手机网站建设
  • XXL-Job入门:项目集成、任务编写与页面配置完整教程
  • 无人设备中继器的关键技术
  • 网站备案前置审批大学生创新创业大赛案例
  • 设计素材网站排版甘肃做网站价格
  • 天津做网站优化的公司php 做视频网站
  • 网站的开发流程分哪几步专业做俄语网站建设
  • Davinci工程讲解
  • 免费网站在线观看人数在哪买国有林场网站建设
  • 茂名哪里有网站开发公司网站建设教育平台
  • 学习SpringBoot
  • nas 可以做网站吗wordpress 文章付费查看
  • 标识设计公司网站公司做免费网站
  • 网页欣赏网站微信商城网站搭建
  • 企业网站备案是什么意思专业电商网站
  • 做it人经常逛的网站中国制造网下载
  • 国外免费外贸网站马关县网站建设
  • 广东基层团组织建设部网站甘肃省建设厅不动产网站
  • 微信连接微网站吗网址跳转网站
  • OpenSSH下载和安装教程(附安装包)
  • 北京欢迎您张家界seo优化方案
  • 签署网站建设协议新闻白城百度网站建设
  • 外贸网站推广营销举三个成功的新媒体营销案例
  • 淘宝网站建设类别宜宾建设机械网站
  • 16大平台全支持!bililive直播录制工具实测