Oracle 19c 本地索引分区变为 UNUSABLE 后的空间占用验证

适用范围

适用于Oracle 19c

场景概述

通过测试说明Oracle 19c中分区表的不可用索引和索引分区是否占用空间。

实施步骤

1、登录到PDB hrpdb中

使用业务用户hr用户连接

sql 复制代码
[oracle@19cdb01 ~]$ sqlplus hr/<password>@hrpdb

SQL*Plus: Release 19.0.0.0.0 - Production on Thu Aug 13 04:16:28 2026
Version 19.27.0.0.0

Copyright (c) 1982, 2024, Oracle.  All rights reserved.
--检查容器名称
HR@hrpdb(HRPDB)> show con_name

CON_NAME
------------------------------
HRPDB
--确认用户
HR@hrpdb(HRPDB)> show user
USER is "HR"
HR@hrpdb(HRPDB)>

2、创建一个range分区表

sql 复制代码
HR@hrpdb(HRPDB)> create table sales1
(sales_amt number
,d_date_id number)
partition by range (d_date_id)(
partition p_2022 values less than (20220101) tablespace XFTBS,
partition p_2023 values less than (20230101) tablespace XFTBS,
partition p_max  values less than (maxvalue) tablespace XFTBS);  2    3    4    5    6    7

Table created

创建range分区表sales1

3、给分区表创建索引

sql 复制代码
HR@hrpdb(HRPDB)> create index inx_sales_fk1 on sales1(d_date_id) tablespace INX_XFTBS local;

Index created.

HR@hrpdb(HRPDB)> create index inx_sales_amt on sales1(sales_amt) tablespace INX_XFTBS  local;

Index created.

HR@hrpdb(HRPDB)>

给分区表创建两个本地索引 inx_sales_fk1 和inx_sales_amt 。

4、为分区表插入测试数据

sql 复制代码
HR@hrpdb(HRPDB)> INSERT INTO sales1(sales_amt, d_date_id) VALUES (50, 2022);

1 row created.

HR@hrpdb(HRPDB)> INSERT INTO sales1(sales_amt, d_date_id) VALUES (100, 2023);

1 row created.

HR@hrpdb(HRPDB)> commit;

Commit complete.

HR@hrpdb(HRPDB)> select count(*) from sales1;

  COUNT(*)
----------
         2

5、查看分区表信息

sql 复制代码
HR@hrpdb(HRPDB)> col table_name for a15
HR@hrpdb(HRPDB)> col partitioning_type for a10
HR@hrpdb(HRPDB)> col def_tablespace_name for a15
HR@hrpdb(HRPDB)> select table_name, partitioning_type, def_tablespace_name
from user_part_tables
where table_name='SALES1';  2    3

TABLE_NAME      PARTITIONI DEF_TABLESPACE_
--------------- ---------- ---------------
SALES1          RANGE      XFTBS

HR@hrpdb(HRPDB)>

6、查表中分区的信息

sql 复制代码
HR@hrpdb(HRPDB)> col table_name for a15
HR@hrpdb(HRPDB)> col partition_name for a15
HR@hrpdb(HRPDB)> col high_value for 9999
HR@hrpdb(HRPDB)> set long 9999999
HR@hrpdb(HRPDB)> select table_name, partition_name, high_value
from user_tab_partitions
where table_name = 'SALES1'
order by table_name, partition_name;  2    3    4

TABLE_NAME      PARTITION_NAME  HIGH_VALUE
--------------- --------------- --------------------
SALES1          P_2022          20220101
SALES1          P_2023          20230101
SALES1          P_MAX           MAXVALUE

HR@hrpdb(HRPDB)>


HR@hrpdb(HRPDB)> select rpad(segment_name,10),partition_name, blocks, bytes from user_segments
 where segment_type='INDEX PARTITION';  2

RPAD(SEGMENT_NAME,10)                    PARTITION_NAME      BLOCKS      BYTES
---------------------------------------- --------------- ---------- ----------
INX_SALES_                               P_2022                   8      65536
INX_SALES_                               P_2022                   8      65536

HR@hrpdb(HRPDB)>

SYS@hrpdb(HRPDB)> select rpad(segment_name,10),partition_name, blocks, bytes from dba_segments
 where segment_type='INDEX PARTITION' and owner='HR' order by 1,2;  2

RPAD(SEGMENT_NAME,10)                    PARTITION_NAME      BLOCKS      BYTES
---------------------------------------- --------------- ---------- ----------
INX_SALES_                               P_2022                   8      65536
INX_SALES_                               P_2022                   8      65536

SYS@hrpdb(HRPDB)>
HR@hrpdb(HRPDB)> select index_name,partition_name,status from user_ind_partitions
where partition_name='P_2022'  order by 1,2;  2

INDEX_NAME           PARTITION_NAME  STATUS
-------------------- --------------- --------
INX_SALES_AMT        P_2022          USABLE
INX_SALES_FK1        P_2022          USABLE

HR@hrpdb(HRPDB)>

SYS@hrpdb(HRPDB)> select index_name,partition_name,status from dba_ind_partitions
   where index_owner='HR' and partition_name='P_2022'  order by 1,2;  2

INDEX_NAME           PARTITION_NAME  STATUS
-------------------- --------------- --------
INX_SALES_AMT        P_2022          USABLE
INX_SALES_FK1        P_2022          USABLE

SYS@hrpdb(HRPDB)>

7、对分区表SALES1中的P_2022分区进行MOVE

sql 复制代码
HR@hrpdb(HRPDB)> alter table SALES1 move partition P_2022;

Table altered.

检查数据库日志

2026-06-19T05:06:29.934561+08:00
HRPDB(3):Some indexes or index [sub]partitions of table HR.SALES1 have been marked unusable

MOVE执行后分区内数据的物理存储位置(ROWID)发生了改变。Oracle 出于数据一致性考虑,会自动将依赖于这些 ROWID 的本地索引(Local Index)分区标记为 UNUSABLE。

8、再次检查表中分区信息

sql 复制代码
HR@hrpdb(HRPDB)> select rpad(segment_name,10),partition_name, blocks, bytes from user_segments
 where segment_type='INDEX PARTITION';  2

no rows selected

HR@hrpdb(HRPDB)>

SYS@hrpdb(HRPDB)> select rpad(segment_name,10),partition_name, blocks, bytes from dba_segments
 where segment_type='INDEX PARTITION' and owner='HR' order by 1,2;  2

no rows selected

SYS@hrpdb(HRPDB)> select index_name,partition_name,status from dba_ind_partitions
   where index_owner='HR' and partition_name='P_2022'  order by 1,2;  2

INDEX_NAME           PARTITION_NAME  STATUS
-------------------- --------------- --------
INX_SALES_AMT        P_2022          UNUSABLE
INX_SALES_FK1        P_2022          UNUSABLE

SYS@hrpdb(HRPDB)>


HR@hrpdb(HRPDB)> select index_name,partition_name,status from user_ind_partitions
where partition_name='P_2022'  order by 1,2;  2

INDEX_NAME           PARTITION_NAME  STATUS
-------------------- --------------- --------
INX_SALES_AMT        P_2022          UNUSABLE
INX_SALES_FK1        P_2022          UNUSABLE

HR@hrpdb(HRPDB)>

9、恢复索引状态

在日常运维中,如果需要让这些索引重新生效并重新分配空间,必须对其进行重建(Rebuild)

sql 复制代码
HR@hrpdb(HRPDB)> ALTER INDEX INX_SALES_AMT REBUILD PARTITION P_2022;

Index altered.

HR@hrpdb(HRPDB)> ALTER INDEX INX_SALES_FK1 REBUILD PARTITION P_2022;

Index altered.

再次查询分区表中分区segment信息,查询结果与 第6步中一致,索引状态是USABLE,segment也分配了值。

10、MOVE分区表时保持索引USABLE状态

sql 复制代码
--move分区表时使用UPDATE INDEXES
HR@hrpdb(HRPDB)> HR@hrpdb(HRPDB)> ALTER TABLE sales1 MOVE PARTITION  p_2022 tablespace XFTBS UPDATE INDEXES;

Table altered.


Table altered.

HR@hrpdb(HRPDB)> select rpad(segment_name,10),partition_name, blocks, bytes from user_segments
 where segment_type='INDEX PARTITION';  2

RPAD(SEGMENT_NAME,10)                    PARTITION_NAME      BLOCKS      BYTES
---------------------------------------- --------------- ---------- ----------
INX_SALES_                               P_2022                   8      65536
INX_SALES_                               P_2022                   8      65536

HR@hrpdb(HRPDB)> select index_name,partition_name,status from user_ind_partitions
where partition_name='P_2022'  order by 1,2;  2

INDEX_NAME           PARTITION_NAME  STATUS
-------------------- --------------- --------
INX_SALES_AMT        P_2022          USABLE
INX_SALES_FK1        P_2022          USABLE

--从12c开始当移动分区时,可以通过 ONLINE 子句指定更新所有索引
HR@hrpdb(HRPDB)>  ALTER TABLE sales1 MOVE PARTITION p_2022 ONLINE TABLESPACE XFTBS;

Table altered.

【总结】19c中分区表的不可用索引和索引分区不占用空间。对分区表MOVE后将分区表中索引状态标记为 不可用用UNUSABLE 的同时,Oracle 会直接释放这些索引分区原本占用的段(Segment)空间。

-the end-

相关推荐
杨云龙UP1 小时前
Oracle ASH 报告详解:与 AWR 的区别、使用场景及生成方法
linux·运维·服务器·数据库·oracle
LCG元2 小时前
ESP32-IDF 远程固件升级实战:HTTPS OTA + 双分区切换 + 自动回滚
数据库·redis·https
️学习的小王2 小时前
MySQL常用函数知识点总结
数据库·mysql·oracle
看浪的路人2 小时前
第6讲:SQL 解析器
java·开发语言·数据库
吴老弟i2 小时前
Mac 本地安装 MySQL 学习指南
数据库
悦数图数据库2 小时前
千亿点边图谱建设,原生分布式图数据库如何避免单点瓶颈
数据库·分布式
XLYcmy3 小时前
pdf论文处理:CSV输出模式
数据库·python·pycharm·pdf·论文·csv·dify
MC皮蛋侠客3 小时前
Redis 系列(十一):高可用(二)——Redis Cluster 集群
数据库·redis·bootstrap
zhanghaha13143 小时前
Python进阶教程:5_XML 解析 —— 新手完全指南
java·前端·数据库