数据库进阶

一、MySQL体系结构

连接层、服务层、引擎层、存储层

连接层 = 超市大门 + 收银员
  • 作用:负责接待 "顾客"(客户端,比如 Workbench、你的 Java 程序),验证身份(核对用户名密码),给顾客分配 "购物车"(数据库连接)。

  • 通俗举例:你进超市要先过门禁,收银员确认你是合法顾客,然后给你推车,你才能开始逛。没有这一步,你连超市门都进不去。

2. 服务层 = 超市导购员 + 调度中心
  • 作用:帮你规划 "购物路线"(优化 SQL 执行计划),告诉你东西在哪(解析 SQL 语法),核对你有没有买东西的权限(权限校验),最后帮你整理买好的商品(处理查询结果)。

  • 通俗举例 :你说 "我要买牛奶和面包",导购员直接带你去乳制品区和烘焙区,不会让你瞎逛;同时确认你带了钱(有权限),最后帮你把东西装袋。所有 "动脑子" 的活都在这一层

3. 引擎层 = 超市货架管理员
  • 作用:负责具体的 "货位管理"(数据存储和读取),不同货架有不同的摆放规则(对应不同存储引擎)。比如有的货架(InnoDB)支持 "退货换货"(事务、行锁),有的货架(MyISAM)只卖特价商品,不支持退换(适合只读场景)。

  • 通俗举例:导购员让货架管理员拿牛奶,管理员就从自己负责的货架上取货,他不管你怎么进来的、买了多少,只负责 "存取货" 这个动作。

4. 存储层 = 超市仓库
  • 作用 :货架上的货最终都来自仓库,仓库就是数据的最终存放地(磁盘文件)。货架管理员需要货了,就去仓库取;卖不完的货,再放回仓库存起来。

  • 通俗举例:仓库里整箱的牛奶、成捆的面包,就是最原始的 "数据",货架只是临时展示用的,真正的存货都在仓库里。

二、存储引擎简介

存储引擎就是存储数据,建立索引、更新、查询数据等技术的实现方式。存储引擎是基于表的,而不得基于库的,所以存储引擎也可被称为表类型。

在创建表时指定存储引擎

sql 复制代码
show engines;   //查看当前数据库支持的存储引擎
-- 建一个电商订单表,用 InnoDB(支持事务)
CREATE TABLE orders (
  id INT PRIMARY KEY,
  user_id INT,
  money DECIMAL(10,2)
) ENGINE=InnoDB;    //默认就是这个所以可以不写
-- 建一个博客文章表,用 MyISAM(只读快)
CREATE TABLE articles (
  id INT PRIMARY KEY,
  title VARCHAR(200),
  content TEXT
) ENGINE=MyISAM;

三、存储引擎的特点

1. InnoDB:"全能管家"(MySQL 5.5 及以上默认)
  • 性格:稳重靠谱、安全第一,啥活都能干,尤其擅长复杂业务。

  • 核心技能

    1. 支持 "事务"(比如转账时,扣钱和加钱要么一起成,要么一起失败,不会出问题);

    2. 支持 "行级锁"(多人同时改不同数据不冲突,比如电商平台多人下单不卡);

    3. 支持 "外键(foreign key)"(比如订单表必须关联用户表,不会出现 "没有用户的订单");

    4. 崩溃恢复(服务器断电也不怕,重启后数据能恢复)。

  • 适用场景:绝大多数业务系统(电商、支付、管理系统等),只要涉及数据安全和并发操作,选它准没错!

2. MyISAM:"快手管家"(老版本默认,现在少用)
  • 性格:干活快、不墨迹,但有点 "不靠谱",只适合简单活。

  • 核心技能

    1. 读写速度比 InnoDB 快(因为不做事务、锁这些 "额外工作");

    2. 占用磁盘空间小(数据存储更紧凑)。

  • 缺点

    1. 不支持事务、外键;

    2. 只支持 "表级锁"(多人同时改一张表会排队,并发差);

    3. 崩溃后数据可能丢失(没有恢复机制)。

  • 适用场景:静态数据、只读场景(比如博客文章、新闻列表、日志归档,只查不改或很少改)

3. Memory:"临时管家"(内存型引擎)
  • 性格:速度飞起来,但健忘(重启就忘)。

  • 核心技能:数据全存在内存里,查询、修改速度极快(比磁盘快几百倍)。

  • 缺点

    1. 服务器重启 / 断电,数据直接消失;

    2. 不支持事务,数据量不能太大(受内存大小限制)。

  • 适用场景:临时计算、缓存数据(比如临时统计报表、会话缓存,用完就扔的那种)。

四、存储引擎的选择

场景描述 选哪个引擎?
电商下单、支付、用户管理(要安全、要并发) InnoDB(必选)
博客文章、新闻列表(只看不改,要快) MyISAM
临时统计数据、会话缓存(用完就扔,要极速) Memory

索引

是帮助 MySQL 高效获取数据 的 数据结构 (有序),索引其实就是数据库表的 "字典目录"------ 就像查字典不用从头翻到尾,先看目录找页码再翻页,数据库查数据也不用扫描全表,靠索引直接定位到要找的行,速度能快几十上百倍。比如查 "id=100 的用户",有索引 1 毫秒就能找到,没索引可能要翻几万行数据。

索引的核心作用(就 2 个)
  1. 加速查询 :这是最核心的!比如查询 SELECT * FROM user WHERE id=100,有索引的话,1 毫秒就能找到;没索引的话,可能要扫描几万行数据,慢几十倍。

  2. 优化排序 :比如查询 SELECT * FROM user ORDER BY name,有 name 字段的索引,MySQL 直接用索引的有序结构排序,不用额外做 "排序操作",效率更高。

索引分类

聚集索引:索引 = 数据,查一次就到位,速度最快(默认主键就是);

二级索引:索引 = 主键,查两次才拿到完整数据,速度比聚集索引慢一点(先查到主键再去聚集索引查),但灵活(可以给多个字段加)。

索引语法
sql 复制代码
create [unique|fulltext]index index_name on table_name (index_Tname,);  //创建索引
show index from table_name;     //查看索引
drop index index_name on table_name;    //删除索引
主键索引(PRIMARY KEY):"唯一的目录页"
  • 特点 :每个表只能有 1 个,字段值必须唯一(不能重复),且不能为 NULL(比如 user 表的 id 字段)。

  • 通俗理解:字典的 "唯一页码",每个页码对应唯一的词条,绝对不会重复。

  • 建表时直接指定:

    sql 复制代码
    CREATE TABLE user (
      id INT PRIMARY KEY, -- 主键索引,自动创建
      name VARCHAR(50)
    );
常规索引(INDEX):"普通目录页"
  • 特点 :可以有多个,字段值可以重复、可以为 NULL(比如 user 表的 namephone 字段)。

  • 通俗理解:字典的 "拼音目录",多个词条可能拼音相同(比如 "李" 和 "理"),可以重复。

  • 建表后添加:

    复制代码
    -- 给 name 字段加普通索引
    CREATE INDEX idx_user_name ON user(name);
3. 唯一索引(UNIQUE):"不重复的普通目录"
  • 特点 :可以有多个,但字段值必须唯一(不能重复),可以为 NULL(比如 user 表的 phone 字段,手机号不能重复)。

  • 通俗理解:字典的 "身份证号目录",每个身份证号对应唯一的人,不能重复,但可以有空缺(比如有人没提供)。

  • 用法

    复制代码
    -- 给 phone 字段加唯一索引(防止重复手机号)
    CREATE UNIQUE INDEX idx_user_phone ON user(phone);
五、InnoDB 的索引核心:B + 树结构

InnoDB 用的是 B + 树 做索引(就像一棵 "倒过来的树"),特点是:

  • 叶子节点(最底层)存的是实际数据(或数据地址),查询时只需要遍历到叶子节点,效率稳定;

  • 所有数据都在叶子节点,且叶子节点之间是 "链表" 结构(双向链表),方便范围查询(比如 WHERE id BETWEEN 100 AND 200)。

简单说:这种结构让查询 "又快又稳",不管查哪个数据,都要走差不多的步骤,不会出现 "有时候快有时候慢" 的情况。

索引怎么用?
  1. 建表时给主键(id)加主键索引(自动加,不用手动);

  2. 给经常查询、排序的字段加普通索引;

  3. 给需要唯一约束的字段(手机号、邮箱)加唯一索引;

  4. 别乱加索引,够用就行!

日常开发中,只要记住 "索引 = 字典目录",就知道什么时候该加、什么时候不该加啦~

SQL性能分析

复制代码
show global status like 'com_______';   //查看当前数据库增删改查的访问次数
慢查询日志

慢查询日志就是 MySQL 的 "慢动作记录仪"------ 专门盯着所有执行的 SQL 语句,只要某条 SQL 执行时间超过你设定的 "阈值"(默认是 10 秒,实际开发中一般设 1~3 秒),就把这条 SQL 的 "作案细节"(执行时间、执行用户、执行时间点、SQL 语句本身)记下来,方便你后续排查 "谁拖慢了数据库"。

举个例子:你做电商网站,用户反映 "下单要等 5 秒",打开慢查询日志一看,发现 SELECT * FROM order WHERE user_id=123 这条 SQL 执行了 4.8 秒,超过了你设的 3 秒阈值,日志里还记着它没走索引、扫描了 10 万行数据 ------ 这就找到 "罪魁祸首" 了,接下来只要给 user_id 加个索引,就能提速。

核心用法就 3 个关键点,通俗说:

  1. 先 "打开记录仪":开启慢查询日志功能(默认是关的,需要手动开);

  2. 设 "触发条件":比如设定 "执行超过 2 秒的 SQL 就记录";

  3. 看 "记录报告":从日志文件里找慢 SQL,针对性优化(比如加索引、简化 SQL)。

简单总结:慢查询日志就是帮你抓 "拖后腿的 SQL" 的工具,有了它,不用瞎猜哪条 SQL 慢,直接看日志就知道该优化啥~

profile详细

Profile 就是 MySQL 里给 SQL 做 "精准计时" 的工具 ------ 像给 SQL 装了个秒表,把它执行的每一步(比如解析语法、查索引、读数据、排序)都拆开来,告诉你每步花了多少时间,精准找到 "慢在哪",比慢查询日志更细。

核心用法
  1. 查询profile: select @@have_profiling; //查询当前是否有profile操作

  2. 开开关:SET profiling = ON/1;(临时生效,关了终端就没了)

  3. 跑 SQL:执行你要分析的语句(比如 SELECT * FROM order WHERE user_id=123;

  4. 看结果:

  • 先看所有记录的 SQL:SHOW PROFILES;(拿到要分析的 SQL 编号,比如 Query_ID=1)

  • 再看详细步骤耗时:SHOW PROFILE FOR QUERY 1;(把 1 换成你的 Query_ID)

关键看什么?

结果里会列一堆步骤,重点盯耗时最长的:

  • 比如 "Retrieving Data"(读数据)久→索引没建好,加索引;

  • "Sorting Result"(排序)久→排序字段没加索引;

  • "Copying to tmp table"(临时表)久→分组 / 连接逻辑要优化。

慢查询日志告诉你 "哪条 SQL 慢",Profile 告诉你 "这条 SQL 慢在哪个步骤",优化时精准下手,不用瞎改

explain执行计划

EXPLAIN 就是 MySQL 的 "SQL 执行计划预览器" ------ 不用真的执行 SQL,就能提前看到 MySQL 会怎么执行这条 SQL(比如走不走索引、扫描多少行数据、用什么连接方式),帮你预判 SQL 有没有效率问题,从源头避免慢查询。

核心用法

在你要分析的 SQL 前面加 EXPLAIN 就行,比如:

sql 复制代码
-- 原SQL:查询用户订单
SELECT * FROM order WHERE user_id=123 ORDER BY create_time;
​
-- 加EXPLAIN查看执行计划
EXPLAIN SELECT * FROM order WHERE user_id=123 ORDER BY create_time;

执行后会返回一张 "执行计划表",不用看复杂字段,盯 3 个核心信息就够了!

重点看 3 列
列名 通俗含义 好情况 坏情况
type MySQL 查找数据的 "方式"(效率从高到低) 出现 refrange(走索引) 出现 ALL(全表扫描,没走索引)
key 实际用到的索引名称 显示你建的索引(比如 idx_user_id 显示 NULL(没用到任何索引)
rows MySQL 预估要扫描的行数 数字越小越好(比如几十、几百) 数字极大(比如几万、几十万,扫全表)
例子 1:好的执行计划

type=ref,key=idx_user_id,rows=50→ 解读:MySQL 走了 user_id 的索引,只需要扫 50 行就能找到数据,效率高!

例子 2:坏的执行计划

type=ALL,key=NULL,rows=100000→ 解读:MySQL 没走任何索引,要扫描 10 万行数据(全表扫),肯定慢!优化方向:给 user_id 加索引。

如果 Extra 列出现 Using filesort(文件排序)或 Using temporary(临时表),说明 SQL 里的 ORDER BYGROUP BY 没用到索引,需要给排序 / 分组字段加索引,比如给 create_time 加索引,就能消除这两个提示。

一句话总结

EXPLAIN 是 "SQL 体检工具"------ 写好 SQL 后先跑一遍 EXPLAIN,只要 type 不是 ALL、key 不为 NULL、rows 不大,这条 SQL 基本就高效;反之就针对性加索引、改查询条件,不用等上线才发现慢!

相关推荐
数据库小组42 分钟前
2026 年,MySQL 到 SelectDB 同步为何更关注实时、可观测与可校验?
数据库·mysql·数据库管理工具·数据同步·ninedata·selectdb·迁移工具
华科易迅44 分钟前
MybatisPlus增删改查操作
android·java·数据库
Kethy__1 小时前
计算机中级-数据库系统工程师-计算机体系结构与存储系统
大数据·数据库·数据库系统工程师·计算机中级
SHoM SSER1 小时前
MySQL 数据库连接池爆满问题排查与解决
android·数据库·mysql
熬夜的咕噜猫2 小时前
MySQL备份与恢复
数据库·oracle
jnrjian2 小时前
recover database using backup controlfile until cancel 假recover,真一致
数据库·oracle
lifewange2 小时前
java连接Mysql数据库
java·数据库·mysql
大妮哟3 小时前
postgresql数据库日志量异常原因排查
数据库·postgresql·oracle
还是做不到嘛\.3 小时前
Dvwa靶场-SQL Injection (Blind)-基于sqlmap
数据库·sql·web安全
不写八个4 小时前
PHP教程004:php链接mysql数据库
数据库·mysql·php