聚簇索引、哈希索引、覆盖索引、索引分类、最左前缀原则、判断索引使用情况、索引失效条件、优化查询性能

news/2025/2/3 16:27:51 标签: mysql

聚簇索引

        聚簇索引像一本按目录排版的书,用空间换时间,适合读多写少的场景。设计数据库时,主键的选择(如自增ID vs 随机UUID)会直接影响聚簇索引的性能。

什么是聚簇索引?

  • 数据即索引:聚簇索引的叶子节点直接存储整行数据(而不是指向数据的指针),因此表中的数据行物理上按索引键的顺序存储

  • 唯一性:一张表只能有一个聚簇索引(就像一本书只能按一种顺序排版)。

类比生活场景:

  • 普通索引(非聚簇索引):像一本书末尾的“关键词索引”,每个关键词后标注页码,你需要先查索引,再翻到对应页。

  • 聚簇索引:像书的目录本身,章节内容严格按照目录顺序排版。找某一章时,直接按目录顺序翻到对应页即可,无需二次跳转。

优点:

  • 查询快:范围查询(如 WHERE id BETWEEN 1000 AND 2000)效率高,因为数据在磁盘上是连续的。

  • 排序快:如果按聚簇索引的字段排序(如主键),数据库可以直接按物理顺序读取,无需额外操作。

缺点:

  • 插入/更新慢:新增数据时,如果新数据需要插入到中间位置,可能导致数据页分裂(类似电话簿插页时需要撕开重新装订)。

  • 依赖主键设计:如果主键设计不合理(例如用随机UUID),可能导致存储碎片化,降低性能。

常见应用:

  • 主键默认是聚簇索引(如MySQL的InnoDB引擎)。

  • 适合频繁查询的字段:比如用户表的用户ID、订单表的订单时间。

哈希索引

        哈希索引通过哈希函数将数据的关键字(如手机号)直接转换成存储位置,适合快速等值查找,但无法支持范围查询或排序。

什么是哈希索引?

  • 哈希函数:将任意长度的输入(如字符串、数字)转换成固定长度的哈希值(如 0x3A7F)。

  • 直接定位数据:通过哈希值直接找到数据在内存或磁盘上的存储位置,无需遍历。

类比生活场景:

  • 普通索引(如B树索引):像图书馆按书名首字母分类的书架,需要按顺序查找。

  • 哈希索引:像快递柜的编号,输入手机号就能秒定位到具体柜子。

优点:

  • 查询极快:等值查询(如 WHERE id = 123)的时间复杂度接近 O(1)。

  • 无数据顺序要求:适合随机读写场景(如用户登录、缓存)。

缺点:

  • 不支持范围查询:无法高效执行 WHERE id > 100 或 ORDER BY

  • 哈希冲突:不同关键字可能生成相同的哈希值(如手机号A和B被分配到同一个柜子),需要额外处理(如链表串联)。

  • 动态扩容成本高:数据量增长时,哈希表可能需要重新分配空间并重新计算所有哈希值。

常见应用:

  • 内存数据库:如Redis的键值存储。

  • 快速查找表:如用户Session、短链映射。

  • 数据库的Hash Join:关联查询时临时使用哈希表加速。

哈希索引 vs B树索引

覆盖索引

使用普通索引时通常需要两步1.查找索引2.回表操作

使用覆盖索引则通常是直接从索引中直接获取数据,也就是省略了回表步骤

覆盖索引的优点:

        减少IO操作:查询时直接从索引中获取数据,无需访问表中的数据行,显著提高查询性能,特别是在数据量很大或者磁盘IO成本很高。

        索引中的数据:索引通常由被索引的列及其指向的行标识符组成,覆盖索引会存储更多的数据以满足查询需求

索引分类

按物理存储方式分类:

        聚簇索引、非聚簇索引

按功能分类:

        唯一索引、普通索引、全文索引、空间索引

按索引结构分类:

        BTree索引、Hash索引

按应用场景分类:

        单列索引、复合索引、覆盖索引

按存储引擎支持情况分类:

  • InnoDB 支持 B-Tree 索引、唯一索引、全文索引(从 MySQL 5.6 开始)。
  • MyISAM 支持 B-Tree 索引、全文索引。
  • Memory 支持 Hash 索引和 B-Tree 索引。

最左前缀原则

        “最左前缀原则”是数据库(尤其是 MySQL 中)在使用复合索引时的一条重要规则,它规定:在复合索引中,查询条件必须从索引的最左侧开始,连续地使用索引列,才能使该索引被有效利用

        如果创建了一个复合索引(col1, col2, col3),当使用索引时必须是从左到右使用,如果跳过前面的去使用后面的话就会导致索引失效。

  • 提高查询效率
    通过利用复合索引,数据库可以直接定位到符合条件的数据行,减少扫描数据量,显著提升查询速度。

  • 优化设计索引
    在设计复合索引时,应考虑查询的常用模式,将最常用的查询条件放在索引的最左侧。例如,如果大多数查询都是根据 col1 进行过滤,再根据 col2 进行细分,那么将 col1 放在最前面可以最大程度发挥索引优势。

  • 避免索引失效
    如果查询条件没有覆盖复合索引的最左前缀,那么索引将无法被利用,这样会导致查询性能下降。因此在编写 SQL 语句和设计索引时,必须充分考虑这一原则。

判断索引使用情况

以MySQL为例:

查看索引的使用统计:

-- 查看表的索引使用情况(需开启性能模式)
SELECT * FROM INFORMATION_SCHEMA.STATISTICS 
WHERE TABLE_NAME = 'your_table';

-- 查看索引的碎片化程度
SHOW INDEX FROM your_table;

分析查询是否使用索引:

EXPLAIN SELECT * FROM your_table WHERE indexed_column = 'value';
  • 关键字段:

    • typeref 或 range 表示使用了索引。

    • key:显示实际使用的索引名称。

    • rows:扫描的行数,值越小效率越高。

优化数据库表

OPTIMIZE TABLE table_name;

作用

  1. 回收未使用的磁盘空间
    删除大量数据后,会有空闲的磁盘空间,OPTIMIZE TABLE 可以释放这些空间。

  2. 重新组织索引
    对于索引密集的表,优化索引布局可以提高查询性能。

  3. 提高数据读取速度
    通过整理数据和索引,可以减少磁盘 I/O 操作,提升读取速度。

索引失效条件

        使用范围查询、不满足最左前缀原则、使用了不等于运算符、使用函数或表达式、隐式类型转换、模糊查询以通配符开头、使用OR、查询返回过多数据、数据分布不均匀、索引未覆盖查询(无法使用覆盖索引)、表统计信息不准确(数据库优化器依赖表的统计信息进行查询计划的选择。如果统计信息过时或不准确,可能导致错误地放弃索引)、使用了不支持索引的操作

如果避免索引失效:

  • 遵循最左前缀原则,合理设计索引。
  • 避免在索引列上使用函数、表达式或隐式类型转换。
  • 在模糊查询中尽量避免 % 开头。
  • OR 条件进行优化,例如重构为 UNION ALL
  • 确保表的统计信息及时更新。
  • 使用覆盖索引,减少回表查询。
  • 确保查询返回的数据量较少。

优化查询性能的方法

减少请求的数据量:

  • 只返回必要的列,最好不要使用SELECT *语句、使用LIMIT语句来限制返回的数据。
  • 缓存重复查询的数据:使用缓存可以避免在数据库中进行查询,特别是在要查询的数据经常被查询时,使用缓存会极大的提升查询性能

减少服务器端扫描的行数:

  • 使用索引来覆盖查询 
  • 避免索引失效

查询重构优化:

  • 避免使用复杂的JOIN和子查询
  • 批量操作代替循环操作(循环执行单条 SQL 会增加网络和事务开销。)
    -- 不推荐:循环插入
    INSERT INTO logs (message) VALUES ('log1');
    INSERT INTO logs (message) VALUES ('log2');
    
    -- 推荐:批量插入
    INSERT INTO logs (message) VALUES ('log1'), ('log2');

数据库配置优化:

  • 调整缓冲区大小
    -- 增加 InnoDB 缓冲池大小(通常设为物理内存的 70%~80%)
    SET GLOBAL innodb_buffer_pool_size = 4G;
  • 配置数据库连接池(避免短连接:使用连接池(如 HikariCP、Druid)复用连接。

    参数调优:设置合理的最大连接数和空闲超时时间)

架构层面优化:

读写分离
  • 主库:处理写操作和高一致性读。

  • 从库:处理读操作,通过复制同步数据。

分库分表
  • 垂直分表:将大字段(如 TEXT、BLOB)拆分到独立表。

  • 水平分库:按业务分库(如订单库、用户库)。

  • 水平分表:按哈希或范围分表(如 user_0user_1)。

 


http://www.niftyadmin.cn/n/5840906.html

相关文章

C++基础day1

前言:谢谢阿秀,指路阿秀的学习笔记 一、基础语法 1.构造和析构: 类的构造函数是一种特殊的函数,在创建一个新的对象时调用。类的析构函数也是一种特殊的函数,在删除所创建的对象时调用。 构造顺序:父类->子类 析…

毕业设计:基于卷积神经网络的鲜花花卉种类检测算法研究

目录 前言 课题背景和意义 实现技术思路 一、算法理论基础 1.1 卷积神经网络 1.2目标检测算法 二、 数据集 2.1 数据集 2.2 数据扩充 三、实验及结果分析 3.1 实验环境搭建 3.2 模型训练 最后 前言 📅大四是整个大学期间最忙碌的时光,一边要忙着备考或…

Chapter2 Amplifiers, Source followers Cascodes

Chapter2 Amplifiers, Source followers & Cascodes MOS单管根据输入输出, 可分为CS放大器, source follower和cascode 三种结构. Single-transistor amplifiers 这一章学习模拟电路基本单元-单管放大器 单管运放由Common-Source加上DC电流源组成. Avgm*Rds, gm和rds和…

python算法和数据结构刷题[5]:动态规划

动态规划(Dynamic Programming, DP)是一种算法思想,用于解决具有最优子结构的问题。它通过将大问题分解为小问题,并找到这些小问题的最优解,从而得到整个问题的最优解。动态规划与分治法相似,但区别在于动态…

C# 类与对象详解

.NET学习资料 .NET学习资料 .NET学习资料 在 C# 编程中,类与对象是面向对象编程的核心概念。它们让开发者能够将数据和操作数据的方法封装在一起,从而构建出模块化、可维护且易于扩展的程序。下面将详细介绍 C# 中类与对象的相关知识。 一、类的定义 …

尝试ai生成figma设计

当听到用ai 自动生成figma设计时,不免好奇这个是如何实现的。在查阅了不少资料后,有了一些想法。参考了:在figma上使用脚本自动生成色谱 这篇文章提供的主要思路是:可以通过脚本的方式构建figma设计。如果我们使用ai 生成figma脚本…

一些计算机零碎知识随写(25年2月)

今天复习 MySQL 的时候,我突然冒出一个想法:能不能远程连接 MySQL 呢?虽说心里清楚理论上可行,但一直没实际操作过。 于是,起床后我立马打开服务器,准备启动 MySQL。结果,这一启动就发现问题了&…

Games202Lecture5 Real time Environment mapping实时环境光照

SDF (Signed Distance Function) SDF shadows pro:快 con:需要大量存储 相关理论:optimal transport sdf作用1:做ray marching (03min:20s) https://www.youtube.com/watch?vhX3mazz8txohttps://www.youtube.com/watch?vh…