MySQL的聚簇索引与非聚簇索引
前言
首先我们要了解到,聚簇索引只能有一个,而非聚簇可以有多个。在本文中可以了解到,范围查询时聚簇索引的优势,以及非聚簇索引在频繁更新时的劣势。
在MySQL中,主键索引通常就是聚簇索引,如果没有显式定义主键,InnoDB会选择一个唯一非空索引代替,如果都没有,会生成隐藏的ROWID作为聚簇索引。
一个用户表,id是主键,作为聚簇索引,数据按id顺序存储。而如果有一个非聚簇索引在email字段上,索引存储的是email和对应的主键id,查询时需要回表操作,即通过email索引找到id,再通过id找到完整数据行。这样回表会影响性能,尤其是当需要大量数据时。
这就要提到覆盖索引的概念,即如果非聚簇索引包含了查询所需的所有字段,就可以避免回表,提升性能。比如,如果查询只需要email和id,那么email索引已经包含这些信息,无需回表。
另外,本文需要讨论不同存储引擎的情况。比如,MyISAM使用的是非聚簇索引,而InnoDB使用的是聚簇索引。这直接影响了选择存储引擎时的考量,比如MyISAM在查询时可能需要更多的磁盘I/O,而InnoDB在范围查询时更高效。
还需要解释索引的结构,比如B+树,以及聚簇索引和非聚簇索引在B+树中的不同组织形式。聚簇索引的叶子节点直接存储数据行,而非聚簇索引的叶子节点存储的是主键值或指向数据行的指针。
在实际的应用场景中,高并发写入的环境下,聚簇索引的顺序插入可能导致页分裂,影响性能,而非聚簇索引的更新可能更频繁,需要维护多个索引结构,增加写操作的开销。这时候可能需要权衡索引的数量和类型,以优化整体性能。
在最后一章节中,本文会总结聚簇索引和非聚簇索引的优缺点,以及适用场景。比如,聚簇索引适合主键查询和范围查询,而非聚簇索引适合辅助查询,但需要注意回表带来的性能问题。以及给出相应的优化建议。
MySQL中的索引是优化查询性能的关键工具,而聚簇索引(Clustered Index)和非聚簇索引(Non-Clustered Index)是两种核心索引类型。它们的实现原理和适用场景有显著差异,理解这些差异对数据库设计和性能优化至关重要。以下章节从存储结构、工作原理、优缺点及实际应用进行全面分析。
一、聚簇索引(Clustered Index)
1. 定义与特性
- 存储方式:数据行的物理存储顺序与索引顺序完全一致。
- 唯一性:每个表只能有一个聚簇索引(因为数据只能按一种方式物理排序)。
- 默认行为:在InnoDB引擎中,主键(Primary Key)自动成为聚簇索引。若未定义主键,InnoDB会选择第一个唯一非空索引(UNIQUE NOT NULL)作为聚簇索引;若两者均无,则隐式生成一个6字节的
ROWID作为聚簇索引。
2. 数据结构
-
B+树结构:
- 叶子节点:直接存储完整数据行(即数据页)。
- 非叶子节点:存储索引键值和指向子节点的指针。
B+树示意图(聚簇索引): 根节点 ├── 索引键值区间1 → 中间节点 │ ├── 索引键值区间1.1 → 叶子节点(数据行) │ └── 索引键值区间1.2 → 叶子节点(数据行) └── 索引键值区间2 → 中间节点
3. 优点
- 高效范围查询:相邻数据物理上连续存储,减少磁盘I/O。
- 主键查询极快:直接通过主键定位到数据行。
- 覆盖索引优化:若查询仅涉及索引列,无需回表。
4. 缺点
- 插入速度依赖顺序:若主键非自增,随机插入可能导致页分裂(Page Split),影响性能。
- 更新代价高:主键更新需移动数据行,导致额外开销。
5. 应用场景
- 主键查询:如
SELECT * FROM users WHERE id = 100。 - 范围查询:如
SELECT * FROM orders WHERE date BETWEEN '2023-01-01' AND '2023-01-31'。
二、非聚簇索引(Non-Clustered Index)
1. 定义与特性
- 存储方式:索引结构与数据行物理存储分离。
- 多索引支持:一个表可创建多个非聚簇索引。
- InnoDB实现:非聚簇索引的叶子节点存储主键值,而非直接指向数据行(需要回表查询)。
2. 数据结构
-
B+树结构:
- 叶子节点:存储索引键值 + 主键值(InnoDB)或数据行指针(MyISAM)。
- 非叶子节点:存储索引键值和指向子节点的指针。
B+树示意图(非聚簇索引): 根节点 ├── 索引键值区间1 → 中间节点 │ ├── 索引键值1.1 → 叶子节点(主键值) │ └── 索引键值1.2 → 叶子节点(主键值) └── 索引键值区间2 → 中间节点
3. 优点
- 灵活索引设计:可针对不同查询需求创建多个辅助索引。
- 减少写开销:更新非聚簇索引不影响数据行物理位置。
4. 缺点
- 回表查询:通过非聚簇索引找到主键后,需二次查询聚簇索引获取完整数据,增加I/O。
- 范围查询效率低:非连续存储需多次磁盘寻址。
5. 应用场景
- 辅助查询:如通过
email字段快速定位用户ID,再通过主键获取完整数据。 - 覆盖索引优化:若索引包含查询所需所有字段,避免回表(如
SELECT email FROM users WHERE email = 'user@example.com')。
三、聚簇索引 vs 非聚簇索引对比
| 特性 | 聚簇索引 | 非聚簇索引 |
|---|---|---|
| 索引数量 | 每个表仅一个 | 可创建多个 |
| 存储内容 | 数据行与索引一体 | 索引键值 + 主键(InnoDB)或指针(MyISAM) |
| 查询性能 | 主键/范围查询快,避免回表 | 需回表,覆盖索引时高效 |
| 插入性能 | 主键顺序插入快,随机插入可能页分裂 | 无数据移动,插入较快 |
| 更新代价 | 主键更新代价高 | 仅更新索引结构,代价较低 |
| 适用场景 | 主键查询、范围扫描 | 辅助查询、覆盖索引 |
四、存储引擎差异
1. InnoDB
- 聚簇索引:主键索引为聚簇索引,数据按主键顺序存储。
- 非聚簇索引:叶子节点存储主键值,需回表查询。
2. MyISAM
- 无聚簇索引:所有索引均为非聚簇索引。
- 数据存储:数据行独立存储(
.MYD文件),索引存储指向数据行的指针(.MYI文件)。
五、实战优化建议
-
合理设计主键:
- 使用自增整数(
AUTO_INCREMENT)减少页分裂。 - 避免使用频繁更新的字段作为主键。
- 使用自增整数(
-
覆盖索引优化:
- 将查询字段包含在索引中,避免回表。
-- 创建覆盖索引 CREATE INDEX idx_user_email ON users(email, name); -- 查询仅需索引即可完成 SELECT email, name FROM users WHERE email = 'user@example.com'; -
控制索引数量:
- 非聚簇索引过多会增加写操作开销,需权衡读写比例。
-
范围查询优先聚簇索引:
- 若查询条件涉及范围,尽量使用聚簇索引字段。
六、示例分析
场景:用户表查询
-
表结构:
CREATE TABLE users (id INT PRIMARY KEY AUTO_INCREMENT, -- 聚簇索引email VARCHAR(100) UNIQUE, -- 非聚簇索引(UNIQUE约束)name VARCHAR(100),INDEX idx_name (name) -- 非聚簇索引 ) ENGINE=InnoDB; -
查询1:
SELECT * FROM users WHERE id = 100;- 路径:直接通过聚簇索引找到数据行,无需回表,效率高。
-
查询2:
SELECT * FROM users WHERE email = 'user@example.com';- 路径:通过
email索引找到主键id,再通过聚簇索引回表查询,效率较低。
- 路径:通过
-
查询3:
SELECT name FROM users WHERE name LIKE 'John%';- 路径:若
idx_name包含name字段,直接通过索引返回结果,避免回表。
- 路径:若
七、总结
- 聚簇索引:数据与索引一体,适合主键和范围查询,但需注意插入顺序。
- 非聚簇索引:独立存储,适合辅助查询和覆盖索引,但可能需回表。
- 优化核心:根据查询模式设计索引,减少回表操作,平衡读写性能。
相关文章:
MySQL的聚簇索引与非聚簇索引
前言 首先我们要了解到,聚簇索引只能有一个,而非聚簇可以有多个。在本文中可以了解到,范围查询时聚簇索引的优势,以及非聚簇索引在频繁更新时的劣势。 在MySQL中,主键索引通常就是聚簇索引,如果没有显式…...
vscode的一些实用操作
1. 焦点切换(比如主要用到使用快捷键在编辑区和终端区进行切换操作) 2. 跳转行号 使用ctrl g,然后输入指定的文件内容,即可跳转到相应位置。 使用ctrl p,然后输入指定的行号,回车即可跳转到相应行号位置。...
C++11 thread
文章目录 C11 线程库线程对象的构造方式无参的构造函数调用带参的构造函数调用移动构造函数thread常用成员函数 this_thread命名空间join && detachmutex C11 线程库 线程对象的构造方式 无参的构造函数 1、调用无参的构造函数,调用无参的构造函数创建出来的线程对象…...
rabbitmq五种模式的总结——附java-se实现(详细)
rabbitmq五种模式的总结 完整项目地址:https://github.com/9lucifer/rabbitmq4j-learning 一、简单模式 (一)简单模式概述 RabbitMQ 的简单模式是最基础的消息队列模式,包含以下两个角色: 生产者:负责发…...
Qt中基于开源库QRencode生成二维码(附工程源码链接)
目录 1.QRencode简介 2.编译qrencode 3.在Qt中直接使用QRencode源码 3.1.添加源码 3.2.用字符串生成二维码 3.3.用二进制数据生成二维码 3.4.界面设计 3.5.效果展示 4.注意事项 5.源码下载 1.QRencode简介 QRencode是一个开源的库,专门用于生成二维码&…...
Java数据结构---链表
目录 一、链表的概念和结构 1、概念 2、结构 二、链表的分类 三、链表的实现 1、创建节点类 2、定义表头 3、创建链表 4、打印链表 5、链表长度 6、看链表中是否包含key 7、在index位置插入val(0下标为第一个位置) 8、删除第一个关键字key …...
mongodb是怎么分库分表的
在构建高性能的数据库架构时,MongoDB的分库分表策略扮演着至关重要的角色,它通过一系列精细的步骤确保了数据的高效分布与访问。以下是对这一过程的详尽阐述,旨在提供一个清晰且优化过的理解框架。 确定分片键(Shard Key…...
C++自研游戏引擎-碰撞检测组件-八叉树AABB检测算法实现
八叉树碰撞检测是一种在三维空间中高效处理物体碰撞检测的算法,其原理可以类比为一个管理三维空间物体的智能系统。这个示例包含两个部分:八叉树部分用于宏观检测,AABB用于微观检测。AABB可以更换为均值或节点检测来提高检测精度。 八叉树的…...
spring boot对接clerk 实现用户信息获取
在现代Web应用中,用户身份验证和管理是一个关键的功能。Clerk是一个提供身份验证和用户管理的服务,可以帮助开发者快速集成这些功能。在本文中,我们将介绍如何使用Spring Boot对接Clerk,以实现用户信息的获取。 1.介绍 Clerk提供…...
一种动态地址的查询
背景 当我们注入一个进程,通过函数地址进行call时经常会遇到这样的一个问题。对方程序每周四会自动更新。更新后之前的函数地址就变化了,然后需要重新找地址。所以,我就使用了一个动态查询的方式。 第一步:先为需要call的函数生…...
周雨彤:用角色与生活,诠释审美的艺术
提到内娱审美优秀且持续在线的女演员,周雨彤绝对是其中最有代表性的一个。 独树一帜的表演美学 作为新生代演员中的实力派代表,周雨彤凭借细腻的表演和对角色的深度共情,在荧幕上留下了多个令人难忘的“出圈”形象。在《我在他乡挺好的》中…...
使用jks给空apk包签名
1、在平台官方下载空的apk包(上传应用时有提醒下载) 2、找到jdk目录,比如C:\Program Files\Java\jdk1.8\bin,并把下载的空包apk和jks文件放到bin下 3、以管理员身份运行cmd,如果不是管理员会签名失败 4、用cd定位到…...
500. 键盘行 771. 宝石与石头 简单 find接口的使用
500. 键盘行1 给你一个字符串数组 words ,只返回可以使用在 美式键盘 同一行的字母打印出来的单词。键盘如下图所示。 请注意,字符串 不区分大小写,相同字母的大小写形式都被视为在同一行。 美式键盘 中: 第一行由字符 "qwer…...
仙剑世界手游新手攻略 仙剑世界能用云手机玩吗
欢迎来到《仙剑世界》手游的仙侠世界!作为新手玩家,以下是一些详细的攻略和建议,帮助你快速上手并享受游戏的乐趣。 一、新手职业推荐 1.轩辕:这是一个偏辅助的职业,可以给队友提供输出加成等增益效果,不过…...
[题解]2024CCPC重庆站-小 C 的神秘图形
Sources:K - 小 C 的神秘图形Abstract:给定正整数 n ( 1 ≤ n ≤ 1 0 5 ) n(1\le n\le 10^5) n(1≤n≤105),三进制字符串 n 1 , n 2 ( ∣ n 1 ∣ ∣ n 2 ∣ n ) n_1,n_2(|n_1||n_2|n) n1,n2(∣n1∣∣n2∣n),按如下方法…...
NPS内网穿透SSH使用手册
1、说明 nps-一款轻量级、高性能、功能强大的内网穿透代理服务器 github地址:https://github.com/ehang-io/nps 官网文档地址:https://ehang-io.github.io/nps/#/?idnps 2、服务端 下载地址:https://github.com/ehang-io/nps/releases 下…...
大幂计算和大阶乘计算【C语言】
大幂计算: #include<stdio.h> long long int c[1000000]{0}; int main() {long long a,b,x1;c[0]1;printf("请输入底数:");scanf("%lld",&a);printf("请输入指数:");scanf("%lld",&b…...
【Linux】详谈 进程控制
目录 一、进程是什么 二、task_struct 三、查看进程 四、创建进程 4.1 fork函数的认识 4.2 2. fork函数的返回值 五、进程终止 5.1. 进程退出的场景 5.2. 进程常见的退出方法 5.2.1 从main返回 5.2.1.1 错误码 5.2.2 exit函数 5.2.3 _exit函数 5.2.4 缓冲区问题补…...
Linux top 命令
作用 top 是一个实时系统监控工具,用于查看系统的资源使用情况和进程状态。 示例 以下是一些常用的 top 命令示例: top :动态显示结果,每 3 秒刷新一次。 top -d 2:动态显示结果,每 2 秒刷新一次。 top …...
Leetcode 424-替换后的最长重复字符
给你一个字符串 s 和一个整数 k 。你可以选择字符串中的任一字符,并将其更改为任何其他大写英文字符。该操作最多可执行 k 次。 在执行上述操作后,返回 包含相同字母的最长子字符串的长度。 题解 可以先做LCR 167/Leetcode 03再做本题 滑动窗口&…...
日语AI面试高效通关秘籍:专业解读与青柚面试智能助攻
在如今就业市场竞争日益激烈的背景下,越来越多的求职者将目光投向了日本及中日双语岗位。但是,一场日语面试往往让许多人感到步履维艰。你是否也曾因为面试官抛出的“刁钻问题”而心生畏惧?面对生疏的日语交流环境,即便提前恶补了…...
ServerTrust 并非唯一
NSURLAuthenticationMethodServerTrust 只是 authenticationMethod 的冰山一角 要理解 NSURLAuthenticationMethodServerTrust, 首先要明白它只是 authenticationMethod 的选项之一, 并非唯一 1 先厘清概念 点说明authenticationMethodURLAuthenticationChallenge.protectionS…...
12.找到字符串中所有字母异位词
🧠 题目解析 题目描述: 给定两个字符串 s 和 p,找出 s 中所有 p 的字母异位词的起始索引。 返回的答案以数组形式表示。 字母异位词定义: 若两个字符串包含的字符种类和出现次数完全相同,顺序无所谓,则互为…...
【论文阅读28】-CNN-BiLSTM-Attention-(2024)
本文把滑坡位移序列拆开、筛优质因子,再用 CNN-BiLSTM-Attention 来动态预测每个子序列,最后重构出总位移,预测效果超越传统模型。 文章目录 1 引言2 方法2.1 位移时间序列加性模型2.2 变分模态分解 (VMD) 具体步骤2.3.1 样本熵(S…...
使用Matplotlib创建炫酷的3D散点图:数据可视化的新维度
文章目录 基础实现代码代码解析进阶技巧1. 自定义点的大小和颜色2. 添加图例和样式美化3. 真实数据应用示例实用技巧与注意事项完整示例(带样式)应用场景在数据科学和可视化领域,三维图形能为我们提供更丰富的数据洞察。本文将手把手教你如何使用Python的Matplotlib库创建引…...
免费数学几何作图web平台
光锐软件免费数学工具,maths,数学制图,数学作图,几何作图,几何,AR开发,AR教育,增强现实,软件公司,XR,MR,VR,虚拟仿真,虚拟现实,混合现实,教育科技产品,职业模拟培训,高保真VR场景,结构互动课件,元宇宙http://xaglare.c…...
Python 训练营打卡 Day 47
注意力热力图可视化 在day 46代码的基础上,对比不同卷积层热力图可视化的结果 import torch import torch.nn as nn import torch.optim as optim from torchvision import datasets, transforms from torch.utils.data import DataLoader import matplotlib.pypl…...
ZYNQ学习记录FPGA(一)ZYNQ简介
一、知识准备 1.一些术语,缩写和概念: 1)ZYNQ全称:ZYNQ7000 All Pgrammable SoC 2)SoC:system on chips(片上系统),对比集成电路的SoB(system on board) 3)ARM:处理器…...
2025年低延迟业务DDoS防护全攻略:高可用架构与实战方案
一、延迟敏感行业面临的DDoS攻击新挑战 2025年,金融交易、实时竞技游戏、工业物联网等低延迟业务成为DDoS攻击的首要目标。攻击呈现三大特征: AI驱动的自适应攻击:攻击流量模拟真实用户行为,差异率低至0.5%,传统规则引…...
【QT控件】显示类控件
目录 一、Label 二、LCD Number 三、ProgressBar 四、Calendar Widget QT专栏:QT_uyeonashi的博客-CSDN博客 一、Label QLabel 可以用来显示文本和图片. 核心属性如下 代码示例: 显示不同格式的文本 1) 在界面上创建三个 QLabel 尺寸放大一些. objectName 分别…...
