当前位置: 首页 > 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;要求将它…...

【Python】 -- 趣味代码 - 小恐龙游戏

文章目录 文章目录 00 小恐龙游戏程序设计框架代码结构和功能游戏流程总结01 小恐龙游戏程序设计02 百度网盘地址00 小恐龙游戏程序设计框架 这段代码是一个基于 Pygame 的简易跑酷游戏的完整实现,玩家控制一个角色(龙)躲避障碍物(仙人掌和乌鸦)。以下是代码的详细介绍:…...

脑机新手指南(八):OpenBCI_GUI:从环境搭建到数据可视化(下)

一、数据处理与分析实战 &#xff08;一&#xff09;实时滤波与参数调整 基础滤波操作 60Hz 工频滤波&#xff1a;勾选界面右侧 “60Hz” 复选框&#xff0c;可有效抑制电网干扰&#xff08;适用于北美地区&#xff0c;欧洲用户可调整为 50Hz&#xff09;。 平滑处理&…...

练习(含atoi的模拟实现,自定义类型等练习)

一、结构体大小的计算及位段 &#xff08;结构体大小计算及位段 详解请看&#xff1a;自定义类型&#xff1a;结构体进阶-CSDN博客&#xff09; 1.在32位系统环境&#xff0c;编译选项为4字节对齐&#xff0c;那么sizeof(A)和sizeof(B)是多少&#xff1f; #pragma pack(4)st…...

Neo4j 集群管理:原理、技术与最佳实践深度解析

Neo4j 的集群技术是其企业级高可用性、可扩展性和容错能力的核心。通过深入分析官方文档,本文将系统阐述其集群管理的核心原理、关键技术、实用技巧和行业最佳实践。 Neo4j 的 Causal Clustering 架构提供了一个强大而灵活的基石,用于构建高可用、可扩展且一致的图数据库服务…...

【从零学习JVM|第三篇】类的生命周期(高频面试题)

前言&#xff1a; 在Java编程中&#xff0c;类的生命周期是指类从被加载到内存中开始&#xff0c;到被卸载出内存为止的整个过程。了解类的生命周期对于理解Java程序的运行机制以及性能优化非常重要。本文会深入探寻类的生命周期&#xff0c;让读者对此有深刻印象。 目录 ​…...

解决:Android studio 编译后报错\app\src\main\cpp\CMakeLists.txt‘ to exist

现象&#xff1a; android studio报错&#xff1a; [CXX1409] D:\GitLab\xxxxx\app.cxx\Debug\3f3w4y1i\arm64-v8a\android_gradle_build.json : expected buildFiles file ‘D:\GitLab\xxxxx\app\src\main\cpp\CMakeLists.txt’ to exist 解决&#xff1a; 不要动CMakeLists.…...

Spring AI Chat Memory 实战指南:Local 与 JDBC 存储集成

一个面向 Java 开发者的 Sring-Ai 示例工程项目&#xff0c;该项目是一个 Spring AI 快速入门的样例工程项目&#xff0c;旨在通过一些小的案例展示 Spring AI 框架的核心功能和使用方法。 项目采用模块化设计&#xff0c;每个模块都专注于特定的功能领域&#xff0c;便于学习和…...

五子棋测试用例

一.项目背景 1.1 项目简介 传统棋类文化的推广 五子棋是一种古老的棋类游戏&#xff0c;有着深厚的文化底蕴。通过将五子棋制作成网页游戏&#xff0c;可以让更多的人了解和接触到这一传统棋类文化。无论是国内还是国外的玩家&#xff0c;都可以通过网页五子棋感受到东方棋类…...

高考志愿填报管理系统---开发介绍

高考志愿填报管理系统是一款专为教育机构、学校和教师设计的学生信息管理和志愿填报辅助平台。系统基于Django框架开发&#xff0c;采用现代化的Web技术&#xff0c;为教育工作者提供高效、安全、便捷的学生管理解决方案。 ## &#x1f4cb; 系统概述 ### &#x1f3af; 系统定…...

xmind转换为markdown

文章目录 解锁思维导图新姿势&#xff1a;将XMind转为结构化Markdown 一、认识Xmind结构二、核心转换流程详解1.解压XMind文件&#xff08;ZIP处理&#xff09;2.解析JSON数据结构3&#xff1a;递归转换树形结构4&#xff1a;Markdown层级生成逻辑 三、完整代码 解锁思维导图新…...