一、数据存储概述
在计算机系统中,数据可以存储在多种形式中:
-
变量:程序中最基本的数据存储单元
-
元组:不可变的序列类型,常用于函数返回多个值
-
列表:有序可变集合,可存储不同类型元素
-
字典:键值对集合,提供快速查找
-
集合:无序不重复元素集
-
文件:
-
XML文件:
<name>ZS</name>
-
YAML文件:
name: ZS
-
JSON文件:
{"name":"zs"}
-
二、数据库分类
1. 关系型数据库(RDBMS)
-
MySQL
-
Oracle
-
SQL Server
-
PostgreSQL
特点:
-
采用关系模型组织数据
-
数据以行和列的形式存储(表结构)
-
支持SQL语言
-
强调数据一致性和完整性
2. 非关系型数据库(NoSQL)
-
Redis(键值存储)
-
MongoDB(文档存储)
-
Cassandra(列存储)
-
Neo4j(图数据库)
特点:
-
灵活的数据模型
-
高扩展性和可用性
-
适合处理大规模数据
-
不强制要求固定表结构
三、数据库选择策略
关系型数据库适用场景
-
需要严格的数据一致性和事务支持
-
银行转账(ACID事务)
-
订单支付
-
库存扣减
-
-
复杂查询和关联分析
-
多表关联(JOIN)
-
聚合函数(GROUP BY)
-
子查询等
-
-
数据结构稳定且规范
-
字段固定(如用户表包含[id, name, email])
-
Schema需预先定义
-
非关系型数据库适用场景
-
高并发写入和水平扩展需求
-
物联网设备数据(每秒百万级写入)
-
社交媒体的用户动态
-
-
灵活或非结构化数据
-
动态字段(如用户自定义属性)
-
嵌套数据(如评论的回复树)
-
-
特定查询模式优化
-
图数据库(Neo4j):处理复杂关系
-
列存储(Cassandra):时间序列数据
-
四、MySQL数据库详解
1. MySQL概述
MySQL是一个开源的关系型数据库管理系统,由瑞典MySQL AB公司开发,现属于Oracle旗下产品。它是目前最流行的关系型数据库之一,特别适合Web应用开发。
特点:
-
体积小、速度快
-
总体拥有成本低
-
开源
-
支持多用户、多线程
2. 安装与卸载
安装步骤:
-
下载对应版本(V5.5/V5.7/V8.0)
-
选择安装路径(避免中文路径)
-
设置root密码
-
配置字符编码(推荐UTF-8)
卸载步骤:
-
控制面板中卸载MySQL
-
删除C盘ProgramData中的MySQL文件夹(隐藏文件夹)
-
清理注册表(可选)
-
重启电脑后重新安装
3. MySQL与Oracle区别
区别项 | MySQL | Oracle |
---|---|---|
字符串类型 | VARCHAR | VARCHAR2 |
自动递增 | 支持AUTO_INCREMENT | 使用序列(SEQUENCE)实现 |
检查约束 | MySQL8.0.16+支持 | Oracle9i+支持 |
分组语法 | 允许SELECT非分组字段 | 只允许SELECT分组字段和统计函数 |
分页语法 | 使用LIMIT | 使用ROWNUM或OFFSET-FETCH |
默认隔离级别 | 可重复读(REPEATABLE READ) | 读已提交(READ COMMITTED) |
五、SQL语言详解
SQL(Structured Query Language)是用于管理关系数据库的标准语言。
1. SQL分类
-
数据査询语言(DQL: Data Query Language):也称为“数据检索语句”,用以从表中获得数据,确定数据怎样在应用程序给出。保留字SELECT是DQL(也是所有SQL)用得最多的动词,其他DQL常用的保留字有WHERE,ORDER BY,GROUP BY和HAVING。这些DQL保留字常与其它类型的SQL语句一起使用。
-
数据操作语言(DML:Data Manipulation Language):其语句包括动词INSERT、UPDATE和DELETE。它们分别用于添加、修改和删除。
-
事务控制语言(TCL:Transaction Control Language):它的语句能确保被DML语句影响的表的所有行及时得以更新。包括COMMIT(提交)命令、SAVEPOINT(保存点)命令、ROLLBACK(回滚)命令。
-
数据控制语言(DCL:Data Control Language):它的语句通过GRANT或REVOKE实现权限控制,确定单个用户和用户组对数据库对象的访问。某些RDBMS可用GRANT或REVOKE控制对表单个列的访问。
-
数据定义语言(DDL:Data Defination Language):其语句包括动词CREATE,ALTER和DROP。在数据库中创建新表或修改、删除表(CREATE TABLE或 DROP TABLE):为表加入索引等。
2. 基础SQL命令
数据库操作
-- 查看所有数据库
SHOW DATABASES;
-- 创建数据库
CREATE DATABASE dbname;
-- 使用数据库
USE dbname;
-- 删除数据库
DROP DATABASE dbname;
-- 查看数据库创建信息
SHOW CREATE DATABASE dbname;
表操作
-- 创建表
CREATE TABLE t_user (
name VARCHAR(10),
age INT(3),
address VARCHAR(50)
);
-- 查看所有表
SHOW TABLES;
-- 查看表结构
DESC t_user;
-- 删除表
DROP TABLE t_user;
修改表结构
-- 删除列
ALTER TABLE t_user DROP COLUMN name;
-- 添加列
ALTER TABLE t_user ADD COLUMN name VARCHAR(10);
-- 修改列
ALTER TABLE t_user CHANGE COLUMN name username VARCHAR(15);
3. 常用数据类型
-
INT:整数
-
DOUBLE:浮点数
-
VARCHAR:可变长度字符串
-
DATETIME:日期时间
-
TEXT:长文本
-
BLOB:二进制数据
六、数据增删改查(CRUD)
1. 增加数据(INSERT)
-- 方式1:全字段插入
INSERT INTO t_user VALUES (12, "beijing", "admin");
-- 方式2:指定字段插入
INSERT INTO t_user (age, address) VALUES (12, "beijing");
2. 删除数据(DELETE)
-- 条件删除
DELETE FROM t_user WHERE address = "beijing";
-- 清空表(慎用)
DELETE FROM t_user;
3. 修改数据(UPDATE)
-- 条件更新
UPDATE t_user SET username="qiaoba" WHERE address="taiyuan";
-- 全表更新
UPDATE t_user SET username="qiaoba";
4. 查询数据(SELECT)
-- 查询所有数据
SELECT * FROM t_user;
-- 查询特定字段
SELECT name, age FROM t_user;
-- 带条件查询
SELECT * FROM t_user WHERE age > 18;
七、约束与索引
1. 约束类型
1.非空约束(NOT NULL)
CREATE TABLE t_admin(
id INT(5),
adminname VARCHAR(10) NOT NULL,
password VARCHAR(20)
);
2.唯一约束(UNIQUE)
CREATE TABLE t_person(
id INT(5) UNIQUE,
adminname VARCHAR(10) NOT NULL,
password VARCHAR(20)
);
3.主键约束(PRIMARY KEY)
CREATE TABLE t_cat(
id INT(5) PRIMARY KEY,
name VARCHAR(10),
password VARCHAR(20)
);
--或者指定
create table t_person(
id int(5) AUTO_INCREMENT,
name varchar(10),
password varchar(20),
constraint pk_id primary key(id)
);
注:
1.一般将id编号设置为主键 (聊到主键索引就想到性能)而且每张表建议至少有一个主键
2.当主键为int数字类型时,一般设置为自动递增
自动递增的两种方式:
方式一:mysql数据库中支持自动递增,所以可以在创表中追加AUTO_INCREMENT(如果删除了id为3的,再插入一个,那么他的id是4不是3)
方式二:通过python程做自动递增 id+=1
当主键为varchar字符串类型时,无法再做自动递增,此时还有两种方式
方式一:通过python程序来生成固定格式,并且不会重复的主键 id+=1
方式二:通过雪花算法(下文会提到)来生成不会重复的主键
4.外键约束(FOREIGN KEY)
关系:一对多 多对多
CREATE TABLE t_user(
id INT(5) AUTO_INCREMENT,
name VARCHAR(10),
gid INT(5),
CONSTRAINT pk_id PRIMARY KEY(id),
CONSTRAINT fk_gid FOREIGN KEY(gid) REFERENCES t_group(id)
);
5.检查约束(CHECK) (MySQL8.0.16+支持)
CREATE TABLE employees(
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(100),
age INT,
CONSTRAINT age_check CHECK(age>=18 AND age<=65)
);
2. 自动递增
-- MySQL自动递增
CREATE TABLE t_person(
id INT(5) PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(10),
password VARCHAR(20)
);
3. 雪花算法
概述
雪花算法(Snowflake Algorithm)是一种分布式唯一ID生成算法,最早由 Twitter 开发,用来解决在高并发环境下生成全局唯一ID的问题。它的特点是高性能、高可用、趋势递增、按时间排序,并且生成的ID不会重复,即使在分布式系统中。
雪花算法的ID结构
雪花算法(Snowflake)是Twitter开发的分布式ID生成算法,生成64位唯一ID,结构如下:
-
1位符号位(始终为0)
-
41位时间戳(毫秒级,69年)
-
10位机器ID(5位数据中心+5位机器ID)
-
12位序列号(每毫秒4096个ID)
优点
- 高性能:本地生成,无需数据库访问,生成一个ID只需几微秒。
- 全局唯一:由时间戳 + 机器号 + 序列号共同决定,天然不会重复。
- 趋势递增:基于时间戳生成,保证ID大致按生成时间递增(方便排序)。
- 适合分布式系统:支持多节点并行生成不冲突的ID。
存在的缺点
- 依赖机器时钟:如果系统时间回拨,可能会导致ID重复。
- 位数固定:64位中各部分长度写死,扩展性有限。
- 不适合生成短ID或可读性强的ID:生成的ID是类似 879278326123438080 的长整型数字。
Python实现简化版:
import time
import threading
class Snowflake:
def __init__(self, datacenter_id=1, worker_id=1):
self.twepoch = 1288834974657
self.datacenter_id = datacenter_id
self.worker_id = worker_id
self.sequence = 0
self.last_timestamp = -1
self.lock = threading.Lock()
def _timestamp(self):
return int(time.time() * 1000)
def get_id(self):
with self.lock:
timestamp = self._timestamp()
if timestamp == self.last_timestamp:
self.sequence = (self.sequence + 1) & 0xfff
if self.sequence == 0:
while timestamp <= self.last_timestamp:
timestamp = self._timestamp()
else:
self.sequence = 0
self.last_timestamp = timestamp
id = ((timestamp - self.twepoch) << 22) | (self.datacenter_id << 17) | (self.worker_id << 12) | self.sequence
return id
雪花算法适合哪些场景?
- 订单号、用户ID、消息ID、日志ID等需要“唯一标识”的场景
- 多服务、多节点部署的微服务架构
- 替代数据库自增ID(特别是 varchar 不支持自增的场景)
八、高级查询
查询引入:
有数据才能进行查询操作,在正式学习查询之前我们先完成建表以及添加数据的操作:
/********************************部门表dept********************************/
/*创建表*/
DROP TABLE IF EXISTS DEPT;
CREATE TABLE DEPT(
DEPTNO INT PRIMARY KEY,
DNAME VARCHAR(14) ,
LOC VARCHAR(13)
);
/********************************员工表emp********************************/
/*创建表*/
DROP TABLE IF EXISTS EMP;
CREATE TABLE EMP(
EMPNO INT PRIMARY KEY,
ENAME VARCHAR(14) ,
JOB VARCHAR(9),
MGR INT,
HIREDATE DATE,
SAL DECIMAL(7,2),
COMM DECIMAL(7,2),
DEPTNO int REFERENCES DEPT
);
/***************工资等级表salgrade********************************/
/*创建表*/
DROP TABLE IF EXISTS SALGRADE;
CREATE TABLE SALGRADE(
GRADE INT PRIMARY KEY,
LOSAL INT,
HISAL INT
);
#工资级别表 插入数据
INSERT INTO salgrade VALUES (1,700,1200);
INSERT INTO salgrade VALUES (2,1201,1400);
INSERT INTO salgrade VALUES (3,1401,2000);
INSERT INTO salgrade VALUES (4,2001,3000);
INSERT INTO salgrade VALUES (5,3001,9999);
#员工表 插入数据
insert into EMP (empno, ename, job, mgr, hiredate, sal, comm, deptno)
values (7369, 'SMITH', 'CLERK', 7902, '1980-12-17', 800, null, 20);
insert into EMP (empno, ename, job, mgr, hiredate, sal, comm, deptno)
values (7499, 'ALLEN', 'SALESMAN', 7698, '1981-02-20', 1600, 300, 30);
insert into EMP (empno, ename, job, mgr, hiredate, sal, comm, deptno)
values (7521, 'WARD', 'SALESMAN', 7698, '1981-02-22', 1250, 500, 30);
insert into EMP (empno, ename, job, mgr, hiredate, sal, comm, deptno)
values (7566, 'JONES', 'MANAGER', 7839, '1981-04-02', 2975, null, 20);
insert into EMP (empno, ename, job, mgr, hiredate, sal, comm, deptno)
values (7654, 'MARTIN', 'SALESMAN', 7698, '1981-09-28', 1250, 1400, 30);
insert into EMP (empno, ename, job, mgr, hiredate, sal, comm, deptno)
values (7698, 'BLAKE', 'MANAGER', 7839, '1981-05-01', 2850, null, 30);
insert into EMP (empno, ename, job, mgr, hiredate, sal, comm, deptno)
values (7782, 'CLARK', 'MANAGER', 7839, '1981-06-09', 2450, null, 10);
insert into EMP (empno, ename, job, mgr, hiredate, sal, comm, deptno)
values (7788, 'SCOTT', 'ANALYST', 7566, '1987-04-19', 3000, null, 20);
insert into EMP (empno, ename, job, mgr, hiredate, sal, comm, deptno)
values (7839, 'KING', 'PRESIDENT', null, '1981-11-17', 5000, null, 10);
insert into EMP (empno, ename, job, mgr, hiredate, sal, comm, deptno)
values (7844, 'TURNER', 'SALESMAN', 7698, '1981-09-08', 1500, 0, 30);
insert into EMP (empno, ename, job, mgr, hiredate, sal, comm, deptno)
values (7876, 'ADAMS', 'CLERK', 7788, '1987-05-23', 1100, null, 20);
insert into EMP (empno, ename, job, mgr, hiredate, sal, comm, deptno)
values (7900, 'JAMES', 'CLERK', 7698, '1981-12-03', 950, null, 30);
insert into EMP (empno, ename, job, mgr, hiredate, sal, comm, deptno)
values (7902, 'FORD', 'ANALYST', 7566, '1981-12-03', 3000, null, 20);
insert into EMP (empno, ename, job, mgr, hiredate, sal, comm, deptno)
values (7934, 'MILLER', 'CLERK', 7782, '1982-01-23', 1300, null, 10);
#部门表 插入数据
insert into DEPT (deptno, dname, loc)
values (10, 'ACCOUNTING', 'NEW YORK');
insert into DEPT (deptno, dname, loc)
values (20, 'RESEARCH', 'DALLAS');
insert into DEPT (deptno, dname, loc)
values (30, 'SALES', 'CHICAGO');
insert into DEPT (deptno, dname, loc)
values (40, 'OPERATIONS', 'BOSTON');
查询语法:
语法: select 字段 from 表名
字段: * 表示所有字段
字段:字段1,字段2
字段: 字段1 别名,字段2 别名
字段:去重 distinct关键字
1. 条件查询
-- 比较运算符
查询薪资高于2000的员工
SELECT * FROM emp WHERE sal > 2000;
-- BETWEEN AND
查询薪资介于1500到5000的员工
SELECT * FROM emp WHERE sal BETWEEN 1500 AND 5000;
-- IS NULL
查询没有奖金的员工信息
SELECT * FROM emp WHERE comm IS NULL;
-- LIKE模糊查询
SELECT * FROM emp WHERE ename LIKE "%s%"; -- 包含s
SELECT * FROM emp WHERE ename LIKE "s%"; -- s开头
SELECT * FROM emp WHERE ename LIKE "%s"; -- s结尾
SELECT * FROM emp WHERE ename LIKE "_m%"; -- 第二个字母是m
查询入职日期在1981年的员工信息
select * from emp where hiredate like '%1981%';
select * from emp where hiredate between '1981-01-01' and '1981-12-31';
查询员工编号在7499 7521 7900的员工
select * from emp where empno = 7499 or empno = 7521 or empno = 7900;
select * from emp where empno in(7499,7521,7900);
2. 排序查询
语法: select 字段 from 表名 [限定语法][排序条件]
排序关键字:order by
升序 asc
降序 desc
如果需要根据多个字段进行排列,那么在排序后边直接追加即可:
select * from 表名 [限定语法][order by 字段1 升序或降序,字段2 升序或降序]
-- 单字段排序
按照入职日期做降序排列:
SELECT * FROM emp ORDER BY hiredate DESC;
-- 多字段排序
按照入职日期做降序排列,如果入职日期相同,按照薪资做升序排列:
SELECT * FROM emp ORDER BY hiredate DESC, sal ASC;
3. 多表查询
如果直接查询所有的员工信息及部门信息
select * from emp,dept;
结果:这种查询方式,简单的将两张表堆积在一块,会带来数据冗余问题,这种现象称之为笛卡尔积效应 解决方法:
-- 等值连接(消除笛卡尔积)
SELECT * FROM emp, dept WHERE emp.deptno = dept.deptno;
-- 自连接(同一表不同别名)
SELECT e1.empno, e1.ename, e2.ename AS manager
FROM emp e1, emp e2
WHERE e1.mgr = e2.empno;
4. 连接查询(在JOIN操作中,将小表放在前面)
1. 内连接(INNER JOIN)
特点:只返回两个表中匹配的行
-- 标准语法
SELECT 列名 FROM 表1
INNER JOIN 表2 ON 表1.列 = 表2.列;
-- 示例:查询员工及其部门信息
SELECT e.empno, e.ename, d.dname
FROM emp e
INNER JOIN dept d ON e.deptno = d.deptno;
等价写法(使用WHERE子句):
SELECT e.empno, e.ename, d.dname
FROM emp e, dept d
WHERE e.deptno = d.deptno;
2. 左外连接(LEFT JOIN / LEFT OUTER JOIN)
特点:返回左表所有记录,即使右表没有匹配
SELECT 列名 FROM 表1
LEFT JOIN 表2 ON 表1.列 = 表2.列;
-- 示例:查询所有员工信息,包括没有部门的员工
SELECT e.empno, e.ename, d.dname
FROM emp e
LEFT JOIN dept d ON e.deptno = d.deptno;
3. 右外连接(RIGHT JOIN / RIGHT OUTER JOIN)
特点:返回右表所有记录,即使左表没有匹配
SELECT 列名 FROM 表1
RIGHT JOIN 表2 ON 表1.列 = 表2.列;
-- 示例:查询所有部门信息,包括没有员工的部门
SELECT e.empno, e.ename, d.dname
FROM emp e
RIGHT JOIN dept d ON e.deptno = d.deptno;
4. 全外连接(FULL JOIN / FULL OUTER JOIN)
特点:返回两表所有记录,没有匹配的用NULL填充
-- MySQL不直接支持FULL JOIN,可用UNION实现
SELECT 列名 FROM 表1 LEFT JOIN 表2 ON 表1.列 = 表2.列
UNION
SELECT 列名 FROM 表1 RIGHT JOIN 表2 ON 表1.列 = 表2.列;
-- 示例:查询所有员工和部门信息
SELECT e.empno, e.ename, d.dname
FROM emp e LEFT JOIN dept d ON e.deptno = d.deptno
UNION
SELECT e.empno, e.ename, d.dname
FROM emp e RIGHT JOIN dept d ON e.deptno = d.deptno;
5. 交叉连接(CROSS JOIN)
特点:返回两表的笛卡尔积
SELECT 列名 FROM 表1 CROSS JOIN 表2;
-- 等价写法
SELECT 列名 FROM 表1, 表2;
6. 自连接(SELF JOIN)
特点:表与自身连接
-- 示例:查询员工及其经理信息
SELECT e1.empno AS 员工ID, e1.ename AS 员工姓名,
e2.empno AS 经理ID, e2.ename AS 经理姓名
FROM emp e1
LEFT JOIN emp e2 ON e1.mgr = e2.empno;
5. 分组查询
语法:select字段 from 表名[连接条件][限定语法][排序条件]
group by
注意事项:
1.一旦出现分组,那么se1ect后边只允许出现分组字段及统计函数
2.统计函数可以单独使用
3.如果出现统计函数嵌套,那么在select后边只允许出现统计函数
4.分组之后如果还要使用条件筛选,不允许使用where,改为having
查询公司所有职位
select job,count(empno) from emp group by job;
查询每个部门的平均工资
select job,count(empno),avg(sal) from emp group by job;
查询每个部门的详细信息,包含平均工资
select emp.job,count(empno),avg(sal),dept.dname from emp left join dept on emp.deptno = dept.deptno group by emp.job;
查询平均薪资高于2000的部门信息
select emp.job,count(empno),avg(sal),dept.dname from emp left join dept on emp.deptno = dept.deptno group by emp.job having avg(emp.sal)>2000;
统计函数
统计数量 count
平均值 avg
最大值 max
最小值 min
求和 sum
6. 子查询
--where子查询:当查询的结果为单行单列或多行单列时
SELECT * FROM emp
查询比Smith工资高的员工信息
WHERE sal > (SELECT sal FROM emp WHERE ename = "smith");
-- from子查询:当查询的结果为多行多列时
查询部门编号,部门名称,部门位置,部门人数,平均薪资的信息
SELECT d.deptno, d.dname, temp.avg_sal
FROM dept d LEFT JOIN (
SELECT deptno, AVG(sal) AS avg_sal
FROM emp
GROUP BY deptno
) temp ON d.deptno = temp.deptno;
=any in
比最大值小的数据:<any
比最小值大的数据: >any
比最大值大的数据: >all
比最小值小的数据: <all
7. 分页查询
语法:select字段 from 表名[连接条件][限定语法][分组查询][排序条件][分页查询]
分页关键字:limit n,m
n:数据下标索引
m:每页显示的条数
当n为0的时候,说明用户要查询首页的数据,n可以省略不写
-- 基本分页
SELECT * FROM emp LIMIT 0, 10; -- 第一页
SELECT * FROM emp LIMIT 10, 10; -- 第二页
-- 简化写法(首页)
SELECT * FROM emp LIMIT 10;
九、数据库设计实践
1. 一对多关系
-- 组表
CREATE TABLE t_group(
id INT(5) AUTO_INCREMENT,
gname VARCHAR(10),
CONSTRAINT pk_id PRIMARY KEY(id)
);
-- 用户表(带外键)
CREATE TABLE t_user(
id INT(5) AUTO_INCREMENT,
name VARCHAR(10),
gid INT(5),
CONSTRAINT pk_id PRIMARY KEY(id),
CONSTRAINT fk_gid FOREIGN KEY(gid) REFERENCES t_group(id)
);
2. 多对多关系
-- 学生表
CREATE TABLE student(
id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(20)
);
-- 课程表
CREATE TABLE course(
id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(20)
);
-- 学生课程关联表
CREATE TABLE student_course(
sid INT,
cid INT,
PRIMARY KEY(sid, cid),
FOREIGN KEY(sid) REFERENCES student(id),
FOREIGN KEY(cid) REFERENCES course(id)
);
3. 级联操作
-- 级联删除
CREATE TABLE t_user(
id INT(5) AUTO_INCREMENT,
gid INT(5),
CONSTRAINT fk_gid FOREIGN KEY(gid) REFERENCES t_group(id) ON DELETE CASCADE
);
-- 级联置空
CREATE TABLE t_user(
id INT(5) AUTO_INCREMENT,
gid INT(5),
CONSTRAINT fk_gid FOREIGN KEY(gid) REFERENCES t_group(id) ON DELETE SET NULL
);
十、性能优化建议
-
合理使用索引:为常用查询条件创建索引
-
避免SELECT *:只查询需要的字段
-
优化JOIN操作:确保JOIN字段有索引
-
合理分页:大数据量使用LIMIT分页
-
避免全表扫描:使用EXPLAIN分析查询
-
事务优化:短事务,及时提交
-
适当拆分表:大表垂直或水平拆分
十一、常见问题解决方案
-
连接问题:
-
检查服务是否启动
-
检查用户名密码
-
检查防火墙设置
-
-
中文乱码:
-
确保数据库、表、连接都使用UTF-8编码
-
设置连接参数:
charset='utf8mb4'
-
-
性能问题:
-
使用EXPLAIN分析慢查询
-
优化SQL语句
-
添加适当索引
-
-
事务问题:
-
检查隔离级别设置
-
确保事务及时提交或回滚
-
避免长事务
-
十二、学习资源推荐
-
官方文档:MySQL官方文档是最权威的学习资料
-
在线教程:菜鸟教程、W3School等
-
书籍推荐:
-
《高性能MySQL》
-
《MySQL必知必会》
-
《SQL进阶教程》
-
-
实践平台:LeetCode数据库题目、牛客网SQL练习题