SQL> create table xue.test_pp(id number,name varchar2(10)) partition by range (id) (partition pa values less than (10),partition pb values less than (20),partition pc values less than (30)); Table created. SQL> insert into xue.test_pp values (1,’a'); 1 row created. SQL> insert into xue.test_pp values (11,’aa’); 1 row created. SQL> insert into xue.test_pp values (22,’bb’); 1 row created. SQL> commit; Commit complete. SQL> select * from xue.test_pp; ID NAME ———- ———- 1 a 11 aa 22 bb SQL> alter table xue.test_pp add constraint u_pp unique (id); Table altered. SQL> select index_name,status,partitioned from dba_indexes where table_name=’TEST_PP’; U_PP VALID NO 普通DML不会导致索引失效: SQL> insert into xue.test_pp values (23,’cc’); 1 row created. SQL> commit; Commit complete. SQL> select index_name,status,partitioned from dba_indexes where table_name=’TEST_PP’; U_PP VALID NO SQL> update xue.test_pp set name=’bc’ where id=23; 1 row updated. SQL> commit; Commit complete. SQL> select index_name,status,partitioned from dba_indexes where table_name=’TEST_PP’; U_PP VALID NO SQL> delete from xue.test_pp where id=23; 1 row deleted. SQL> commit; Commit complete. SQL> select index_name,status,partitioned from dba_indexes where table_name=’TEST_PP’; U_PP VALID NO tuncate 一个分区则导致索引无效: SQL> select * from xue.test_pp; 1 a 11 aa 22 bb SQL> alter table xue.test_pp truncate partition pc; Table truncated. SQL> select * from xue.test_pp; 1 a 11 aa SQL> select index_name,status,partitioned from dba_indexes where table_name=’TEST_PP’; U_PP UNUSABLE NO 在这种情况下做INSERT/DELETE操作会报错: SQL> insert into xue.test_pp values(23,’dd’); insert into xue.test_pp values(23,’dd’) * ERROR at line 1: ORA-01502: index ‘XUE.U_PP’ or partition of such index is in unusable state 即使是插入到没有TRUNCATE的分区也报错: SQL> insert into xue.test_pp values(12,’dd’); insert into xue.test_pp values(12,’dd’) * ERROR at line 1: ORA-01502: index ‘XUE.U_PP’ or partition of such index is in unusable state –DELETE报错: SQL> delete from xue.test_pp where id=11; delete from xue.test_pp where id=11 * ERROR at line 1: ORA-01502: index ‘XUE.U_PP’ or partition of such index is in unusable state 不过做UPDATE不会报错: SQL> update xue.test_pp set name=’bc’ where id=11; 1 row updated. 创建一个local索引: SQL> create unique index xue.UUU on xue.test_pp(id) local; create unique index xue.UUU on xue.test_pp(id) local * ERROR at line 1: ORA-01408: such column list already indexed SQL> create unique index xue.UUU on xue.test_pp(id,name) local; Index created. SQL> select index_name,status,partitioned from dba_indexes where table_name=’TEST_PP’; UUU N/A YES U_PP UNUSABLE NO SQL> select index_name,status from dba_ind_partitions where INDEX_name=’UUU’; UUU USABLE UUU USABLE UUU USABLE 在全局索引、本地索引共存的情况下仍然报错: SQL> delete from xue.test_pp where id=11; delete from xue.test_pp where id=11 * ERROR at line 1: ORA-01502: index ‘XUE.U_PP’ or partition of such index is in unusable state 删除原来的索引后就不再报错: SQL> alter table xue.test_pp disable constraint u_pp; Table altered. SQL> delete from xue.test_pp where id=11; 1 row deleted. 在这种情况下,观察语句的执行计划: update xue.test_pp set name=’cce’ where id=13; select * from v$sqlarea where sql_text like ‘%test_pp%’ select * from table(dbms_xplan.display_cursor(‘12jr4j8vzx5pw’)); SQL_ID 12jr4j8vzx5pw, child number 0 ————————————- update xue.test_pp set name=’cce’ where id=13 Plan hash value: 935868745 ————————————————————————————————— | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | Pstart| Pstop | ————————————————————————————————— | 0 | UPDATE STATEMENT | | | | 1 (100)| | | | | 1 | UPDATE | TEST_PP | | | | | | | | 2 | PARTITION RANGE SINGLE| | 1 | 20 | 1 (0)| 00:00:01 | 2 | 2 | |* 3 | INDEX RANGE SCAN | UUU | 1 | 20 | 1 (0)| 00:00:01 | 2 | 2 | ————————————————————————————————— Predicate Information (identified by operation id): ————————————————— 3 – access("ID"=13) Note —– – dynamic sampling used for this statement 该操作使用了新索引:UUU,同时使用了INDEX RANGE SCAN 创建原来的索引: SQL> alter table xue.test_pp enable constraint u_pp; Table altered. SQL> select index_name from dba_indexes where table_name=’TEST_PP’; UUU U_PP 这种情况下该语句的执行计划变为: SQL_ID 7crj9fgwu7kfw, child number 0 ————————————- update xue.test_pp set name=’eeee’ where id=13 Plan hash value: 2992425951 ——————————————————————- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| ——————————————————————- | 0 | UPDATE STATEMENT | | | | 1 (100)| | 1 | UPDATE | TEST_PP | | | | |* 2 | INDEX UNIQUE SCAN| U_PP | 1 | 20 | 0 (0)| ——————————————————————- Predicate Information (identified by operation id): ————————————————— 2 – access("ID"=13) 可以看到,使用U_PP索引时是INDEX UNIQUE SCAN。 修改测试语句的where条件: update xue.test_pp set name=’ffff’ where id=13 and name=’eeee’; SQL_ID 8r665dj5174n0, child number 0 ————————————- update xue.test_pp set name=’ffff’ where id=13 and name=’eeee’ Plan hash value: 1843624919 —————————————————————————————- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Pstart| Pstop | —————————————————————————————- | 0 | UPDATE STATEMENT | | | | 1 (100)| | | | 1 | UPDATE | TEST_PP | | | | | | | 2 | PARTITION RANGE SINGLE| | 1 | 20 | 0 (0)| 2 | 2 | |* 3 | INDEX UNIQUE SCAN | UUU | 1 | 20 | 0 (0)| 2 | 2 | —————————————————————————————- Predicate Information (identified by operation id): ————————————————— 3 – access("ID"=13 AND "NAME"=’eeee’) –删掉索引 SQL> drop index XUE.UUU 2 ; Index dropped. update xue.test_pp set name=’aaaaaa’ where id=13 and name=’ffff’; Execution Plan ———————————————————- Plan hash value: 714092732 —————————————————————————————————- ———– | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | Psta rt| Pstop | —————————————————————————————————- ———– | 0 | UPDATE STATEMENT | | 1 | 6 | 1 (0)| 00:00:01 | | | | 1 | UPDATE | TEST_PP | | | | | | | |* 2 | TABLE ACCESS BY GLOBAL INDEX ROWID| TEST_PP | 1 | 6 | 1 (0)| 00:00:01 | 2 | 2 | |* 3 | INDEX UNIQUE SCAN | U_PP | 1 | | 0 (0)| 00:00:01 | | | —————————————————————————————————- ———– Predicate Information (identified by operation id): ————————————————— 2 – filter("NAME"=’ffff’) 3 – access("ID"=13) –使用了索引U_PP,不过仍然是INDEX UNIQUE SCAN 测试结论 1、truncate 操作会导致全局索引失效 2、如果全局索引失效,即使有其他索引可用,该表也不能进行INSERT\DELETE,可以UPDATE。 3、假设有索引1(索引列为id1),索引2(索引列为id1,id2),且都是unique索引,则: –只有索引2的情况下: 以id1为where条件的语句会使用索引2,但是其索引模式为:INDEX RANGE SCAN; 以id1,id2为where条件的语句会使用索引2,并且其索引模式为:INDEX UNIQUE SCAN ; –只有索引1的情况下: 以id1为where条件,或以id1,id2为条件,都会使用索引1,并且其索引模式为:INDEX UNIQUE SCAN ; –2个索引都存在的情况下: 以id1为where条件的语句会使用索引1,并且其索引模式为:INDEX UNIQUE SCAN ; 以id1,id2为where条件的语句会使用索引2,并且其索引模式为:INDEX UNIQUE SCAN ;
全局索引失效带来的几个测试场景
来源:这里教程网
时间:2026-03-03 19:00:23
作者:
编辑推荐:
相关推荐
-
雷神推出 MIX PRO II 迷你主机:基于 Ultra 200H,玻璃上盖 + ARGB 灯效
2 月 9 日消息,雷神 (THUNDEROBOT) 现已宣布推出基于英
-
制造商 Musnap 推出彩色墨水屏电纸书 Ocean C:支持手写笔、第三方安卓应用
2 月 10 日消息,制造商 Musnap 现已在海外推出一款 Oce
热文推荐
- 修改主机时区对Oracle的影响分析
修改主机时区对Oracle的影响分析
26-03-03 - Oracle 标准审计功能及开启
Oracle 标准审计功能及开启
26-03-03 - 研究Oracle 延迟块清除(defered block cleanout)
- ORACLE下一次奇怪的job停止问题分析及处理
ORACLE下一次奇怪的job停止问题分析及处理
26-03-03 - Oracle标准审计,关闭AUDIT
Oracle标准审计,关闭AUDIT
26-03-03 - Oracle 在查询的where子句中,索引的索引列/前导列是否作为单个表谓词提供列进行匹配
- Oracle 标准审计,设置AUDIT_SYSLOG _LEVEL参数
Oracle 标准审计,设置AUDIT_SYSLOG _LEVEL参数
26-03-03 - 一次异常宕机后数据库启动报ora-600[4000]错误恢复
一次异常宕机后数据库启动报ora-600[4000]错误恢复
26-03-03 - 数据库数据恢复-Oracle数据库truncate table如何恢复数据?
- 创作新纪元:知乎、阅文加码AI大模型,撬动创作者经济
创作新纪元:知乎、阅文加码AI大模型,撬动创作者经济
26-03-03
