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

删除,分区,如何,不让,全局,索引,失效 · 浏览次数 : 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个分区,每个

[转帖]三种缓存策略分析:Cache aside,Read/Write through,Write Back

Cache aside 旁路缓存,旁路缓存操作逻辑是查询缓存,如果不存在那么就读取数据库并更新到缓存当中. 如果是更新数据库,那么操作完数据库后,删除缓存. 注意旁路缓存,缓存中的内容是不做更新操作的,只有写入和删除操作. 问题 1.请求1查询不到缓存,查询数据库.请求2更新数据,删除缓存,请求1写

[转帖]redis bigkey 删除问题

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

[转帖]RabbitMQ高可用性

RabbitMQ消息应答 执行一个任务可能需要花费几秒钟,你可能会担心如果一个消费者在执行任务过程中挂掉了。一旦RabbitMQ将消息分发给了消费者,就会从内存中删除。在这种情况下,如果正在执行任务的消费者宕机,会丢失正在处理的消息和分发给这个消费者但尚未处理的消息。 但是,我们不想丢失任何任务,如

[转帖]5分钟学会这种更高效的Redis数据删除方式

https://ost.51cto.com/posts/12513 简述 我们知道,Del命令能删除数据,除此之外,数据在Redis中,还会以哪种方式被删除呢?在Redis内存满一定会返回OOM错误?Key到达过期时间就立即删除?删除大Key会影响性能吗?下面,咱们一起探讨。 同步和异步删除 1.D

[转帖]Redis 的数据被删除,内存占用还这么大?

作者 | 码哥 来源 | 码哥字节 操作系统分配给 Redis 的内存有 6GB,通过指标 used_memory_human 发现存储数据只使用了 4GB,为何会这样?为何无法保存数据? 通过 CONFIG SET maxmemory 100mb或者在 redis.conf 配置文件设置 maxm

[转帖]SQL语言的分类总结

https://zhuanlan.zhihu.com/p/555596861 常用的SQL命令 数据定义语言DDL(Data Definition Language) create 、drop 、alter 主要为创建、修改、删除数据库的逻辑结构,其中包括表结构,视图和索引等。 create 创建数

[转帖]Shell编程之正则表达式与文本处理器(grep、sort、uniq、tr、cut)

目录 正则表达式概念正则表达式的作用元字符grep命令在文本中查找指定的字符串sort命令排序uniq命令快捷去重tr命令替换、压缩和删除cut命令快速裁剪命令expr substr 截取方法cut截取方法 split命令文件拆分paste命令文件合并eval变量扫描器位置锚定分组或其他扩展正则表达

[转帖]删除软链接

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