深入理解索引(一)

news2024/11/24 10:28:09

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基本知识和排障案例及经验、性能调优等。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Spring |(四)IoC/DI配置管理第三方bean

文章目录 📚数据源对象管理🐇环境准备🐇实现Druid管理🐇实现C3P0管理 📚加载properties文件🐇第三方bean属性优化🐇读取单个属性 学习来源:黑马程序员SSM框架教程_SpringSpringMVCMa…

鸿蒙NEXT开发案例:随机数生成

【引言】 本项目是一个简单的随机数生成器应用,用户可以通过设置随机数的范围和个数,并选择是否允许生成重复的随机数,来生成所需的随机数列表。生成的结果可以通过点击“复制”按钮复制到剪贴板。 【环境准备】 • 操作系统:W…

[译]Elasticsearch Sequence ID实现思路及用途

原文地址:https://www.elastic.co/blog/elasticsearch-sequence-ids-6-0 如果 几年前,在Elastic,我们问自己一个"如果"问题,我们知道这将带来有趣的见解: "如果我们在Elasticsearch中对索引操作进行全面排序会怎样…

小米14升级澎湃OS 2.0.6.VNCCNXM 记录

简介 11.23 小米14凌晨推送了澎湃2.0,还真是11月压轴的,不是内测申请的。 btw,什么时候才能有红米耳机连接的弹窗啊??为什么13都有,但是14没有? 系统更新推送 版本介绍 1.0.47 更新到 2.0.6.VNCCNXM,记录一些界面变化,应用问题和内存情况。 澎湃OS 2 更新 - 功能介…

【单点知识】基于PyTorch进行模型部署

文章目录 0. 前言1. 模型导出1.1 TorchScript1.1.1 使用 torch.jit.trace1.1.2 使用 torch.jit.script 1.2 ONNX1.2.1 导出为 ONNX 格式 1.3 导出后的模型加载1.3.1 加载 TorchScript 模型1.3.2 加载 ONNX 模型 2. 模型优化2.1 模型量化2.2 模型剪枝 3. 服务化部署3.1 Flask 部…

FreeRTOS——互斥信号量

一、为什么需要互斥信号量 前面的学习中: 调度锁、临界段不可避免的破坏了实时性,还有二值信号量存在这样的隐患——“优先级翻转” 优先级翻转 简单来说,就是由于信号量被低优先级任务占用,即使遇到高优先级任务,它…

前端-react(class组件和Hooks)

文章主要以Hooks为主,部分涉及class组件方法进行对比 一.了解react 1.管理组件的方式 在React中,有两种主要的方式来管理组件的状态和生命周期:Class 组件和 Hooks。 Class 组件: Class 组件是 React 最早引入的方式,它是基于…

Ngrok实现内网穿透(Windows)

Ngrok实现内网穿透(Windows) 什么是内网穿透,内网穿透有什么用 内网穿透(NAT traversal)是一种技术手段,使得位于内网或防火墙后面的设备能够通过外网访问。例如,如果你的计算机、服务器等设备…

如何使用Jest测试你的React组件

在本文中,我们将了解如何使用Jest(Facebook 维护的一个测试框架)来测试我们的React组件。我们将首先了解如何在纯 JavaScript 函数上使用 Jest,然后再了解它提供的一些开箱即用的功能,这些功能专门用于使测试 React 应…

力扣 三数之和-15

三数之和-15 class Solution { public:vector<vector<int>> threeSum(vector<int>& nums) {int temp 0;//定义一个二维vector数组vector<vector<int>> ans;int n nums.size();//对nums数组进行排序sort(nums.begin(), nums.end());//固定…

深度学习每周学习总结J6(ResNeXt-50 算法实战与解析 - 猴痘识别)

&#x1f368; 本文为&#x1f517;365天深度学习训练营 中的学习记录博客&#x1f356; 原作者&#xff1a;K同学啊 | 接辅导、项目定制 目录 0. 总结ResNeXt基本介绍 1. 设置GPU2. 导入数据及处理部分3. 划分数据集4. 模型构建部分5. 设置超参数&#xff1a;定义损失函数&…

Transformer架构笔记

Attention is All You Need. 3.Model Architecture 3.1 整体架构如图 3.2 Encoder与Decoder Encoder&#xff1a;由 N 6 N6 N6个相同的Block/Layer堆叠而成。每个Block有两个子层sub-layer&#xff1a;多头注意力和MLP&#xff08;FFN&#xff0c;前馈神经网络&#xff09;&…

【大数据学习 | Spark-Core】spark-shell开发

spark的代码分为两种 本地代码在driver端直接解析执行没有后续 集群代码&#xff0c;会在driver端进行解析&#xff0c;然后让多个机器进行集群形式的执行计算 spark-shell --master spark://nn1:7077 --executor-cores 2 --executor-memory 2G sc.textFile("/home/ha…

增量预训练(Pretrain)样本拼接篇

增量预训练&#xff08;Pretrain&#xff09;样本拼接篇 一、Pretrain阶段&#xff0c;为什么需要拼接拼接&#xff1f; 为了提高pretrain效率、拓展LLM最大长度&#xff0c;随机将若干条短文本进行拼接是pretrain阶段常见手段。 二、有哪些拼接方式&#xff1f; 拼接方式一…

【AI最前线】DP双像素sensor相关的AI算法全集:深度估计、图像去模糊去雨去雾恢复、图像重建、自动对焦

Dual Pixel 简介 双像素是成像系统的感光元器件中单帧同时生成的图像&#xff1a;通过双像素可以实现&#xff1a;深度估计、图像去模糊去雨去雾恢复、图像重建 成像原理来源如上&#xff0c;也有遮罩等方式的pd生成&#xff0c;如图双像素视图可以看到光圈的不同一半&#x…

从零开始-VitePress 构建个人博客上传GitHub自动构建访问

从零开始-VitePress 构建个人博客上传GitHub自动构建访问 序言 VitePress 官网&#xff1a;VitePress 中文版 1. 什么是 VitePress VitePress 是一个静态站点生成器 (SSG)&#xff0c;专为构建快速、以内容为中心的站点而设计。简而言之&#xff0c;VitePress 获取用 Markdown…

使用uniapp编写APP的文件上传

使用uniapp插件文件选择、文件上传组件&#xff08;图片&#xff0c;视频&#xff0c;文件等&#xff09; - DCloud 插件市场 实用效果&#xff1a; 缺陷是只能一个一个单独上传

【51单片机】红外遥控

学习使用的开发板&#xff1a;STC89C52RC/LE52RC 编程软件&#xff1a;Keil5 烧录软件&#xff1a;stc-isp 开发板实图&#xff1a; 文章目录 红外遥控硬件电路 NEC协议编码编程实例LCD1602显示Data红外遥控控制扇叶转速 红外遥控 红外遥控是利用红外光进行通信的设备&#…

【解决】Unity TMPro字体中文显示错误/不全问题

问题描述&#xff1a;字体变成方块 原因&#xff1a;字体资源所承载的长度有限 1.找一个中文字体放入Assets中 2.选中字体创建为TMPro 字体资源 3.选中创建好的字体资源&#xff08;蓝色的大F&#xff09; 在右边的属性中找到Atlas Width h和 Atlas Heigth,修改的大一点&…

深度学习:GPT-1的MindSpore实践

GPT-1简介 GPT-1&#xff08;Generative Pre-trained Transformer&#xff09;是2018年由Open AI提出的一个结合预训练和微调的用于解决文本理解和文本生成任务的模型。它的基础是Transformer架构&#xff0c;具有如下创新点&#xff1a; NLP领域的迁移学习&#xff1a;通过最…