深入理解索引(一)

1.引言

在数据库和数据结构中,索引(Index)是一种用于提高数据检索速度的重要机制。本文将详细深入介绍索引。

2. 索引的分类

2.1 B - 树索引(B - Tree Index)

2.1.1 结构细节
  1. 树状结构:B - 树索引是一种平衡的多叉树结构。它由根节点、分支节点和叶子节点组成。根节点位于树的顶部,包含指向子节点的指针和索引键值范围。分支节点用于引导搜索路径,也包含指向子节点的指针和索引键值范围。叶子节点存储实际的索引键值和对应的行标识符(ROWID),ROWID 用于定位表中的数据行。
  2. 有序存储:索引键值在树的节点中是按照一定顺序(通常是升序)排列的。这种有序排列使得范围查询和排序查询更加高效。例如,在一个存储员工工资信息的表中,如果对工资列建立了 B - 树索引,工资数据会按照从小到大的顺序存储在索引的叶子节点中。
2.1.2 查询场景优势
  1. 等值查询高效:当进行等值查询(如查询工资等于 5000 元的员工)时,数据库可以从根节点开始,沿着索引树的分支节点快速定位到存储该工资值的叶子节点,然后通过 ROWID 找到对应的员工记录。这个过程避免了全表扫描,大大提高了查询速度。
  2. 范围查询支持良好:对于范围查询(如查询工资在 4000 - 6000 元之间的员工),由于索引键值的有序性,数据库可以顺序读取叶子节点中的数据,找到符合范围的索引键值及其对应的 ROWID,从而获取相应的员工记录。这种顺序读取减少了磁盘 I/O 的随机访问,提高了查询效率。
2.1.3 更新操作影响
  1. 插入和删除影响:当插入新数据时,B - 树索引可能需要调整树的结构来保持平衡。例如,如果插入一个新的工资值,可能会导致索引节点的分裂或合并操作。删除数据时也可能导致节点的调整。这些操作会消耗一定的系统资源,但 Oracle 数据库有相应的机制来尽量减少这种影响。
  2. 更新索引列影响:如果更新的是索引列的值,那么索引也需要相应地更新。如果更新后的索引列值仍然在原索引键值的范围内,可能只需要在叶子节点内进行调整;如果超出了原范围,可能会导致节点的重新排列。

2.2 位图索引(Bitmap Index)

2.2.1 结构细节
  1. 位图表示:位图索引针对表中的每一个可能的索引值都有一个对应的位图。位图是由一系列的位(0 或 1)组成,位图中的每一位代表表中的一行。如果位的值为 1,表示该行包含对应的索引值;如果为 0,则表示该行不包含。例如,在一个有性别(男 / 女)列的客户表中,对于 “男” 这个索引值,位图中对应男性客户行的位为 1,女性客户行的位为 0。
  2. 存储空间节省:对于具有低基数(即不同值的数量相对较少)的列,位图索引可以有效地节省存储空间。因为它不需要像 B - 树索引那样存储每个索引键值和 ROWID,而是通过位图来表示数据分布。
2.2.2 查询场景优势
  1. 低基数列查询高效:在查询低基数列时,位图索引表现出色。例如,在查询所有男性客户的信息时,数据库只需对 “男” 对应的位图进行扫描,找到位为 1 的行,就可以快速定位到男性客户的记录。对于多条件查询(如查询男性且年龄大于 30 岁的客户),位图索引可以通过位运算(如 AND、OR 操作)来快速合并查询条件,提高查询效率。
2.2.3 更新操作影响
  1. 更新复杂性:位图索引在更新操作时比较复杂。当插入或删除数据时,需要更新多个位图。例如,在客户表中插入一个新的男性客户,需要更新性别列的位图,将新客户对应的位置为 1。而且,由于位运算的特性,在高并发环境下,位图索引的更新可能会导致锁竞争等问题,影响系统性能。

2.3 函数索引(Function - Based Index)

2.3.1 结构细节
  1. 基于函数结果存储:函数索引不是直接对列的值进行索引,而是对列经过特定函数或表达式计算后的结果进行索引。例如,在一个存储产品销售日期的表中,对日期列建立一个提取年份的函数索引,索引中存储的是经过提取年份函数计算后的结果(如 2024)和对应的 ROWID。
2.3.2 查询场景优势
  1. 函数查询加速:当查询条件经常涉及对列的函数操作时,函数索引可以大大提高查询效率。比如,在上述产品销售日期表中,如果经常查询某一年的销售情况,通过提取年份的函数索引,数据库可以直接定位到该年份对应的销售记录,而不需要对每个销售日期进行函数计算后再查询。
2.3.3 更新操作影响
  1. 更新时重新计算:当更新索引列时,由于函数索引是基于函数结果的,需要重新计算函数值来更新索引。如果函数计算比较复杂,可能会增加更新操作的成本。而且,函数索引的创建和维护需要考虑函数的确定性(即相同的输入总是得到相同的输出),否则可能会导致索引不一致等问题。

2.4 全文索引(Full - Text Index)

2.4.1 结构细节
  1. 文本内容分析:全文索引用于对文本数据进行索引,它会对文本中的单词、词组等进行分析和存储。Oracle 会将文本内容分解为一个个的词汇单元(token),并记录这些词汇单元在文本中的位置等信息。例如,在一个包含文章内容的表中,全文索引会对文章中的每个单词进行索引,包括单词出现的频率、位置等。
2.4.2 查询场景优势
  1. 文本搜索高效:当进行文本搜索(如查询包含某个特定关键词的文章)时,全文索引可以快速定位到相关的文本内容。它支持多种文本搜索方式,如模糊搜索、词干搜索(如搜索 “run” 可以匹配 “running”)等,为文本相关的应用提供了强大的搜索功能。
2.4.3 更新操作影响
  1. 更新成本高:由于全文索引需要对文本内容进行复杂的分析和处理,在更新文本数据时,全文索引的更新成本相对较高。特别是对于大量文本数据的更新,可能会导致系统性能下降。

2.5 反向键索引(Reverse Key Index)

2.5.1 结构细节
  1. 键值反转存储:反向键索引是一种特殊的 B - 树索引,它将索引键值的字节顺序反转后存储。例如,对于索引键值为 1234 的列,在反向键索引中存储为 4321。这种反转存储主要是为了避免在插入数据时,由于索引键值的顺序性导致索引树的不平衡。
2.5.2 查询场景优势
  1. 插入热点问题缓解:在一些应用场景中,如使用序列生成的主键列,数据可能会按照顺序插入,导致索引树的右侧分支过度增长(插入热点问题)。反向键索引通过反转键值,使得插入的数据在索引树中的分布更加均匀,从而在一定程度上缓解了插入热点问题,提高了插入操作的性能。
2.5.3 查询性能权衡

反向键索引在查询性能上可能会有一定的损失。因为在查询时,需要先将查询条件中的键值反转,然后再在索引树中进行搜索。对于范围查询,反向键索引的性能通常不如普通 B - 树索引,因为反转后的键值顺序打乱了原有的范围顺序。

3. 索引的创建

3.1 B - 树索引创建

3.1.1 语法

基本的创建 B - 树索引的语法是:

CREATE INDEX index_name ON table_name (column_name [ASC|DESC],...);

其中,index_name是要创建的索引名称,table_name是索引所属的表名,column_name是要建立索引的列名。可以指定多个列来创建组合索引,列名之间用逗号分隔。ASC或DESC用于指定索引列的排序方式,默认为ASC(升序)。

3.1.2 示例

假设存在一个员工表employees,包含employee_id(员工编号)、employee_name(员工姓名)和department_id(部门编号)列。如果经常根据员工姓名进行查询,可以创建一个 B - 树索引:

CREATE INDEX idx_employee_name ON employees (employee_name);
3.1.3 考虑因素:
  1. 选择合适的列:应该选择那些经常在查询条件中出现的列建立索引。同时,要避免对数据变化频繁的列过度建立索引,因为这会增加数据更新的成本。例如,在一个日志记录表中,日志内容列通常不需要建立索引,因为很少会根据日志内容进行查询,而且日志内容可能会频繁变化。
  2. 组合索引的列顺序:当创建组合索引时,列的顺序很重要。应该将最常用于过滤数据的列放在前面。例如,在一个订单表中,如果经常根据客户编号和订单日期进行查询,且客户编号的选择性更高(不同客户编号的数量相对订单日期的组合更多),那么组合索引的顺序应该是(customer_id, order_date)。

3.2 位图索引创建

3.2.1 语法

创建位图索引的语法为:

CREATE BITMAP INDEX bitmap_index_name ON table_name (column_name);

其中,bitmap_index_name是位图索引的名称,table_name是所属表名,column_name是要建立位图索引的列名。

3.2.2 示例

对于一个包含产品类别列product_category的产品表products,如果产品类别列的取值较少(低基数),可以创建位图索引:

CREATE BITMAP INDEX bitmap_product_category ON products (product_category);
3.2.3 考虑因素:
  1. 适用场景:主要适用于低基数列,即列的取值范围较小且重复值较多的情况。如性别、状态等列。对于高基数列,使用位图索引可能会导致存储空间过大和性能下降。
  2. 更新操作影响:要考虑到位图索引在更新操作时比较复杂。当插入或删除数据时,需要更新多个位图,在高并发环境下可能会导致锁竞争等问题,影响系统性能。

3.3 函数索引创建

3.3.1 语法

创建函数索引的语法是:

CREATE INDEX function_index_name ON table_name (function(column_name));

其中,function_index_name是函数索引的名称,table_name是所属表名,function(column_name)是基于列column_name的函数表达式。

3.3.2 示例

在一个销售记录表sales中,包含销售日期列sale_date,如果经常需要查询某一月份的销售记录,可以创建一个提取月份的函数索引:

CREATE INDEX idx_sale_month ON sales (EXTRACT(MONTH FROM sale_date));
3.3.3 考虑因素:
  1. 函数确定性:函数索引的创建和维护需要考虑函数的确定性,即相同的输入总是得到相同的输出。否则可能会导致索引不一致等问题。
  2. 更新成本:当更新索引列时,由于函数索引是基于函数结果的,需要重新计算函数值来更新索引。如果函数计算比较复杂,可能会增加更新操作的成本。

3.4 全文索引创建

3.4.1 语法(以 Oracle Text为例)

首先需要安装和配置 Oracle Text 组件。创建全文索引的基本语法如下:

CREATE INDEX fulltext_index_name ON table_name (column_name) INDEXTYPE IS CTXSYS.CONTEXT;
3.4.2 示例

在一个文档内容表documents中,包含content(文档内容)列,可以创建全文索引:

CREATE INDEX idx_document_content ON documents (content) INDEXTYPE IS CTXSYS.CONTEXT;
3.4.3 考虑因素:
  1. 文本分析要求:在创建全文索引时,需要考虑对文本内容的分析要求,如是否需要进行词干提取、停用词过滤等操作。这些操作可以通过 Oracle Text 的参数进行配置。
  2. 更新成本:由于全文索引需要对文本内容进行复杂的分析和处理,在更新文本数据时,全文索引的更新成本相对较高。特别是对于大量文本数据的更新,可能会导致系统性能下降。

4. 管理索引

4.1 查看索引信息

  1. 数据字典视图:可以使用数据字典视图来查看索引的相关信息。USER_INDEXES视图显示当前用户拥有的索引信息,包括索引名称、所属表、索引类型等。ALL_INDEXES视图可以查看当前用户有权访问的所有索引信息,DBA_INDEXES视图(需要管理员权限)则可以查看数据库中的所有索引信息。
  2. 示例:通过以下查询可以查看用户自己创建的索引:
SELECT index_name, table_name, index_type FROM USER_INDEXES;

4.2 重建和维护索引

  1. 索引碎片问题:随着数据的插入、更新和删除操作,索引可能会变得碎片化,影响其性能。例如,在频繁更新数据的表中,B - 树索引的节点可能会频繁分裂和合并,导致索引结构不紧凑,降低查询效率。
  2. 重建索引方法:可以通过重建索引来优化其性能。对于 B - 树索引,使用ALTER INDEX index_name REBUILD;语句进行重建。重建索引可以重新组织索引结构,减少碎片,提高索引的效率。

4.3 删除索引

  1. 语法:当索引不再需要时,可以使用DROP INDEX index_name;语句删除索引。
  2. 考虑因素:在删除索引之前,需要谨慎考虑。应该评估该索引是否真的不再使用,因为删除索引后可能会导致相关查询性能下降。如果是为了测试或者临时调整,可以先备份索引定义,以便在需要时重新创建。

未完待续
码字不易,宝贵经验分享不易,请各位支持原创,转载注明出处,多多关注作者,后续不定期分享DB基本知识和排障案例及经验、性能调优等。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/921699.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

C0030.Clion中运行提示Process finished with exit code -1073741515 (0xC0000135)解决办法

1.错误提示 2.解决办法 添加环境变量完成之后,重启Clion软件,然后就可以正常调用由mingw编译的opencv库了。

【es6进阶】vue3中的数据劫持的最新实现方案的proxy的详解

vuejs中实现数据的劫持,v2中使用的是Object.defineProperty()来实现的,在大版本v3中彻底重写了这部分,使用了proxy这个数据代理的方式,来修复了v2中对数组和对象的劫持的遗留问题。 proxy是什么 Proxy 用于修改某些操作的默认行为&#xff0…

Python浪漫之画明亮的月亮

目录 1、效果展示 2、完整版代码 1、效果展示 2、完整版代码 import turtledef draw_moon():# 设置画布turtle.bgcolor("black") # 背景颜色为黑色turtle.speed(10) # 设置绘制速度# 绘制月亮的外圈turtle.penup()turtle.goto(0, -100) # 移动到起始…

《线性代数的本质》

之前收藏的一门课,刚好期末复习,顺便看一看哈哈 课程链接:【线性代数的本质】合集-转载于3Blue1Brown官方双语】 向量究竟是什么 线性代数中最基础、最根源的组成部分就是向量,需要先明白什么是向量 不同专业对向量的看法 物理专…

鸿蒙系统ubuntu开发环境搭建

在RISC-V等平台移植鸿蒙系统OpenHarmony,需要使用linux环境进行代码的编译,为兼顾日常办公需要,可采用WindowsUbuntu虚拟机的混合开发的环境,通过网络及文件夹共享,在主机和虚拟机之间共享文件数据。 工具准备&#x…

智能停车解决方案之停车场室内导航系统(二):核心技术与系统架构构建

hello~这里是维小帮,如有项目需求和技术交流欢迎大家私聊我们!点击文章最下方获取智慧停车场方案~撒花! 随着城市化进程的加速,停车难问题日益凸显。智能停车系统作为缓解停车压力的有效手段,其核心技术与架构的构建至…

(免费送源码)计算机毕业设计原创定制:Java+JSP+HTML+JQUERY+AJAX+MySQL springboot计算机类专业考研学习网站管理系统

摘 要 大数据时代下,数据呈爆炸式地增长。为了迎合信息化时代的潮流和信息化安全的要求,利用互联网服务于其他行业,促进生产,已经是成为一种势不可挡的趋势。在大学生在线计算机类专业考研学习网站管理的要求下,开发一…

IDEA2023版本中如何启动项目的多个实例

假设现在要启动多个服务,例如简单的客户端和服务端,默认的idea是只能启动一个的,那么我们需要进行配置允许多个项目的同时启动,现在进行多实例的配置。 第一步 点击Edit Configurations 第二步 点击Modify options 第三步 勾选…

图的邻接矩阵和邻接表存储

目录 邻接矩阵存储法 简介 ​编辑 邻接矩阵举例 无向图邻接矩阵 有向图邻接矩阵 当各条边带有权值时 邻接矩阵算法实现 结构体定义和函数声明 函数的实现 邻接表存储法 简介 邻接表的算法实现 结构体定义和函数声明 函数的实现 邻接矩阵和邻接表的差别 邻接矩阵存…

【Linux命令】grep

Linux命令-grep GREP命令:进行字符串数据的比对,并将符合指定模式的字符串行打印出来。1.命令介绍基础正则表达式原始文档如下: 2.练习题:2.1 练习(一):2.1.1 读取加行号的文件内容:…

WMS 如何实现智能仓储与自动化物流的无缝对接

【大家好,我是唐Sun,唐Sun的唐,唐Sun的Sun。】 在当今高度竞争的商业环境中,企业对于物流效率和仓储管理的要求日益严苛。智能仓储和自动化物流作为现代物流领域的重要发展方向,能够显著提高物流运作的速度、准确性和成…

DevOps-Jenkins-新手入门级

1. Jenkins概述 1. Jenkins是一个开源持续集成的工具,是由JAVA开发而成 2. Jenkins是一个调度平台,本身不处理任何事情,调用插件来完成所有的工作 1.1 什么是代码部署 代码发布/部署>开发书写的程序代码---->部署测试/生产环境 web服务…

WEB APIS(DOM对象,操作元素内容,属性,表单属性,自定义属性,定时器)

js基础基本语法: 变量,数据类型,循环,函数,对象等(主要是控制台打印) WEB APIS 操作DOM BOM : 控制网页元素,交互等各种网页交互效果 js高级 语法: js新增语法&#xff0…

cs144(一)

cs144(一) 1、osi 当应用程序有数据要发送时,应用层将数据交给传输层, 传输层负责将数据可靠或不可靠地传送到另外一端,传输层通过将数据交给网络层来发送数据 网络层负责将数据分成数据包,每个数据包都有正确的目的地址 最后…

IEC61850读服务器目录命令——GetServerDirectory介绍

IEC61850标准中的GetServerDirectory命令是变电站自动化系统中非常重要的一个功能,它主要用于读取服务器的目录信息,特别是服务器的逻辑设备节点(LDevice)信息。以下是对GetServerDirectory命令的详细介绍。 目录 一、命令功能 …

如何使用AWS Lambda构建一个云端工具(超详细)

首发地址(欢迎大家访问):如何使用AWS Lambda构建一个云端工具(超详细) 1 前言 1.1 无服务器架构 无服务器架构(Serverless Computing)是一种云计算服务模型,它允许开发者构建和运行…

力扣-位运算-1【算法学习day.41】

前言 ###我做这类文档一个重要的目的还是给正在学习的大家提供方向(例如想要掌握基础用法,该刷哪些题?)我的解析也不会做的非常详细,只会提供思路和一些关键点,力扣上的大佬们的题解质量是非常非常高滴&am…

MySQL数据库学习(持续更新ing)

1. 什么是数据库?什么是数据库管理系统?什么是SQL?他们之间的关系是什么? 数据库:Database, 简称DB。按照一定格式存储数据,一些文件的组合。 数据库管理系统:DataBaseManagement&…

【Python · PyTorch】循环神经网络 RNN(基础概念)

【Python PyTorch】循环神经网络 RNN(基础概念) 0. 生物学相似性1. 概念2. 延时神经网络(TDNN)3. 简单循环神经网络(Simple RNN)3.1 BiRNN 双向循环神经网络3.2 特点记忆性参数共享图灵完备 3.3 网络结构3…

【Isaac Sim】相关问题汇总

目录 一、安装点击Install时报错二、启动时报 Failed to create any GPU devices三、加载Isaac Sim自带模型或示例时报 Isaac Sim is not responding 一、安装点击Install时报错 报错: request to https://asset.launcher.omniverse.nvidia.com/… failed, reason:…