Mysql--14

一、InnoDB 数据组织与主键基础

1. 索引组织表(IOT)

InnoDB 存储引擎中,表数据按主键顺序组织存储 ,这种表称为索引组织表(Index Organized Table, IOT),主键索引即聚簇索引,数据和索引存储在一起。

2. InnoDB 逻辑存储结构

表格

层级 说明 大小
表空间(Tablespace) 最高层级,管理所有段 -
段(Segment) 管理多个区,分为数据段、索引段等 -
区(Extent) 连续的页集合,避免碎片 1MB(固定 64 个页)
页(Page) InnoDB 最小存储单元,数据存储的基础 16KB(默认)
行(Row) 实际数据行,包含事务 ID、回滚指针、业务字段 -

二、主键优化核心

1. 页分裂与页合并

(1)页分裂
  • 原理:InnoDB 页按主键顺序存储,当向已满的页乱序插入数据时,需将页分裂为两个,移动一半数据到新页,产生额外 IO,严重影响性能。
  • 触发场景:主键乱序插入、UUID 等无序主键插入。
  • 影响:导致页空间利用率降低、IO 开销剧增、插入性能下降。
(2)页合并
  • 原理:删除数据时仅标记删除,不物理删除;当页中删除数据达到 MERGE_THRESHOLD(默认页大小的 50%)时,InnoDB 会尝试与相邻页合并,优化空间。
  • 补充:MERGE_THRESHOLD 可在创建表 / 索引时自定义,调整合并阈值。

2. 主键设计原则

  1. 满足业务需求的前提下,尽量降低主键长度主键长度越小,索引体积越小,IO 开销越低,缓存命中率越高。
  2. 优先顺序插入,使用 AUTO_INCREMENT 自增主键自增主键保证顺序插入,完全避免页分裂,插入性能最优。
  3. 禁止使用 UUID、身份证号等无序自然主键无序主键会导致频繁页分裂,严重拖慢插入性能,同时索引体积膨胀。
  4. 业务操作中,避免修改主键主键修改会触发数据移动、索引重构,产生大量 IO,影响性能。

3. 大批量插入优化

  • 问题:批量插入时,普通 INSERT 语句性能低下。

  • 解决方案:使用 LOAD DATA LOCAL INFILE 批量导入,步骤如下:

    sql

    复制代码
    -- 1. 客户端连接时开启本地文件权限
    mysql --local-infile -u root -p
    
    -- 2. 开启全局本地文件开关
    SET GLOBAL local_infile = 1;
    
    -- 3. 执行批量导入
    LOAD DATA LOCAL INFILE '/root/sql1.log' 
    INTO TABLE `tb_user` 
    FIELDS TERMINATED BY ',' 
    LINES TERMINATED BY '\n';
  • 关键结论:主键顺序插入性能远高于乱序插入


三、ORDER BY 优化

1. 两种排序方式

表格

排序方式 说明 性能
Using filesort 通过索引 / 全表扫描读取数据,在排序缓冲区(sort buffer)中完成排序,所有非索引直接返回的排序都属于此类 低(需额外排序)
Using index 直接通过有序索引顺序扫描返回有序数据,无需额外排序 高(最优)

2. ORDER BY 优化原则

  1. 为排序字段建立合适索引,多字段排序遵循最左前缀法则联合索引需从最左列开始,才能命中索引排序,避免 filesort。
  2. 尽量使用覆盖索引让查询字段全部包含在索引中,避免回表,同时提升排序效率。
  3. 多字段排序注意升降序一致性 若一个升序、一个降序,需在创建联合索引时指定对应 ASC/DESC,否则无法命中索引。
  4. filesort 优化:增大排序缓冲区 若无法避免 filesort,大数据量场景下可增大 sort_buffer_size(默认 256KB),减少磁盘排序,提升性能。

四、GROUP BY 优化

1. 核心原理

GROUP BY 本质是先排序再分组,因此优化逻辑与 ORDER BY 高度一致,核心是利用索引避免排序

2. 优化示例

sql

复制代码
-- 1. 删除原有联合索引
DROP INDEX idx_user_pro_age_sta ON tb_user;

-- 2. 无索引分组:触发filesort,性能低
EXPLAIN SELECT profession, COUNT(*) FROM tb_user GROUP BY profession;

-- 3. 创建联合索引(遵循最左前缀)
CREATE INDEX idx_user_pro_age_sta ON tb_user(profession, age, status);

-- 4. 有索引分组:直接利用索引有序性,无需排序,性能高
EXPLAIN SELECT profession, COUNT(*) FROM tb_user GROUP BY profession;
EXPLAIN SELECT profession, COUNT(*) FROM tb_user GROUP BY profession, age;

3. 优化原则

  1. 分组操作可通过索引大幅提升效率
  2. 分组索引使用严格遵循最左前缀法则
  3. 优先使用覆盖索引,避免回表,进一步提升性能。

五、与前文索引体系的联动补充

1. 索引设计原则(补充)

  • 针对数据量大、查询频繁的表建索引
  • 针对 WHERE/ORDER BY/GROUP BY 字段建索引
  • 选择区分度高的列,优先唯一索引
  • 长字符串使用前缀索引
  • 优先联合索引,减少单列索引
  • 控制索引数量,避免影响增删改
  • 索引列尽量设置 NOT NULL 约束

2. 索引失效场景(回顾)

  • 违反最左前缀法则
  • 范围查询右侧列
  • 字符串不加引号
  • 头部模糊查询 LIKE '%xxx'
  • OR 条件中存在无索引列
  • 索引列参与运算 / 函数
  • MySQL 评估全表扫描更快时
相关推荐
014-code2 小时前
Java Optional 那些被忽略的用法
java·数据库·javase
qq_283720052 小时前
MySQL实战(十五): 常用内置函数实战--日期、字符串、数学函数从入门到精通
mysql·内置函数·日期函数·字符函数·日期计算
码云数智-园园2 小时前
关系型与非关系型数据库:核心区别与业务场景解析
数据库·oracle
Javatutouhouduan2 小时前
SQL优化从入门到精通!
java·数据库·mysql·sql优化·java面试·后端开发·java程序员
jnrjian2 小时前
restore archivelog RAC thread from sequence logseq
服务器·数据库
小草儿7992 小时前
PG18之插件使用大全(简单用例)
数据库
Elastic 中国社区官方博客2 小时前
从 Elasticsearch runtime fields 到 ES|QL:将传统工具适配到当前技术
大数据·数据库·sql·elasticsearch·搜索引擎·全文检索
刘晨鑫12 小时前
MySQL主从复制与读写分离
数据库·mysql·adb
ClouGence2 小时前
数据迁移同步工具 CloudCanal-v5.5.0.0 发布,支持 RETL(定时扫描同步)
数据库·mysql·postgresql·oracle·sqlserver·kafka·etl