深入理解索引(一)

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.rhkb.cn/news/477200.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【线程】Java线程操作

【线程】Java线程操作 一、启动线程1.1 run()和start()的区别 二、终止线程三、等待线程四、线程的状态 一、启动线程 Java中通过start()方法来启动一个线程,其次我们要着重理解start()和run()的区别。 1.1 run()和start()的区别 我们通过一份代码来进行观察&…

MySQL学习/复习10视图/用户/权限/语言连接数据库

一、视图 1.1创建视图 1.2视图影响基表 1.3基表影响视图 1.4删除视图 1.5视图使用规则 二、数据库的用户 2.1mysql中的user表 注意事项:主机/用户名/密码/权限 2.2用户的创建 注意事项:设置密码与登录地点需谨慎 2.3删除用户 注意事项:% 2.4…

Python 中的三重引号

Python 中的三重引号,我之前以为只有长注释的作用,仔细查了下,原来还有给函数、类添加说明的作用。这个功能太好了,大大增加了代码的可读性。 具体的作用,总计如下。 1. 定义长字符串 其实三重引号的最直接作用是用…

rust中解决DPI-1047: Cannot locate a 64-bit Oracle Client library问题

我们在使用rust-oracle crate连接oracle进行测试的过程中,会发现无法连接oracle,测试运行过程中抛出“DPI-1047: Cannot locate a 64-bit Oracle Client library”错误。该问题是由于rust-oracle需要用到oracle的动态连接库,我们通过安装orac…

Python + 深度学习从 0 到 1(00 / 99)

希望对你有帮助呀!!💜💜 如有更好理解的思路,欢迎大家留言补充 ~ 一起加油叭 💦 欢迎关注、订阅专栏 【深度学习从 0 到 1】谢谢你的支持! ⭐ 什么是深度学习? 人工智能、机器学习与…

太通透了,Android 流程分析 蓝牙enable流程(应用层/Framework/Service层)

零. 前言 由于Bluedroid的介绍文档有限,以及对Android的一些基本的知识需要了(Android 四大组件/AIDL/Framework/Binder机制/JNI/HIDL等),加上需要掌握的语言包括Java/C/C等,加上网络上其实没有一个完整的介绍Bluedroid系列的文档&#xff0…

【MySQL课程学习】:MySQL安装,MySQL如何登录和退出?MySQL的简单配置

🎁个人主页:我们的五年 🔍系列专栏:MySQL课程学习 🌷追光的人,终会万丈光芒 🎉欢迎大家点赞👍评论📝收藏⭐文章 目录 MySQL在Centos 7环境下的安装: 卸载…

安宝特分享 | 如何利用AR技术革新医疗实践:从远程急救到多学科协作

AR技术在国内外医院的应用 在现代医疗环境中,患者面临的挑战依然严峻:看病难、看病远、看病急。这些问题不仅影响了患者的治疗效果,也让医务工作者倍感压力。幸运的是,随着增强现实(AR)技术的发展&#xf…

macOS 无法安装第三方app,启用任何来源的方法

升级新版本 MacOS 后,安装下载的软件时,不能在 ”安全性与隐私” 中找不到 ”任何来源” 选项。 1. 允许展示任何来源 点击 启动器 (Launchpad) – 其他 (Other) – 终端 (Terminal): 打开终端后,输入以下代码回车: …

Rust中Tracing 应用指南

欢迎来到这篇全面的Rust跟踪入门指南。Rust 的tracing是一个用于应用程序级别的诊断和调试的库。它提供了一种结构化的、异步感知的方式来记录日志和跟踪事件。与传统的日志记录相比,tracing能够更好地处理复杂的异步系统和分布式系统中的事件跟踪,帮助开…

介绍一下strset(arr,ch);(c基础)

hi , I am 36 适合对象c语言初学者 strset(arr,ch)函数 功能 是将arr数组全部赋值为ch 格式 #include<string.h> strset(arr,ch); 返回值为arr 链接分享一下arr的意义(c基础)(必看)(牢记)-CSDN博客 hi I am 36.thanks for your looking .&#x1f44d;&#x1…

Web3与智能合约:区块链技术下的数字信任体系

随着互联网的不断发展&#xff0c;Web3代表着我们迈入了一个去中心化、更加安全和智能的网络时代。作为Web3的核心组成部分&#xff0c;区块链技术为智能合约的出现和发展提供了强有力的基础。智能合约不仅仅是自动化的代码&#xff0c;它们正逐步成为重塑数字世界信任体系的关…

如何更改手机GPS定位

你是否曾想过更改手机GPS位置以保护隐私、玩游戏或访问受地理限制的内容&#xff1f;接下来我将向你展示如何使用 MagFone Location Changer 更改手机GPS 位置&#xff01;无论是在玩Pokmon GO游戏、发布社媒贴子&#xff0c;这种方法都快速、简单且有效。 第一步&#xff1a;下…

青少年编程等级考试C++一级,硬币反转问题

代码 #include<iostream>using namespace std;bool a[300];int main(){ int n,m; cin >> n >> m; for(int i 1;i < m;i) { for (int j 1;j < n;j) { if( j % i 0) { a[j] !a[j];…

微信小程序技术架构图

一、视图层1.WXML&#xff08;WeiXin Markup Language&#xff09; 这是微信小程序的标记语言&#xff0c;类似于 HTML。它用于构建小程序的页面结构。例如&#xff0c;通过标签来定义各种视图元素&#xff0c;如<view>&#xff08;类似于 HTML 中的<div>&#xff…

《生成式 AI》课程 作业6 大语言模型(LLM)的训练微调 Fine Tuning -- part2

资料来自李宏毅老师《生成式 AI》课程&#xff0c;如有侵权请通知下线 Introduction to Generative AI 2024 Spring 来源背景说明 该文档主要介绍了国立台湾大学&#xff08;NTU&#xff09;2024 年春季 “生成式人工智能&#xff08;GenAI&#xff09;” 课程的作业 5&#…

gocv调用opencv添加中文乱码的解决方案

前言 相信很多做视觉的同学在使用opencv给图片添加中文文字的时候会出现这样的乱码显示: 而实际上你期望的是“告警时间:2011-11-11 11:11:11 告警类型:脱岗检测告警 Area:XXXXX Camera:Camera001-001”这样的显示内容,那么这篇文章我将用很简单的方法来解决乱码问题,只需…

【自用】常用希腊字母表

常用希腊字母表 原文链接 https://xilazimu.net/

【UE5】在材质中计算模型在屏幕上的比例

ViewProperty节点有很多有意思的变量 例如用 ViewProperty 的 tan ⁡ ( FOV / 2 ) \tan(\text{FOV} / 2) tan(FOV/2) 输出&#xff0c;用它计算模型占屏幕的比例。 &#xff08;常用于for运算的次数优化&#xff0c;也可以用于各种美术效果&#xff09; ScaleOnScreen Obje…

耳朵“嗡嗡”响,这是怎么啦

耳朵嗡嗡响&#xff0c;医学上称为耳鸣&#xff08;Tinnitus&#xff09;&#xff0c;是一种常见的症状&#xff0c;表现为耳朵内持续或间歇性的嗡嗡声、响声或鸣叫声。耳鸣的原因有很多&#xff0c;以下是一些常见的原因和相应的解决方法&#xff1a; 常见原因 1. 长时间暴露…