Oracle && OceanBase 相关文档,希望互相学习,
共同进步
1.背景
生产由于频繁查某个大表,优化时需要给字段增加索引,根据实际业务场景,发现大表的使用中频繁需要查询某几个字段,于是把这几个字段建立复合索引,方便索引命中。另外,本文还对比了 全局复合索引、本地复合索引的利弊,分析了 复合索引和分区字段的共用的情况。
欢迎各位同行一起探讨,共同学习。上节增加单列索引:
【Oracle专栏】千万数据表增加索引会影响插入吗
https://blog.csdn.net/weixin_42081167/article/details/164849971
2. 实验
2.1 测试环境数据大小
sql
select /*+parallel(5)*/count(*) from FM_RPT_KMYEB t;
--生产 2.7亿 271268263
--测试 873万 8737767
select sum(t.bytes)/1024/1024/1024 from user_segments t
where t.segment_name='FM_RPT_KMYEB'
--生产 35.16G
--测试 1.44G
表数据上百万,生产上亿。表分区字段为 DATE_ID
sqlselect * from FM_RPT_KMYEB T WHERE T.BANK_CODE = '014007029100004001' AND T.BOOK_ID = 'ff8080819391477b0193aad6673c0959' --AND T.DATE_ID BETWEEN '2022-01' AND '2022-02' AND T.DATE_ID >= '2022-01' and T.DATE_ID <='2022-02'
sql执行计划:

2.2 实验 复合索引
上节增加bank_code 的索引,虽然命中了,但还是可以 进一步优化。上节内容如下:
【Oracle专栏】千万数据表增加索引会影响插入吗
https://blog.csdn.net/weixin_42081167/article/details/164849971
1 实验思路
根据业务情况,发现还可以升级为复合分区索引,把 BANK_CODE、BOOK_ID、DATE_ID 组合起来,实现完全免回表的覆盖查询,性能还能再提升一个量级,彻底消除全分区扫描的可能性。
- 规划索引列顺序 :严格遵循「等值查询列在前,范围查询列在后」原则,本场景下推荐为
BANK_CODE→BOOK_ID→DATE_ID,完全匹配现有查询的过滤逻辑。- 提前检查存储空间:确认索引所在表空间剩余容量≥表数据量的1/3,避免创建过程中空间不足报错。
1)使用
ONLINE在线语法避免阻塞业务写入,搭配NOLOGGING减少大表场景下的重做日志开销,同时开启并行加速创建
sqlCREATE INDEX IDX_FM_RPT_KMYEB_COMP ON FM_RPT_KMYEB (BANK_CODE, BOOK_ID, DATE_ID) LOCAL -- 声明为本地分区索引,自动与表分区一一绑定 TABLESPACE IDX_TBS -- 指定独立的索引表空间,提升IO性能 ONLINE -- 在线创建,不阻塞业务插入更新 PARALLEL 8 -- 开启8并行度,大幅压缩大表创建耗时 NOLOGGING -- 关闭重做日志,减少磁盘IO压力 COMPRESS 2; -- 启用键压缩,减少重复索引值的存储空间2)创建完成后必须将索引并行度改回默认值,避免后续业务查询被意外强制走并行执行,消耗过多系统资源
sqlALTER INDEX IDX_FM_RPT_KMYEB_COMP NOPARALLEL; ALTER INDEX IDX_FM_RPT_KMYEB_COMP LOGGING;注意:
- ❌ 不要将分区键放在复合索引的前导列,否则会破坏最左前缀匹配规则,导致等值查询条件无法命中索引。
- ❌ 禁止在创建过程中对表执行DDL操作,避免出现索引分区状态异常。
- ✅ 对于按日期分区的大表,后续执行
DROP PARTITION等维护操作时,Oracle会自动同步清理对应索引分区,无需手动重建全量索引。
2.相关问题
1)是否需要删除原有的单列索引?
新建的(BANK_CODE, BOOK_ID, DATE_ID)复合分区索引已经完全覆盖了原单列
BANK_CODE索引的所有查询能力,保留单列索引属于冗余设计,推荐直接删除。✅ 保留单列索引的弊端
额外空间占用 :单列索引会额外占用磁盘存储空间,对于2.7亿行的大表,单列索引本身可能占用数GB空间,和复合索引形成双重存储浪费。
DML性能损耗 :每次执行INSERT/UPDATE/DELETE操作时,Oracle需要同时维护两个索引的B树结构,写入开销直接翻倍,高并发场景下会明显拖慢写入性能。
优化器选择混乱 :当两个索引都能匹配查询条件时,CBO优化器可能生成错误的执行计划,出现本该走复合索引却误选单列索引的情况,导致查询性能波动。
📋 唯一需要保留单列索引的特殊场景:
- 存在大量仅使用
BANK_CODE单个字段作为过滤条件的高频查询,且这些查询无法被复合索引的前导列完全覆盖。本场景中复合索引前导列就是BANK_CODE,天然兼容单列等值查询
2)date_id 已是分区索引了,还需要在复合索引中吗?
DATE_ID作为分区字段,即使本身已经是分区索引,DATE_ID加入复合索引不会产生冗余存储,反而能替代单独的DATE_ID分区索引,减少索引总数,降低DML操作的写入维护开销。能带来显著性能收益,并非冗余设计。
DATE_ID不能放在复合索引的前导列,必须放在等值查询字段
BANK_CODE、BOOK_ID之后,否则会破坏最左前缀匹配规则,导致等值查询条件无法高效命中索引,反而降低查询性能。
- 强化分区裁剪能力 :本地复合分区索引的分区结构和表分区严格一对一绑定,把DATE_ID加入索引后,查询可以直接在索引层面完成分区裁剪,无需先回表判断分区范围,进一步减少不必要的IO开销。
- 适配唯一索引强制约束 :如果后续要在
BANK_CODE + BOOK_ID上创建本地唯一索引,Oracle强制要求必须包含分区键DATE_ID,否则会直接抛出ORA-14038错误,无法创建局部唯一索引。- 实现完全覆盖查询 :当DATE_ID作为索引列的一部分时,查询的所有过滤条件都能在索引中完成判断,无需回表读取表数据,把IO开销降到最低。
3. 创建复合索引
sql
CREATE INDEX IDX_FM_RPT_KMYEB_COMP ON FM_RPT_KMYEB (BANK_CODE, BOOK_ID, DATE_ID)
ONLINE PARALLEL 8 NOLOGGING COMPRESS 2; -- 启用键压缩,减少重复索引值的存储空间
执行:800多万1.44G 用时22秒

sql
ALTER INDEX IDX_FM_RPT_KMYEB_COMP NOPARALLEL;
ALTER INDEX IDX_FM_RPT_KMYEB_COMP LOGGING;
---删除单列索引
drop index idx_FM_RPT_KMYEB_bank;
sql执行计划比较:全局复合索引


4. 改为本地复合索引
sql
--全局复合分区
drop index IDX_FM_RPT_KMYEB_COMP;
CREATE INDEX IDX_FM_RPT_KMYEB_COMP ON FM_RPT_KMYEB (BANK_CODE, BOOK_ID, DATE_ID)
ONLINE PARALLEL 8 NOLOGGING COMPRESS 2; -- 启用键压缩,减少重复索引值的存储空间
ALTER INDEX IDX_FM_RPT_KMYEB_COMP NOPARALLEL;
ALTER INDEX IDX_FM_RPT_KMYEB_COMP LOGGING;
--本地复合分区
drop index IDX_FM_RPT_KMYEB_COMP1;
CREATE INDEX IDX_FM_RPT_KMYEB_COMP1 ON FM_RPT_KMYEB (BANK_CODE, BOOK_ID, DATE_ID) local
ONLINE PARALLEL 8 NOLOGGING COMPRESS 2; -- 启用键压缩,减少重复索引值的存储空间
ALTER INDEX IDX_FM_RPT_KMYEB_COMP1 NOPARALLEL;
ALTER INDEX IDX_FM_RPT_KMYEB_COMP1 LOGGING;
sql执行计划比较:本地复合索引

5.全局复合索引 貌似比本地复合索引 性能下降了?
从两张执行计划的实测数据来看,并不是本地索引性能下降,反而是全局复合索引的执行成本更高,本地复合索引的实际表现更适配分区大表场景。
| 索引类型 | 执行成本 | 核心访问逻辑 | 实际IO开销 |
|---|---|---|---|
| 全局复合索引 | 5 | 直接走全局索引范围扫描后回表 | 要遍历整棵全局B树,跨所有分区查找目标行 |
| 本地复合索引 | 6 | 先做分区裁剪,再走本地索引范围扫描后回表 | 先跳过所有无关分区,仅在目标分区内扫描索引 |
🔍看似"成本略高"的真实原因
执行计划里的成本值差异极小,几乎可以忽略不计,本地索引多出来的1点成本,是Oracle执行分区裁剪的极小计算开销,完全不会影响实际查询速度。
本地索引的
PARTITION LIST ITERATOR操作,代表优化器已经自动识别到了DATE_ID的范围条件,直接跳过2022-01和2022-02之外的所有历史分区,避免了扫描全量索引数据。全局索引没有分区裁剪能力,哪怕只查两个月的数据,也要扫描整棵全局索引的所有分支块,在数据量持续增长的场景下,后续性能会越来越差。
✅ 本地索引的长期性能优势
随着表数据量持续增长,本地索引的性能会保持稳定,因为每次查询只需要访问极小范围的分区索引段,不会随着总数据量膨胀而变慢。
高并发写入场景下,本地索引的每个分区独立维护,不会出现全局索引所有DML操作争抢同一棵B树根块的锁竞争问题,写入性能更稳定。
后续清理历史分区时,本地索引会自动同步清理对应索引分区,不会出现全局索引直接失效需要全量重建的问题,运维成本极低。
3.知识点 🎯
1)维度对比
| 对比维度 | 全局复合索引 | 本地分区复合索引 |
|---|---|---|
| 分区维护影响 | 执行DROP/TRUNCATE分区操作时,索引会直接变为UNUSABLE,必须手动全量重建,亿级表重建可能耗时数小时 | 分区维护操作自动同步对应索引分区,完全不会影响其他索引分区,无需人工干预 |
| 分区裁剪能力 | 不支持分区裁剪,哪怕只查单个分区数据,也需要扫描整棵全局索引B树 | 天然支持分区裁剪,查询含分区键时直接定位到对应索引分区,跳过所有无关分区,IO开销仅为全局索引的几十分之一 |
| 写入性能 | 所有DML操作都争抢同一棵全局索引的根块,高并发场景下容易出现锁竞争,成为写入瓶颈 | 每个分区的索引独立存储,DML操作仅影响当前分区的索引段,写入压力天然分散,性能更稳定 |
| 唯一约束支持 | 可以直接建立跨分区的全局唯一约束,无需包含分区键 | 只能保证单分区内唯一,要实现全局唯一必须把分区键加入索引列中 |
两者的核心差异集中在分区绑定关系、运维成本和性能适配场景上,完全适配当前的亿级分区大表优化需求。
2)核心结构差异
- 全局复合索引 :是一个完整的单棵B树结构,跨表所有分区独立存在,索引分区规则和表分区规则完全解耦,索引分区数量和表分区数量没有必然关联。
- 本地分区复合索引 :索引分区和表分区严格一一对应,索引分区键必须和表分区键保持一致,新增/删除表分区时,索引分区数量会自动同步变化,无需人工干预。
3)适配场景差异
- 全局复合索引适用场景 :高并发OLTP系统中,频繁按非分区业务唯一键做单点查询,且分区维护操作频率极低,可接受短时间的索引重建窗口。
- 本地分区复合索引适用场景 :像当前的按日期分区的亿级大表,高频查询都包含分区键,需要频繁按时间归档清理历史分区,追求7×24小时业务不中断,是数据仓库和海量分析场景的最优选择。

放松一下,加个知识点 😊:
OLTP (全称 Online Transaction Processing),中文叫联机事务处理,是处理日常业务交易记录的数据库技术。简单说就是每天用的那些"点一下就生效"的操作,比如银行转账、电商下单、超市收银,都靠 OLTP 系统在背后撑着。
核心特点:
- 高并发处理能力:能同时支撑大量用户操作,像银行网点同时办理业务的客户,或者电商大促时瞬间涌入的下单请求。
- 数据实时性:每一笔操作都要立即生效,实时更新到数据库中,用户不能等。
- 事务完整性:保证每一笔交易都准确无误地完成,要么都成要么都不成,即ACID 特性
OLAP (联机分析处理) 和 OLTP (联机事务处理) 区别:1)OLTP 是数据的"源头",主攻"业务执行",核心是事务处理,常用"多维模型"或"数据立方体",更新频率极高,每发生一笔业务就要执行更新。 数据实时性是其关键要求。**处理的数据量相对较小(主要是当前活跃的业务数据)。**用户进行操作(比如点击提交订单),系统必须在秒级甚至毫秒级内响应,否则用户体验会非常差,甚至导致交易失败或业务中断。企业的日常运作,每时每刻都在通过OLTP系统产生最原始的业务数据。
- OLTP系统: 最看重高并发处理能力 和低延迟。系统设计必须能随着业务增长方便地扩展以支撑更多用户和交易量。
2)OLAP 是数据的"分析平台",主攻"分析决策",核心是多维分析,主要用"关系数据库",更新频率低,主要是历史数据的快照,定期 从OLTP系统抽取数据进行更新,分析时数据相对静态。处理的数据量通常很大。 **对响应时间容忍度较高。**一个复杂分析查询运行几分钟甚至更长时间,只要能得出有价值的分析结果用于决策,通常是可以接受的。它定期从OLTP系统获取数据,经过清洗、转换、整合(这个过程叫ETL)后,存储到专门为分析优化的结构(如数据仓库)中,用于分析决策。
- OLAP系统: 最看重复杂查询的执行效率 和存储容量与扩展性。架构设计要考虑数据量的持续增长。
没有OLTP持续产生准确的数据,OLAP就没有分析的基础;没有OLAP的深度分析,OLTP产生的数据价值就难以充分释放。
今天就到这里吧,ok 
项目管理--相关知识 
项目管理-项目绩效域1/2_八大绩效域和十大管理有什么联系-CSDN博客
项目管理-计算题公式【复习】_项目管理进度计算题公式:乐观-CSDN博客
项目管理-相关知识(组织通用治理、组织通用管理、法律法规与标准规范)-CSDN博客
Oracle其他文档,希望互相学习,
共同进步
Oracle-找回误删的表数据(LogMiner 挖掘日志)_oracle日志挖掘恢复数据-CSDN博客
oracle 跟踪文件--审计日志_oracle审计日志-CSDN博客
ORA-12899报错,遇到数据表某字段长度奇怪现象:"Oracle字符型,长度50"但length查却没有50_varchar(50) oracle 超出截断-CSDN博客
