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

Mysql 中数据主键类型不一样导致数据插入速度快慢问题

在 MySQL 数据库中,主键是自增的 BIGINT 类型主键是 UUID 字符串类型 的情况下,插入数据的速度通常是不一样的,并且 BIGINT 类型通常比 UUID 更快。以下是主要的影响因素:

1. 索引结构的影响

MySQL 的 InnoDB 存储引擎使用 B+ 树索引 作为主键索引。

  • 自增 BIGINT(顺序插入)
    • 自增主键是单调递增的,新插入的记录会顺序追加到 B+ 树的叶子节点末尾,索引结构相对稳定。
    • 由于数据总是往后追加,几乎不会导致页分裂(page split),插入性能更高。
  • UUID(随机插入)
    • UUID 是随机分布的,新插入的记录可能落在索引树的不同位置,导致频繁的 页分裂页面重组
    • 频繁的索引调整会导致更多的磁盘 I/O 操作,从而降低插入速度。

2. 数据存储的影响

  • BIGINT(8 字节)
    • 占用 8 字节,存储紧凑,索引占用的空间较小,数据查询效率更高。
  • UUID(通常是 VARCHAR(36)BINARY(16)
    • 如果是 VARCHAR(36),占用 36 字节,会使索引更大,影响查询和插入效率。
    • 如果使用 BINARY(16) 存储,会稍微优化存储效率,但仍然比 BIGINT 大。

3. 磁盘和缓存利用率

  • BIGINT 更小,索引页能容纳更多的索引项,减少磁盘 I/O,提高查询和插入速度。
  • UUID 更大,占用更多的索引页,导致数据库缓存命中率下降,从而影响整体性能。

4. 并发场景

  • 在高并发场景下,使用自增 BIGINT 可能会带来主键争用(INSERT 争用),但 MySQL 5.7+ 的 innodb_autoinc_lock_mode=2 可以缓解这个问题。
  • UUID 没有自增 ID 的锁争用问题,但由于随机性高,插入速度仍然较慢。

innodb_autoinc_lock_mode

innodb_autoinc_lock_mode=2 是 MySQL InnoDB 存储引擎中的一个自增锁模式,它可以优化并发插入时的性能。

innodb_autoinc_lock_mode 控制 InnoDB 在插入数据时如何处理自增(AUTO_INCREMENT)锁,主要影响并发插入的性能和一致性。它有 0、1、2 三种模式。

innodb_autoinc_lock_mode 的取值

取值模式名称作用
0传统模式(“traditional”)使用 表级 AUTO-INC 锁,严格保证自增 ID 连续,但并发性能较差。
1交错模式(“consecutive”) (默认模式)使用 轻量级的 AUTO-INC 锁,支持 批量插入 并提高并发性能。
2轻量级模式(“interleaved”)不使用 AUTO-INC 锁,使用 事务内部的自增分配机制,极大提高并发性能,但 ID 可能不连续。

innodb_autoinc_lock_mode=2 的作用

✅ 优势
  • 完全去掉 AUTO-INC 锁,提高并发性能
    • 适用于高吞吐量的插入,如 多线程 INSERT ... SELECTLOAD DATA
    • 特别适用于 主从复制(MySQL Replication),因为 ID 分配是事务内部完成的,无需额外的锁
  • REPLICA 复制模式下表现更优(防止锁等待)
❌ 代价
  • 自增 ID 可能出现不连续的跳跃(但通常这不是问题)
  • 适用于 “批量插入”(bulk inserts)和 “复制场景”,但如果是单行 INSERT,影响不大

innodb_autoinc_lock_mode 的适用场景

场景适用模式
低并发插入,要求 ID 连续0(传统模式)
一般业务,兼顾性能和唯一性1(默认模式)
高并发插入(批量导入、复制)2(轻量模式)

如何修改 innodb_autoinc_lock_mode

方式 1:临时修改
SET GLOBAL innodb_autoinc_lock_mode = 2;

⚠️ 需要重启连接才会生效

方式 2:永久修改(推荐)

修改 MySQL 配置文件 my.cnf

[mysqld]
innodb_autoinc_lock_mode = 2

然后 重启 MySQL 使其生效:

systemctl restart mysql

innodb_autoinc_lock_mode=2 示例

假设有如下表:

CREATE TABLE test_auto (
    id BIGINT AUTO_INCREMENT PRIMARY KEY,
    name VARCHAR(100)
) ENGINE=InnoDB;

对比 innodb_autoinc_lock_mode 的不同行为

传统模式 (0)
INSERT INTO test_auto (name) VALUES ('A');
INSERT INTO test_auto (name) VALUES ('B');
  • ID 可能是 1, 2
  • 即使并发插入,ID 依然保持严格递增
  • 由于表级 AUTO-INC 锁,并发性能较差
默认模式 (1)
INSERT INTO test_auto (name) VALUES ('C'), ('D');
  • ID 可能是 3, 4
  • 如果是 INSERT ... SELECT,批量分配 ID,提高性能
轻量模式 (2)
INSERT INTO test_auto (name) VALUES ('E'), ('F');
  • ID 可能是 7, 10(因为批量分配,不保证连续)
  • 并发性能最高,适用于高吞吐插入

总结

模式锁类型适用场景并发性能ID 是否连续
0表级锁低并发、严格 ID 递增
1自增锁 + 事务内分配一般业务(默认)基本连续
2无锁高并发批量插入、复制最高

什么时候用 innodb_autoinc_lock_mode=2

高并发插入(批量插入、INSERT ... SELECTLOAD DATA
主从复制(MySQL Replication)
数据导入、ETL 场景

如果业务允许 ID 不连续,建议使用 innodb_autoinc_lock_mode=2 来优化插入性能

结论:

  1. 自增 BIGINT 在插入时通常比 UUID 更快,尤其是在大量数据写入的场景下。
  2. 如果要使用 UUID,建议:
    • 使用 BINARY(16) 代替 VARCHAR(36) 来减少存储空间。
    • 使用 有序 UUID(如基于时间的 UUID,如 UUIDv1)来减少索引碎片。

如果插入性能是主要考虑因素,自增 BIGINT 仍然是更好的选择。如果需要全局唯一性(如分布式系统),可以优化 UUID 的存储方式以降低插入成本。

http://www.dtcms.com/a/108822.html

相关文章:

  • Java开发如何基于 Spring AI Alibaba 玩转 MCP:从发布、调用到 Claude Manus 集成
  • 2.5路径问题专题:LeetCode 64. 最小路径和
  • Python的三方库之Pandas(三)
  • MetaBase Mysql8.0连接不上
  • 怎么理解量子比特模型,迁移到量子计算机开始编程
  • 飞桨新一代框架3.0正式发布:加速大模型时代的技术创新与产业应用
  • AF3 OpenFoldMultimerDataset类解读
  • 洛谷题单3-P1035 [NOIP 2002 普及组] 级数求和-python-流程图重构
  • JavaScript日期对象
  • Python 编程实战:打造高效便捷的目录结构生成器
  • 踩坑ubuntu24.04 编译vtk9.3.1的安卓版本
  • 前端开发技术演进与就业现实:顺应时代方能不被淘汰-优雅草卓伊凡
  • ubantu执行sudo chown -R username xxx(文件夹)命令失效
  • 推荐系统(二十一):基于MaskNet的商品推荐CTR模型实现
  • OpenCV 图形API(12)用于计算图像或矩阵的平均值函数mean()
  • dify开启多租户模式
  • Coco-AI 支持嵌入,让你的网站拥有 AI 搜索力
  • 基于javaweb的SSM+Maven机房管理系统设计与实现(源码+文档+部署讲解)
  • 智慧高炉厂可视化:钢铁行业的数字化转型之路
  • leetcode31.下一个排列
  • 42.C++11-右值引用与移动语义/完美转发
  • Real-Time Anomaly Detection of Network Traffic Basedon CNN
  • 动、静态创建任务
  • 实战打靶集锦-37-Wpwnvm
  • GUI-Guider 按钮按下 选项卡 右移动一个,到最右边停下
  • BMS电池关键参数及其含义
  • Lua中debug调试函数详解
  • 【DLI】Generative AI with Diffusion Models通关秘籍
  • Redis基础知识-2
  • 从零构建大语言模型全栈开发指南:第五部分:行业应用与前沿探索-5.1.1百度ERNIE、阿里通义千问的技术对比