[转帖]删除分区如何不让全局索引失效?

删除,分区,如何,不让,全局,索引,失效 · 浏览次数 : 0

小编点评

**删除分区,会导致全局索引失效,但如何避免?** 当我们删除表中数据的时候,同时要删除他对应的索引,由于索引是有序排列的,如果要删除一条索引数据,他的组织结构,就需要调整,以保证正确的排列顺序。 1. **重建索引,让其生效** - SQL> alter index idx_01 rebuild online; 2. **再次执行分区删除的操作** - SQL> alter table interval_sale drop partition; 3. **再看全局索引,他的状态正常,VALID,并未因为分区删除的操作,导致其失效** - SQL> select table_name, index_name, status  2  from user_indexes where table_name='INTERVAL_SALE';TABLE_NAME     INDEX_NAME   STATUS--------------- --------------- --------INTERVAL_SALE    IDX_01       VALID 4. **通过以上实验,可以得到结论,如果待删除的分区中没有任何数据,执行分区删除,不会导致全局索引状态的失效**

正文

记得上次ACOUG年会(《ACOUG年会感想》),请教杨长老问题的时候,谈到分区,如果执行分区删除的操作,就会导致全局索引失效,除了使用12c以上版本能避免这个问题外,指出另外一种解决的方式,表面看很巧妙,实则是对分区原理的深入理解。

我们先从实验,了解这个问题,首先创建分区表,他存在4个分区,每个分区中,都存在数据,

  1. SQL> CREATE TABLE interval_sale
  2.   2  ( prod_id        NUMBER(6)
  3.   3  , cust_id        NUMBER
  4.   4  , time_id        DATE
  5.   5  )
  6.   6  PARTITION BY RANGE (time_id)
  7.   7  INTERVAL(NUMTOYMINTERVAL(1'YEAR'))
  8.   8    ( PARTITION p0 VALUES LESS THAN (TO_DATE('1-1-2003''DD-MM-YYYY')),
  9.   9      PARTITION p1 VALUES LESS THAN (TO_DATE('1-1-2004''DD-MM-YYYY')),
  10.  10      PARTITION p2 VALUES LESS THAN (TO_DATE('1-1-2005''DD-MM-YYYY')),
  11.  11      PARTITION p3 VALUES LESS THAN (TO_DATE('1-1-2006''DD-MM-YYYY')));
  12. SQL> insert into interval_sale values(11, to_date('2002-01-01','yyyy-mm-dd'));
  13. 1 row created.
  14. SQL> insert into interval_sale values(22, to_date('2003-01-01','yyyy-mm-dd'));
  15. 1 row created.
  16. SQL> insert into interval_sale values(33, to_date('2004-01-01','yyyy-mm-dd'));
  17. 1 row created.
  18. SQL> insert into interval_sale values(44, to_date('2005-01-01','yyyy-mm-dd'));
  19. 1 row created.
  20. SQL> commit;
  21. Commit complete.

创建全局索引,当前状态是VALID,

  1. SQL> create index idx_01 on interval_sale(cust_id);
  2. Index created.
  3. SQL> select table_name, index_name, partitioned, status
  4.   2  from user_indexes where table_name='INTERVAL_SALE';
  5. TABLE_NAME     INDEX_NAME   PARTITIONED STATUS
  6. --------------- --------------- ------------ --------
  7. INTERVAL_SALE    IDX_01       NO VALID
  8. 删除第一个分区,
  1. SQL> alter table interval_sale drop partition for (to_date('2002-01-01','yyyy-mm-dd'));
  2. Table altered.

此时,看到这个全局索引是UNUSABLE的状态,和我们的设想是相同的,即删除分区,会导致全局索引的失效,

  1. SQL> select table_name, index_name, status
  2.   2  from user_indexes where table_name='INTERVAL_SALE';
  3. TABLE_NAME     INDEX_NAME   STATUS
  4. --------------- --------------- ----------
  5. INTERVAL_SALE    IDX_01       UNUSABLE

结论告诉我们,删除分区,确实会导致全局索引的失效,我们从问题入手,为什么分区删除,会导致全局索引的失效?

我们知道,Oracle中索引是以B树的结构存储的,包括了索引键值、rowid信息,而且按照索引键值有序排列,当通过索引扫描需要回表的时候,能利用rowid直接定位到索引键值对应的数据块,这是最快的数据访问方式。当我们删除表中数据的时候,同时要删除他对应的索引,由于索引是有序排列的,如果要删除一条索引数据,他的组织结构,就需要调整,以保证正确的排列顺序,12c之前,因为某种原因,无法在删除分区的同时,对索引重新构建,所以此时索引的状态是失效的,与其是错的,宁可不让用,删除分区,需要手工rebuild重建索引才能让其生效,

我们换种思路,之所以全局索引的状态失效,根本问题就是索引对应的分区中数据被删除了,那么,如果不删除分区中的数据,索引结构无需任何调整,他的状态是不是就是正常的?

首先重建索引,让其生效,

  1. SQL> alter index idx_01 rebuild online;
  2. Index altered.
  3. SQL> select table_name, index_name, status
  4.   2  from user_indexes where table_name='INTERVAL_SALE';
  5. TABLE_NAME     INDEX_NAME   STATUS
  6. --------------- --------------- --------
  7. INTERVAL_SALE    IDX_01       VALID

此时,通过delete删除即将删除的第二个分区的数据,

  1. SQL> delete from interval_sale where time_id <= to_date('2003-01-01','yyyy-mm-dd');
  2. 1 row deleted.
  3. SQL> commit;
  4. Commit complete.

再次执行分区删除的操作,

  1. SQL> alter table interval_sale drop partition for (to_date('2003-01-01','yyyy-mm-dd'));
  2. Table altered.

此时,再看全局索引,他的状态正常,VALID,并未因为分区删除的操作,导致其失效,

  1. SQL> select table_name, index_name, status
  2.   2  from user_indexes where table_name='INTERVAL_SALE';
  3. TABLE_NAME     INDEX_NAME   STATUS
  4. --------------- --------------- --------
  5. INTERVAL_SALE    IDX_01       VALID

通过以上实验,可以得到结论,如果待删除的分区中没有任何数据,执行分区删除,不会导致全局索引状态的失效。原因已经说了,因为分区删除时,不存在任何数据需要删除,意味着无需调整索引结构,所以全局索引的状态,就无需置为失效,这个算是对待分区删除避免全局索引失效的一种另类解决方案了。

通过这个问题,能让我体会到的,就是一个看着很简单的问题背后,其实蕴涵着丰富的知识,同时对待任何一个知识点,从原理层理解地越深入,找到问题的本质,就可以让你和真相更近,豁然开朗,这可能就需要日常的积累,碰到问题的时候,多问一句为什么,就可能让你大开眼界,这就是Oracle以及技术领域最吸引人的地方了。

</article>

与[转帖]删除分区如何不让全局索引失效?相似的内容:

[转帖]删除分区如何不让全局索引失效?

记得上次ACOUG年会(《ACOUG年会感想》),请教杨长老问题的时候,谈到分区,如果执行分区删除的操作,就会导致全局索引失效,除了使用12c以上版本能避免这个问题外,指出另外一种解决的方式,表面看很巧妙,实则是对分区原理的深入理解。 我们先从实验,了解这个问题,首先创建分区表,他存在4个分区,每个

[转帖]删除软链接

1,建立软链接 ln -s 源文件 目标文件 例如:ln -s /usr/hb/ /home/hb_link 2,删除软链接 正确的是:rm -rf hb_link 错误的是:rm -rf hb_link/ 这个会把整个目录都删了 备注:想要删除链接文件要用以下命令 rm /home/hb_link

[转帖]删除数据后的Redis内存占用率为什么还是很高?

https://zhuanlan.zhihu.com/p/490569316 有时候Redis明明做了数据删除,数据量已经不大了,但是使用top命令的时候,还会发现Redis占用了很多内存? PS:关于 Redis的高并发及高可用,到底该如何保证?可以参考下这个帖子:httss://http://z

[转帖]shell删除文件前几行或后几行

https://www.cnblogs.com/1394htw/p/14852207.html shell删除文件前几行或后几行 #!/bin/bash #删除前两行 sed -i '1,2d' filename #删除后两行 sed -i '$d' filename sed -i '$d' fil

[转帖]linux删除文本文件空白行

https://zhuanlan.zhihu.com/p/627152095 sed命令 在Linux中,可以使用sed命令批量删除文本中的空白行。以下是一个示例命令: sed -i '/^$/d' filename.txt 这个命令将会删除 filename.txt 文件中所有的空白行,并且直接在

[转帖]linux删除文本文件空白行

linux删除文本文件空白行https://www.zhihu.com/people/chen-kai-84-54-75 sed命令 在Linux中,可以使用sed命令批量删除文本中的空白行。以下是一个示例命令: sed -i '/^$/d' filename.txt 这个命令将会删除 filena

[转帖]redis惰性删除 lazy free 源码剖析,干货满满

目录 前言 数据删除场景 lazy free 概念 配置 源码剖析(版本 6.2.6) 场景一:客户端执行的显示删除/清除命令 场景二:某些指令带有的隐式删除命令 场景三:删除过期数据 场景四:内存淘汰数据删除 场景五:主从同步清空从库 小结 前言 都说 redis 是单线程的,其实并不是说 red

[转帖]redis bigkey 删除问题

一、慢操作分析 redis 的慢操作已经有了,如果没有,我们可以自己去 redis 服务器查看历史的慢日志操作,或者有对应的慢操作监控系统也可以发现问题,这里不做展开。 接下来我们就要看一看为什么这么慢。 看了下项目中的实现代码,结合日志一分析,发现是一个 redis bigkey。 一个 redi

[转帖]oracle如何删除datafile,误删除Oracle datafile 无法打开数据库

1、在Oracle open方式下,直接从OS上删除了datafile文件。 rm /u02/rmants.dbf 2、数据库关闭后,无法打开数据库,只能到mount状态。 SQL> alter database open; alter database open * ERROR at line 1

[转帖]玩转REDIS-删除了两百万KEY,为什么内存依旧未释放?

https://www.freesion.com/article/87101375552/ 《玩转Redis》系列文章主要讲述Redis的基础及中高级应用。本文是《玩转Redis》系列第【12】篇,最新系列文章请前往公众号“zxiaofan”(点我点我)查看,或百度搜索“玩转Redis zxiaof