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

MySQL中索引全详解

第一部分:什么是索引

        索引在数据库中就像书的目录,能够快速定位数据位置,从而提升查询效率。没有索引时,数据库查询需要从头到尾扫描整个表(称为全表扫描),这在数据量大时非常耗时。有了索引后,查询就像查找字典中某个字母开头的单词一样,可以直接跳转到相关数据,大大加快了响应速度。

索引的原理可以简单理解为:

  • 数据库通过创建额外的“数据结构”(类似目录)存储索引字段的信息。
  • 查询时,数据库优先查找索引,再根据索引定位到实际数据。
  • 索引对查询速度有提升,但同时也会增加写入和更新的时间,因为每次修改表数据时,索引也需要维护和更新。

        简单总结,索引的核心作用是提高查询速度,但这是一种以额外存储和维护成本换取查询效率的优化方式。

第二部分:索引的分类

        我们按照三个角度来详细分析索引的分类:数据结构字段特性字段个数

1.按数据结构分类

        这是基于索引底层的存储和组织方式来划分的,常见的有以下三种:

1.1 B+Tree 索引

  1. 原理

    • B+Tree 索引是 MySQL 中最常用的索引结构,底层采用的是平衡多路搜索树。
    • 数据以“节点”的形式存储,叶子节点存储了表中所有的索引字段值,并以链表形式连接;非叶子节点作为目录,用于快速查找。
    • 查找过程:从根节点开始,依次向下遍历,直到叶子节点。
  2. 特点

    • 有序存储,支持范围查询。
    • 查询效率稳定,查找时间复杂度为 O(log⁡n)O(logn)。
    • 适用于大多数场景,包括等值查询、范围查询、排序等。
  3. 适用场景

    • 查询条件中包含范围操作(如 BETWEEN> <)。
    • 常见于主键索引和普通索引。
  4. 局限性

    • 如果字段值分布不均匀,可能导致某些查询的效率下降。
    • 对频繁插入或更新的大表性能有一定影响,因为需要维护树的平衡。

1.2 Hash 索引

  1. 原理

    • 使用哈希函数将字段值映射为哈希值,哈希值对应实际数据的位置。
    • 适合等值查询,类似于通过钥匙直接打开锁。
  2. 特点

    • 查询速度极快,时间复杂度接近 O(1)O(1)。
    • 不支持范围查询,因为哈希值无法保持顺序性。
    • 哈希冲突可能影响性能。
  3. 适用场景

    • 等值查询场景,例如 WHERE id = 10
    • 用于对性能要求极高、数据分布均匀的表。
  4. 局限性

    • 不支持范围查询(如 BETWEEN> <)。
    • 不适合排序或分组操作。

1.3 Full-Text 索引

  1. 原理

    • 专门为全文搜索设计的一种索引,类似搜索引擎的倒排索引。
    • 将文本内容切分为关键词,并建立关键词到文档的映射关系。
  2. 特点

    • 支持模糊查询、多关键字匹配。
    • 效率远高于使用 LIKE '%...%' 的查询方式。
  3. 适用场景

    • 对大文本字段(如文章、评论)进行搜索,例如实现类似搜索引擎的功能。
  4. 局限性

    • 配置复杂,只支持特定存储引擎(如 MyISAM、InnoDB 的部分版本)。
    • 对于频繁更新的大文本字段性能较差。

2. 按字段特性分类

        这是基于字段在表中的角色和限制条件来划分的,主要有以下几种:

2.1 主键索引

  1. 定义

    • 主键是表中的唯一标识,每张表只能有一个主键。主键索引是数据库默认为主键字段生成的索引。
  2. 特点

    • 唯一性,保证每行数据的主键值不同。
    • 主键索引一般使用 B+Tree 实现,叶子节点存储完整的行数据。
  3. 适用场景

    • 必须保证数据唯一性,例如用户 ID、订单号等。

2.2 唯一索引

  1. 定义

    • 唯一索引与主键类似,但表中可以有多个唯一索引。
    • 保证字段值唯一,但允许存在空值(NULL)。
  2. 特点

    • 避免重复值,确保数据完整性。
    • 唯一索引一般用于非主键字段。
  3. 适用场景

    • 确保特定字段的值不重复,例如邮箱、用户名等。

2.3 普通索引

  1. 定义

    • 没有唯一性限制,仅用于提升查询速度。
  2. 特点

    • 普通索引可以在任意字段上添加。
    • 支持多种查询操作(等值、范围等)。
  3. 适用场景

    • 提高查询效率,但对唯一性无严格要求的字段。

2.4 前缀索引

  1. 定义

    • 针对字符串字段,只索引前面几位字符,而不是整列。
  2. 特点

    • 节省存储空间,提升索引效率。
    • 对于区分度较高的字符串字段适用。
  3. 适用场景

    • 长字符串字段,如 URL、电子邮件地址等。

3. 按字段个数分类

这是根据字段数量来划分的,主要有以下两种:

3.1 单列索引

  1. 定义

    • 索引只包含一个字段。
  2. 特点

    • 适合简单的查询条件(单字段查询)。
    • 无法直接优化多字段组合查询。
  3. 适用场景

    • 单一字段的等值或范围查询。

3.2 联合索引(复合索引)

  1. 定义

    • 索引包含多个字段,以字段顺序为准。
  2. 特点

    • 支持最左前缀原则,即查询条件必须包含从左到右的字段顺序。
    • 高效优化多字段查询,但顺序很重要。
  3. 适用场景

    • 多字段组合查询,例如 WHERE col1 = ? AND col2 = ?

第三部分:何时需要/无需索引

1. 什么时候需要创建索引?

        创建索引的核心目的是优化查询性能,因此以下场景适合创建索引:

  1. 查询条件中频繁使用的字段

    • 如果某个字段经常出现在 WHEREJOINGROUP BY 或 ORDER BY 中,应该为该字段创建索引。例如:
SELECT * FROM orders WHERE customer_id = 1001;
    • 为 customer_id 创建索引可以显著提升查询速度。
  1. 数据量大的表

    • 对于大表,如果没有索引,查询时需要进行全表扫描,这会严重拖慢性能。
    • 例如,有一张订单表有上百万条数据,为订单号字段 order_id 创建索引,可以极大提高查找效率。
  2. 高频查询的字段

    • 如果一个字段经常用于查询,即便表数据量不大,也可以考虑创建索引,因为优化高频操作的效率尤为重要。
  3. 排序和分组操作的字段

    • 如果查询中包含排序(ORDER BY)或分组(GROUP BY),为相关字段创建索引可以加速操作。
SELECT product_id, COUNT(*) FROM sales GROUP BY product_id;

2. 什么时候不需要创建索引?

索引虽然有助于查询,但也有成本,以下情况不适合创建索引:

  1. 小表或结果集较大的查询

    • 如果表的数据量很小(例如几十条数据),索引的优化效果微乎其微,反而会增加维护成本。
    • 类似地,如果查询结果总是返回表的大部分数据(如 80% 以上),索引优化的意义不大。
  2. 更新频繁的字段

    • 索引需要在数据修改时同步更新,因此对于频繁更新的字段,创建索引可能导致写入性能下降。
    • 例如日志表中的 last_updated_time 字段频繁更新,此时不建议为其创建索引。
  3. 重复性高的字段

    • 如果字段的值高度重复,索引会失去意义。例如:性别字段 gender(只有男或女)在查询中不建议单独建立索引。
  4. 临时表或测试表

    • 临时数据表通常存活时间短,查询次数少,因此无需索引。

第四部分:优化索引的方法

        索引的设计和使用需要考虑性能和实际需求,以下是几种常见的优化索引的方法:

1. 前缀索引优化

场景和原理

  • 适用场景:当字段值较长(如字符串类型),且前缀部分可以区分大多数记录时,使用前缀索引既能节省存储空间,又能加速查询。
  • 原理:前缀索引只记录字段值的前 N 个字符,降低了索引的大小,但仍能起到查询加速的作用。

优化步骤

  1. 选择合适的前缀长度
  2. 选择长度时,需要保证前缀的区分度(即前缀的唯一性较高)。可以通过以下查询评估:
    SELECT COUNT(DISTINCT LEFT(column_name, N)) / COUNT(*) AS prefix_selectivity FROM table_name;
    • 如果区分度接近 1,说明前缀长度合适。
  3. 创建前缀索引
    • 使用 CREATE INDEX 指定前缀长度:
      CREATE INDEX idx_prefix ON users (email(10));

适用场景的示例
        假设有一个邮件用户表,每个用户的邮箱 email 字段长度不一,且查询通常只匹配前缀部分:

SELECT * FROM users WHERE email LIKE 'john%';

使用前缀索引可显著提升效率。

2. 覆盖索引优化

定义与优点

  • 覆盖索引:当索引本身包含了查询所需的全部字段,无需回表查询,即称为覆盖索引。
  • 优点:减少磁盘 I/O 和查询时间。

如何实现覆盖索引

  1. 设计包含所有查询字段的索引

    • 例如,针对以下查询:
      SELECT id, name FROM employees WHERE department_id = 10;
      可以创建覆盖索引:
      CREATE INDEX idx_covering ON employees (department_id, id, name);
    • 索引中的字段顺序很重要,应优先按查询条件出现的字段排列。
  2. 使用查询分析工具

    • 使用 EXPLAIN 分析查询是否使用了覆盖索引:
      EXPLAIN SELECT id, name FROM employees WHERE department_id = 10;

3. 主键索引最好是自增的

自增主键的优势

  1. 避免页分裂
    • 自增主键的值是递增的,因此每次插入数据时,新记录会追加到索引的最后一个叶子节点,避免了频繁的页分裂。
  2. 提升插入效率
    • 自增主键的插入是顺序的,减少了磁盘 I/O。

非自增主键的问题

  • 随机插入导致性能下降
    • 如果主键是随机值(如 UUID),新数据可能插入到索引的任意位置,导致频繁的页分裂和性能下降。

4. 防止索引失效

什么是索引失效?

  • 当查询无法使用已有索引时,称为索引失效。这会导致查询退化为全表扫描,性能显著下降。

常见导致索引失效的场景

  1. 使用函数或计算操作

    • 如以下查询会导致索引失效:
      SELECT * FROM orders WHERE YEAR(order_date) = 2023;
      • 解决方法:将计算移到索引之外:
        SELECT * FROM orders WHERE order_date >= '2023-01-01' AND order_date < '2024-01-01';
  2. 类型不匹配

    • 如果索引字段和查询条件的类型不一致,会导致索引失效。
      SELECT * FROM users WHERE phone_number = 12345; -- phone_number 是字符串类型
      • 解决方法:确保类型一致:
        SELECT * FROM users WHERE phone_number = '12345';
  3. 查询条件中使用 OR

    • 如果 OR 中的字段未全部使用索引,会导致索引失效。
      SELECT * FROM employees WHERE department_id = 10 OR name = 'Alice';
      • 解决方法:改为使用 UNION,确保每个查询条件单独使用索引:
        SELECT * FROM employees WHERE department_id = 10 UNION SELECT * FROM employees WHERE name = 'Alice';
  4. 模糊查询中通配符的位置

    • 以下查询会导致索引失效:
      SELECT * FROM products WHERE name LIKE '%phone';
      • 解决方法:避免通配符在前,或者考虑全文索引:
        SELECT * FROM products WHERE name LIKE 'iPhone%';

总结
        索引的优化不仅是设计阶段的任务,在实际使用中还需定期监控和调整,避免失效或过度索引,确保系统性能最佳。

相关文章:

MySQL中索引全详解

第一部分&#xff1a;什么是索引 索引在数据库中就像书的目录&#xff0c;能够快速定位数据位置&#xff0c;从而提升查询效率。没有索引时&#xff0c;数据库查询需要从头到尾扫描整个表&#xff08;称为全表扫描&#xff09;&#xff0c;这在数据量大时非常耗时。有了索引后&…...

vllm serve的参数大全及其解释

以下是 vllm serve 的常见参数说明以及它们的作用&#xff1a; 1. 基本参数 model_tag 说明&#xff1a;用于指定要加载的模型&#xff0c;可以是 Hugging Face 模型仓库中的模型名称&#xff0c;也可以是本地路径。示例&#xff1a;vllm serve "gpt-neo-2.7B"--co…...

2025职业院校技能大赛信息安全管理与评估(河北省) 任务书

2025职业院校技能大赛信息安全管理与评估--河北省 任务书 模块一网络平台搭建与设备安全防护任务1&#xff1a;网络平台搭建 &#xff08;50分&#xff09;任务2&#xff1a;网络安全设备配置与防护&#xff08;250分&#xff09; 模块二网络安全事件响应、数字取证调查、应用程…...

通过高德 JS API 实现H5端定位

实现步骤: 1、安装 amap-jsapi-loader 插件 npm install amap-jsapi-loader 2、对定位组件进行封装 gb-location组件 <script lang="ts" setup> import AMapLoader from @amap/amap-jsapi-loader; import {ref,defineExpose} from vue;let map = ref(nul…...

第J6周:RenseNeXt-50实战

&#x1f368; 本文为&#x1f517;365天深度学习训练营 中的学习记录博客&#x1f356; 原作者&#xff1a;K同学啊 文章目录 一、前言1、结构改进2、分组卷积 二、前期工作1.设置GPU2. 导入数据3. 查看数据 三、数据预处理1、加载数据2、配置数据集 四、构建网络1、导入包2、…...

JAVA八股与代码实践----接口与抽象类的区别和用法

接口和抽象类的区别 关键字abstractinterface 实例化不能直接实例化不能直接实例化 方法可以有抽象和具体方法只能有抽象方法&#xff08;Java 8 支持默认方法&#xff09; 变量可以有普通变量只能有常量 (public static final) 继承单继承多继承 构造函数可以定义不允许…...

详解 【AVL树】

AVL树实现 1. AVL的概念AVL树的实现2.1 AVL树的结点结构2.2 AVL树的插入2.2.1 AVL树的插入的一个大概操作&#xff1a;2.2.2 AVL树的平衡因子更新2.2.3 平衡因子的停止条件2.2.4 再不考虑旋转的角度上实现AVL树的插入 2.3 旋转2.3.1 旋转的原则2.3.2 右单旋2.2.3 右单旋代码实现…...

SQLite Having 子句

SQLite Having 子句 SQLite 是一种轻量级的数据库管理系统&#xff0c;广泛应用于移动设备和嵌入式系统。它支持标准的 SQL 语法&#xff0c;包括 SELECT 语句中的 HAVING 子句。HAVING 子句通常与 GROUP BY 子句一起使用&#xff0c;用于对分组后的结果进行条件过滤。 SQLit…...

ZYNQ-7020嵌入式系统学习笔记(1)——使用ARM核配置UART发送Helloworld

本工程实现调用ZYNQ-7000的内部ARM处理器&#xff0c;通过UART给电脑发送字符串。 硬件&#xff1a;正点原子领航者-7020 开发平台&#xff1a;Vivado 2018、 SDK 1 Vivado部分操作 1.1 新建工程 设置工程名&#xff0c;选择芯片型号。 1.2 添加和配置PS IP 点击IP INTEGR…...

实践篇:青果IP助理跨境电商的高效采集

写在前面&#xff1a; 近年来&#xff0c;跨境电商行业迅速崛起&#xff0c;成为全球贸易的重要组成部分。据市场调研机构Statista数据显示&#xff0c;2024年全球跨境电商市场规模预计将突破5万亿美元&#xff0c;覆盖数十亿消费者。跨境电商的竞争日益激烈&#xff0c;商家不…...

本地安装YAPI

项目中用到很多的RESTAPI&#xff0c;光靠人工管理或者普通文档肯定是不行的&#xff0c;翻了很多的RESTAPI管理工具&#xff0c;还是选择了YAPI&#xff0c;原因有2&#xff0c;一个是接口位于内网&#xff0c;外网网站上管理测试不到内网接口&#xff0c;另外一个是使用方式&…...

pytest日志总结

pytest日志分为两类&#xff1a; 一、终端&#xff08;控制台&#xff09;打印的日志 1、指定-s&#xff0c;脚本中print打印出的信息会显示在终端&#xff1b; 2、pytest打印的summary信息&#xff0c;这部分是pytest 的默认输出&#xff08;例如测试结果PASSED, FAILED, S…...

day16

目录 1 联合体的定义和使用 2 联合体的内存布局 3 联合体的应用 1 联合体的定义和使用 #include <iostream>using namespace std;struct DataS {int i; double d; char s[10]; };/*联合体 所有成员共享同一段内存 修改一个成员会影响其他成员 { */ union DataU {int…...

医工交叉入门书籍分享:Transformer模型在机器学习领域的应用|个人观点·24-11-22

小罗碎碎念 今天给大家推荐一本入门书籍。 这本书由Uday Kamath、Kenneth L. Graham和Wael Emara撰写&#xff0c;深入探讨了Transformer模型在机器学习领域的应用&#xff0c;特别是自然语言处理&#xff08;NLP&#xff09;。 原文pdf已经上传至知识星球的【入门书籍】专栏&…...

【读书】复杂性意义结构框架——Cynefin框架

Cynefin框架 《代码大全》的作者史蒂夫麦克康奈尔&#xff08;Steve McConnell&#xff09;在《卓有成效的敏捷》这本书里&#xff0c;探讨了用于理解不确定性和复杂性的Cynefin框架。 Cynefin框架是戴维斯诺登&#xff08;David Snowden&#xff09;20世纪90年代的在IBM时创…...

Python模块、迭代器与正则表达式day10

1、Python模块 1.1模块的简介 在编写代码的时候&#xff0c;创建的.py文件就被称为一个模块 1.2模块的使用 想要在a文件里使用b文件的时候&#xff0c;只要在a文件中使用关键字import导入即可 1.2.2 from ...import...语句 导入模块可以使用import&#xff0c;如果只导入模…...

Hutool工具类生成二维码

1、引入依赖 <dependency><groupId>com.google.zxing</groupId><artifactId>core</artifactId><version>3.3.3</version></dependency><dependency><groupId>cn.hutool</groupId><artifactId>hutoo…...

wpf 事件转命令的方式

1&#xff0c;方式1 <StackPanel Background"Transparent"><StackPanel.InputBindings><KeyBinding Command"{Binding ChangeColorCommand}"CommandParameter"{Binding ElementNamecolorPicker, PathSelectedItem}"Key"{Bi…...

第二十八章 TCP 客户端 服务器通信 - JOB命令示例

文章目录 第二十八章 TCP 客户端 服务器通信 - JOB命令示例JOB命令示例 第二十八章 TCP 客户端 服务器通信 - JOB命令示例 JOB命令示例 以下示例显示了一个非常简单的并发服务器&#xff0c;只要它检测到来自客户端的连接&#xff0c;就会产生一个子作业。 JOB指定一个并发服…...

「Mac玩转仓颉内测版19」PTA刷题篇10 - L1-010 比较大小

本篇将继续讲解PTA平台上的题目 L1-010 比较大小&#xff0c;通过对三个整数的排序&#xff0c;进一步提升Cangjie编程语言的数组操作与逻辑处理能力。 关键词 PTA刷题数字排序条件判断Cangjie语言 一、L1-010 比较大小 题目描述&#xff1a;给定3个整数&#xff0c;要求将它…...

RocketMQ延迟消息机制

两种延迟消息 RocketMQ中提供了两种延迟消息机制 指定固定的延迟级别 通过在Message中设定一个MessageDelayLevel参数&#xff0c;对应18个预设的延迟级别指定时间点的延迟级别 通过在Message中设定一个DeliverTimeMS指定一个Long类型表示的具体时间点。到了时间点后&#xf…...

大话软工笔记—需求分析概述

需求分析&#xff0c;就是要对需求调研收集到的资料信息逐个地进行拆分、研究&#xff0c;从大量的不确定“需求”中确定出哪些需求最终要转换为确定的“功能需求”。 需求分析的作用非常重要&#xff0c;后续设计的依据主要来自于需求分析的成果&#xff0c;包括: 项目的目的…...

聊聊 Pulsar:Producer 源码解析

一、前言 Apache Pulsar 是一个企业级的开源分布式消息传递平台&#xff0c;以其高性能、可扩展性和存储计算分离架构在消息队列和流处理领域独树一帜。在 Pulsar 的核心架构中&#xff0c;Producer&#xff08;生产者&#xff09; 是连接客户端应用与消息队列的第一步。生产者…...

最新SpringBoot+SpringCloud+Nacos微服务框架分享

文章目录 前言一、服务规划二、架构核心1.cloud的pom2.gateway的异常handler3.gateway的filter4、admin的pom5、admin的登录核心 三、code-helper分享总结 前言 最近有个活蛮赶的&#xff0c;根据Excel列的需求预估的工时直接打骨折&#xff0c;不要问我为什么&#xff0c;主要…...

MMaDA: Multimodal Large Diffusion Language Models

CODE &#xff1a; https://github.com/Gen-Verse/MMaDA Abstract 我们介绍了一种新型的多模态扩散基础模型MMaDA&#xff0c;它被设计用于在文本推理、多模态理解和文本到图像生成等不同领域实现卓越的性能。该方法的特点是三个关键创新:(i) MMaDA采用统一的扩散架构&#xf…...

高等数学(下)题型笔记(八)空间解析几何与向量代数

目录 0 前言 1 向量的点乘 1.1 基本公式 1.2 例题 2 向量的叉乘 2.1 基础知识 2.2 例题 3 空间平面方程 3.1 基础知识 3.2 例题 4 空间直线方程 4.1 基础知识 4.2 例题 5 旋转曲面及其方程 5.1 基础知识 5.2 例题 6 空间曲面的法线与切平面 6.1 基础知识 6.2…...

ffmpeg(四):滤镜命令

FFmpeg 的滤镜命令是用于音视频处理中的强大工具&#xff0c;可以完成剪裁、缩放、加水印、调色、合成、旋转、模糊、叠加字幕等复杂的操作。其核心语法格式一般如下&#xff1a; ffmpeg -i input.mp4 -vf "滤镜参数" output.mp4或者带音频滤镜&#xff1a; ffmpeg…...

Nginx server_name 配置说明

Nginx 是一个高性能的反向代理和负载均衡服务器&#xff0c;其核心配置之一是 server 块中的 server_name 指令。server_name 决定了 Nginx 如何根据客户端请求的 Host 头匹配对应的虚拟主机&#xff08;Virtual Host&#xff09;。 1. 简介 Nginx 使用 server_name 指令来确定…...

Ascend NPU上适配Step-Audio模型

1 概述 1.1 简述 Step-Audio 是业界首个集语音理解与生成控制一体化的产品级开源实时语音对话系统&#xff0c;支持多语言对话&#xff08;如 中文&#xff0c;英文&#xff0c;日语&#xff09;&#xff0c;语音情感&#xff08;如 开心&#xff0c;悲伤&#xff09;&#x…...

【开发技术】.Net使用FFmpeg视频特定帧上绘制内容

目录 一、目的 二、解决方案 2.1 什么是FFmpeg 2.2 FFmpeg主要功能 2.3 使用Xabe.FFmpeg调用FFmpeg功能 2.4 使用 FFmpeg 的 drawbox 滤镜来绘制 ROI 三、总结 一、目的 当前市场上有很多目标检测智能识别的相关算法&#xff0c;当前调用一个医疗行业的AI识别算法后返回…...