Oracle索引

Oracle索引

一、索引介绍

1.为什么使用索引

索引是存储引擎用于快速找到数据记录的一种数据结构,就好比一本教课书的目录部分,通过目录中找到对应文章的页码,便可快速定位到需要的文章。Oracle中也是一样的道理,进行数据查找时,首先查看查询条件是否命中某条索引,符合则通过索引查找相关数据,如果不符合则需要全表扫描,即需要一条一条地查找记录,直到找到与条件符合的记录。

在这里插入图片描述

如上图所示,数据库在没有索引的情况下,数据分布在硬盘的不同位置上面,读取数据时,摆臂需要前后摆动查找,这样操作非常耗时。如果数据顺序摆放,那么也需要从1到6行按顺序读取,这样就相当于进行了六次IO操作,依旧非常耗时。如果我们不借助任何索引结构帮助我们快速定位数据的话,我们查找Col2=89这条数据,就要逐行去查找、去比较。从Col2=34开始,进行比较,发现不是,继续下一行。我们当前的表只有不到10行数据,但如果表很大的话,有上千万条数据,就意味着要做很多很多次磁盘I/0才能找到。现在要查找Col2=89这条记录。CPU必须先去磁盘查找这条记录,找到之后加载到内存,再对数据进行处理。这个过程最耗时间的就是磁盘I/O(涉及到磁盘的旋转时间(速度较快)、磁头的寻道时间(速度慢、费时))

假如给数据使用 二叉树 这样的数据结构进行存储,如下图所示:

在这里插入图片描述


对字段Col2添加了索引,就相当于在硬盘上为Col2维护了一个索引的数据结构,即这个二叉搜索树。二叉搜索树的每个结点存储的是(K,V)结构,key是Col 2,value是该key所在行的文件指针(地址)。比如:该二叉搜索树的根节点就是:(34,0x07)。现在对Col2添加了索引,这时再去查找Col2=89这条记录的时候会先去查找该二叉搜索树(二叉树的遍历查找)。读34到内存,89>34;继续右侧数据,读89到内存,89==89;找到数据返回。找到之后就根据当前结点的value快速定位到要查找的记录对应的地址。我们可以发现,只需要查找两次就可以定位到记录的地址,查询速度就提高了。

这就是我们为什么要建索引,目的就是为了减少磁盘I/0的次数,加快查询速率。

2.索引及其优缺点

索引概述
索引的定义为:索引(Index)是帮助MySQL高效获取数据的数据结构

索引的本质:索引是数据结构。你可以简单理解为“排好序的快速查找数据结构”,满足特定查找算法。 这些数据结构以某种方式指向数据, 这样就可以在这些数据结构的基础上实现高级查找算法

索引是在存储引擎中实现的,因此每种存储引擎的索引不一定完全相同,并且每种存储引擎不一定支持所有索引类型。同时,存储引擎可以定义每个表的最大索引数最大索引长度。所有存储引擎支持每个表至少16个存储引擎,总索引长度至少为256字节。有些存储引擎支持更多的索引数和更大的索引长度。

优点
1.类似大学图书馆建书目索引,提高数据检索的效率,降低数据库的IO成本 ,这也是创建索引最主要的原因。
2.通过创建唯一索引,可以保证数据库表中每一行数据的唯一性
3.在实现数据的 参考完整性方面,可以加速表和表之间的连接 。换句话说,对于有依赖关系的子表和父表联合查询时,可以提高查询速度。
4.在使用分组和排序子句进行数据查询时,可以显著减少查询中分组和排序的时间,降低了CPU的消耗。

缺点
1.创建索引和维护索引要耗费时间,并且随着数据量的增加,所耗费的时间也会增加。
2.索引需要占磁盘空间,除了数据表占数据空间之外,每一个索引还要占一定的物理空间,存储在磁盘上,如果有大量的索引,索引文件就可能比数据文件更快达到最大文件尺寸。
3.虽然索引大大提高了查询速度,同时却会降低更新表的速度。当对表中的数据进行增加、删除和修改的时候,索引也要动态地维护,这样就降低了数据的维护速度。

因此,选择使用索引时,需要综合考虑索引的优点和缺点。

提示:
索引可以提高查询的速度,但是会影响插入记录的速度。在这种情况下,最好的办法是先删除表中的索引,然后插入数据,插入完成后再创建索引。

3.Oracle的各种索引

优先使用 B-Tree 索引 + 组合索引,根据查询模式添加函数索引或位图索引。
索引类型特点适用场景创建命令备注
B-Tree 索引
(默认索引类型)
- 平衡树结构
- 适合等值查询/范围查询
- 适合高基数列
- 默认索引类型
主键查询、单列查询、多列查询CREATE INDEX idx_name ON table_name (column);
示例:
CREATE INDEX idx_emp_last_name ON employees(last_name);
Oracle 默认索引类型(非唯一)
唯一索引- 确保列值唯一
- 允许 NULL(但仅一个 NULL)
- 创建主键时自动创建
保证列唯一性(如邮箱、身份证号)CREATE UNIQUE INDEX idx_name ON table_name (column);
示例:
CREATE UNIQUE INDEX idx_emp_email ON employees(email);
B树结构, B树索引 + UNIQUE 约束
组合索引
(复合索引)
- 多列的B树索引
- 最左前缀原则(查询必须包含最左列)
- 适合多条件查询
WHERE dept_id = 10 AND job = 'Manager' 等多条件查询CREATE INDEX idx_name ON table_name (col1, col2, col3);
示例:
CREATE INDEX idx_emp_dept_job ON employees(department_id, job);
B树结构, B树索引 + 多列
位图索引- 用位图(bit array)存储数据
- 专为低基数列设计(如性别、状态)
- 适合数据仓库(DWH)
- 不适合高并发写入
低基数列查询(如 gender = 'M'
数据仓库场景
CREATE BITMAP INDEX idx_name ON table_name (column);
示例:
CREATE BITMAP INDEX idx_emp_gender ON employees(gender);
函数索引- 在表达式/函数上创建索引
- 查询必须使用相同函数才能命中
- 适合 UPPER(), LOWER() 等函数
WHERE UPPER(last_name) = 'SMITH' 等函数查询CREATE INDEX idx_name ON table_name (FUNCTION(column));
示例:
CREATE INDEX idx_upper_name ON employees(UPPER(last_name));
索引组织表
(IOT)
- 表数据存储在索引中
- 消除回表操作
- 适合主键查询为主场景
- 必须定义主键
主键查询(如 WHERE employee_id = 100
高性能读取场景
CREATE TABLE table_name (
col1 PRIMARY KEY,
col2,
...
) ORGANIZATION INDEX;<br>示例:<br>CREATE TABLE employees_iot (<br> employee_id NUMBER PRIMARY KEY,<br> last_name VARCHAR2(25),<br> department_id NUMBER<br>) ORGANIZATION INDEX;
位图连接索引- 加速连接查询(如 table1.join_col = table2.join_col
- 专为星型模型设计
- 通常用于数据仓库
数据仓库星型模型连接查询
sales JOIN employees
CREATE BITMAP INDEX idx_name ON table1(col1)
TABLE table2 (join_col)
WHERE table2.status = 'ACTIVE';
示例:
CREATE BITMAP INDEX idx_sales_emp ON sales(sale_id)
TABLE employees (employee_id)
WHERE employees.status = 'ACTIVE';
逆序索引- 反转索引键值(如 ‘123’ → ‘321’)
- 解决索引尾部热点问题
- 提升自增ID写入性能
自增ID插入(如 employee_id 递增)
高并发写入场景
CREATE INDEX idx_name ON table_name (column) REVERSE;
示例:
CREATE INDEX idx_emp_id_rev ON employees(employee_id) REVERSE;
本地分区索引- 索引分区 = 表分区
- 默认分区索引类型
- 适合分区表
分区表的查询(如 WHERE sale_date BETWEEN ...CREATE INDEX idx_name ON table_name (col) LOCAL;
示例:
CREATE INDEX idx_sales_date ON sales(sale_date) LOCAL;
全局分区索引- 索引分区独立于表分区
- 适合范围查询
- 需维护分区
全局范围查询(如 WHERE sale_date BETWEEN '2023-01-01' AND '2023-12-31'CREATE INDEX idx_name ON table_name (col)
GLOBAL PARTITION BY RANGE (col) (
PARTITION p1 VALUES LESS THAN (1000),
PARTITION p2 VALUES LESS THAN (2000)
);<br>示例:<br>CREATE INDEX idx_sales_amount ON sales(amount)<br>GLOBAL PARTITION BY RANGE (amount) (<br> PARTITION p1 VALUES LESS THAN (1000),<br> PARTITION p2 VALUES LESS THAN (2000)<br>);

4.各种索引创建命令

--B-Tree 索引CREATEINDEX idx_name ON table_name (column);--创建命令CREATEINDEX idx_emp_last_name ON employees(last_name);--示例--唯一索引CREATEUNIQUEINDEX idx_name ON table_name (column);--创建命令CREATEUNIQUEINDEX idx_emp_email ON employees(email);--示例--组合索引(复合索引)CREATEINDEX idx_name ON table_name (col1, col2, col3);--创建命令CREATEINDEX idx_emp_dept_job ON employees(department_id, job);--示例--位图索引CREATE BITMAP INDEX idx_name ON table_name (column);--创建命令CREATE BITMAP INDEX idx_emp_gender ON employees(gender);--示例--函数索引CREATEINDEX idx_name ON table_name (FUNCTION(column));--创建命令CREATEINDEX idx_upper_name ON employees(UPPER(last_name));--示例--索引组织表(IOT)CREATETABLE table_name ( col1 PRIMARYKEY, col2,...) ORGANIZATION INDEX;--创建命令CREATETABLE employees_iot ( employee_id NUMBER PRIMARYKEY, last_name VARCHAR2(25), department_id NUMBER) ORGANIZATION INDEX;--示例--位图连接索引CREATE BITMAP INDEX idx_name ON table1(col1)TABLE table2 (join_col)WHERE table2.status='ACTIVE';--创建命令CREATE BITMAP INDEX idx_sales_emp ON sales(sale_id)TABLE employees (employee_id)WHERE employees.status='ACTIVE';--示例--逆序索引CREATEINDEX idx_name ON table_name (column) REVERSE;--创建命令CREATEINDEX idx_emp_id_rev ON employees(employee_id) REVERSE;--示例--本地分区索引CREATEINDEX idx_name ON table_name (col)LOCAL;--创建命令CREATEINDEX idx_sales_date ON sales(sale_date)LOCAL;--示例--全局分区索引CREATEINDEX idx_name ON table_name (col)GLOBALPARTITIONBY RANGE (col)(PARTITION p1 VALUES LESS THAN (1000),PARTITION p2 VALUES LESS THAN (2000));--创建命令CREATEINDEX idx_sales_amount ON sales(amount)GLOBALPARTITIONBY RANGE (amount)(PARTITION p1 VALUES LESS THAN (1000),PARTITION p2 VALUES LESS THAN (2000));--示例

二、各种索引详解

1.B树索引

Oracle数据库中最常见的索引类型是b-tree索引,也就是B-树索引,以其同名的计算科学结构命名。Oracle 默认索引类型(未指定类型时自动创建)

特点:
适合与大量的增、删、改(OLTP)
不能用包含OR操作符的查询;
适合高基数的列(唯一值多)
典型的树状结构;
每个结点都是数据块;
大多都是物理上一层、两层或三层不定,逻辑上三层;
叶子块数据是排序的,从左向右递增;
在分支块和根块中放的是索引的范围;

技巧:
索引列的值都存储在索引中。因此,可以建立一个组合(复合)索引,这些索引可以直接满足查询,而不用访问表。这就不用从表中检索数据,从而减少了I/O量。

2.唯一索引

B树索引 + UNIQUE 约束(确保列值唯一)
允许一个 NULL(NULL 不参与唯一性比较)
创建主键时自动创建唯一索引

3.组合索引

多列的B树索引
最左前缀原则:查询条件必须包含最左列才能命中索引

4.位图索引

位图索引:专为低基数列设计的特殊索引(如性别、状态)

特点:
不适合高并发写入
非常适合OR操作符的查询;
基数比较少的时候才能建位图索引;

技巧:
对于有较低基数的列需要使用位图索引。性别列就是这样一个例子,它有两个可能值:男或女(基数仅为2)。位图对于低基数(少量的不同值)列来说非常快,这是因为索引的尺寸相对于B树索引来说小了很多。因为这些索引是低基数的B树索引,所以非常小,因此您可以经常检索表中超过半数的行,并且仍使用位图索引。
当大多数条目不会向位图添加新的值时,位图索引在批处理(单用户)操作中加载表(插入操作)方面通常要比B树做得好。当多个会话同时向表中插入行时不应该使用位图索引,在大多数事务处理应用程序中都会发生这种情况。
在一个查询中合并多个位图索引后,可以使性能显著提高。位图索引使用固定长度的数据类型要比可变长度的数据类型好。较大尺寸的块也会提高对位图索引的存储和读取性能。

5.函数索引

在表达式/函数上创建的索引(非原始列)
查询条件必须使用相同函数才能命中索引

可以在表中创建基于函数的索引。如果没有基于函数的索引,任何在列上执行了函数的查询都不能使用这个列的索引。例如,下面的查询就不能使用JOB列上的索引,除非它是基于函数的索引:

select*from emp where UPPER(job)='MGR';

下面的查询使用JOB列上的索引,但是它将不会返回JOB列具有Mgr或mgr值的行:

select*from emp where job ='MGR';

可以创建这样的索引,允许索引访问支持基于函数的列或数据。可以对列表达式UPPER(job)创建索引,而不是直接在JOB列上建立索引,如:

createindex EMP$UPPER_JOB on emp(UPPER(job));

尽管基于函数的索引非常有用,但在建立它们之前必须先考虑下面一些问题:
能限制在这个列上使用的函数吗?如果能,能限制所有在这个列上执行的所有函数吗
是否有足够应付额外索引的存储空间?
在每列上增加的索引数量会对针对该表执行的DML语句的性能带来何种影响?
基于函数的索引非常有用,但在实现时必须小心。在表上创建的索引越多,INSERT、UPDATE和DELETE语句的执行就会花费越多的时间。

6.索引组织表

表数据直接存储在主键索引的叶子节点中(而非单独存储数据块)
无需额外回表操作(查询主键时直接获取数据)

普通表结构:
索引 (B-Tree) → 数据块 (ROWID) → 数据行
IOT 结构:
索引 (B-Tree) → 数据行 (直接存储在叶子节点)

7.位图连接索引

位图索引的扩展,直接关联多表的连接条件
专为数据仓库的星型模型设计(如 fact_table JOIN dimension_table)

8.逆序索引

反转索引键值(如 123 → 321,ABC → CBA)
解决自增ID插入时的索引尾部热点问题(避免频繁修改索引最后一个叶子块)

普通 B-Tree 索引(自增ID):
1, 2, 3, 4, 5, 6, 7, 8, 9, 10 → 每次插入都修改最后叶子块
逆序索引:
1 → 1, 2 → 2, 3 → 3, 4 → 4, 5 → 5, 6 → 6, 7 → 7, 8 → 8, 9 → 9, 10 → 01 →
插入位置分散在索引各处

9.本地分区索引

索引分区 = 表分区(表分区1 → 索引分区1,表分区2 → 索引分区2)
自动维护:表分区操作(如 ADD PARTITION)会自动同步到索引

表分区:
sales_2023Q1 (2023-01-01 ~ 2023-03-31)
sales_2023Q2 (2023-04-01 ~ 2023-06-30)
本地分区索引:
idx_sales_date_2023Q1 (仅包含 2023Q1 数据)
idx_sales_date_2023Q2 (仅包含 2023Q2 数据)

10.全局分区索引

索引分区独立于表分区(索引分区1可能包含多个表分区的数据)
需手动维护:表分区操作后需重建索引

表分区:
sales_2023Q1 (2023-01-01 ~ 2023-03-31)
sales_2023Q2 (2023-04-01 ~ 2023-06-30)
全局分区索引:
idx_sales_date_p1 (包含 sales_2023Q1 + sales_2023Q2 的部分数据)
idx_sales_date_p2 (包含 sales_2023Q1 + sales_2023Q2 的其他数据)

Read more

什么是 JWT?一文彻底搞懂 JSON Web Token(附 Spring Boot 实战)

视频看了几百小时还迷糊?关注我,几分钟让你秒懂! 你是否经常听到这些词: * “我们用 JWT 做登录认证” * “前端把 token 放在 Authorization 头里” * “JWT 无状态,适合分布式系统” 但你真的理解 JWT 到底是什么?它怎么工作?和 Session 有什么区别? 吗? 今天我们就用 通俗语言 + 图解 + Spring Boot 代码实战,带你从零彻底搞懂 JWT! 🧩 一、一句话解释 JWT JWT(JSON Web Token)是一种开放标准(RFC 7519),用于在网络应用间安全地传递“声明”(claims)的紧凑、自包含令牌。 简单说:JWT 就是一个加密的字符串,里面包含了用户身份信息,

By Ne0inhk

从数学概率到神经网络:双色球预测的算法演进史

从数学概率到神经网络:双色球预测的算法演进史 彩票预测一直是数学家和计算机科学家们热衷探索的领域。双色球作为一种典型的随机游戏,其预测方法经历了从传统概率统计到现代深度学习的演变过程。本文将带您回顾这一技术发展历程,分析不同算法的原理与效果,并探讨未来可能的发展方向。 1. 传统概率统计方法的探索 早期的双色球预测主要依赖概率统计理论。数学家们试图通过分析历史数据中的数字分布规律来预测未来结果。这种方法基于一个基本假设:虽然每次开奖都是独立事件,但长期来看数字出现频率会趋于均衡。 常见概率统计方法包括: * 频率分析法:统计各号码的历史出现频率,认为出现次数较少的号码"更有可能"在未来出现 * 间隔分析法:计算号码连续未出现的期数,预测"冷号"和"热号" * 和值分析法:研究红球号码总和的历史分布规律 * 奇偶比分析法:分析奇数和偶数号码的比例关系 这些方法虽然简单直观,但存在明显局限。双色球本质上是一个独立随机事件,每次开奖结果不受历史影响。统计规律只能提供参考,无法保证预测准确性。 注意:概率统计方法更适合分析长期趋势,对单期预测的指导意义有限。 2.

By Ne0inhk
【排序算法】快速排序、冒泡排序

【排序算法】快速排序、冒泡排序

文章目录 * 快速排序 * 1.hoare版本(左右指针法) * 时间复杂度、空间复杂度分析 * 优化——三数取中法 * 2.挖坑法 * 3.前后指针版本 * 优化:小区间优化 * 快速排序非递归代码——借助栈 * 冒泡排序 * 时间复杂度 快速排序 1.hoare版本(左右指针法) 代码: intPartSort1(int* a,int left,int right){// 使用三数取中法获取基准值的下标int midi =GetMidi(a, left, right);Swap(&a[left],&a[midi]);// 将基准值移到最左边int keyi = left;// 基准值的下标while(left <

By Ne0inhk
MMDetection3D 所有核心Backbone、Neck、数据集类型、完整模型算法详细剖析(超详细)

MMDetection3D 所有核心Backbone、Neck、数据集类型、完整模型算法详细剖析(超详细)

🎯 框架定位 MMDetection3D 是 OpenMMLab 生态中专注于3D目标检测、3D语义分割、多模态感知的工业级框架,支持点云、单/多视角图像、多传感器融合等输入,广泛适配自动驾驶、机器人导航、工业质检等场景。其模块化设计(Backbone→Neck→Head)与 MMSegmentation 完全对齐,可快速复用2D生态的成熟模块。 🔧 一、MMDetection3D 所有核心 Backbone(骨干网络) Backbone 是3D感知的特征提取核心,负责从原始3D数据(点云/体素/图像)中提取底层特征,支持三类骨干,所有Backbone均可在配置文件中通过backbone:字段直接调用,部分支持预训练权重加载。 1. 点云专用 Backbone(3D 特征提取核心) 专为点云稀疏性、无序性设计的骨干,是3D感知的基础核心。 BackboneMMDetection3D 配置标识核心特点适配场景PointNet++PointNet2Backbone多尺度分组(MSG/

By Ne0inhk