暂无图片
oracle普通表转分区表之后的唯一索引创建问题
我来答
分享
神武天尊
2022-03-07
oracle普通表转分区表之后的唯一索引创建问题
暂无图片 10M

oracle普通表转分区表之后的唯一索引创建问题

问题描述:

普通表cz_orderlist中有ORDERID, SPID,SUBTIME等字段,其中ORDERID, SPID构成组合式唯一索引 转为新分区表,使用SUBTIME按月分区。在对新分区表创建唯一索引时遇到问题: SQL> create unique index uk_cz_orderlist on CZ_ORDERLIST(ORDERID, SPID) local; create unique index uk_cz_orderlist on CZ_ORDERLIST(ORDERID, SPID) local * ERROR at line 1: ORA-14039: partitioning columns must form a subset of key columns of a UNIQUE index 意思是如果创建本地唯一索引,则必须把分区列包含进去。 如果我按以下方式,能够正常创建: create unique index uk_cz_orderlist on CZ_ORDERLIST(ORDERID, SPID, SUBTIME) local;
复制

有人会问,你为什么要创建本地索引,而不是全局索引呢?

因为我之所以把这张表转为分区表,就是需要定期删除历史数据,减少数据量以提高sql处理速度。这张表数据量非常大,且每分钟都有大量的相关DML操作。

而如果我使用全局索引,则在对历史分区进行truncate或drop时出现全局索引直接失效的问题。一旦此索引失效,则会对大多数条件中使用此索引的查询造成重大影响,大量锁等待,业务无法进行。

如果我按照上面的方法,把分区键SUBTIME加进去创建的唯一索引,这又不符合业务逻辑了!

为什么呢?因为之所以原表中有这个唯一索引,就是为了防止数据重复写入,但加了SUBTIME后已经不能实现这个功能了。原因是SUBTIME是按数据写入数据库时的sysdate获取的值,此时如果前后有两条相同的数据要写入到分区表的同一个分区之中,虽然ORDERID+SPID重复了(代表重复数据),但由于sysdate不一样,系统并不会报冲突,导致数据写入成功。这就与原来的应用逻辑有偏差,导致最终数据不一致。

说了这么多,我想问问大家,有什么办法解决这个问题吗?

(注:关于在truncate或drop时加rebuild online参数在线重建索引这种方案,实测不可行。因为数据量太大,重建索引也要耗费很长时间,同样会导致大量锁等待,业务无法进行)

我来答
添加附件
收藏
分享
问题补充
4条回答
默认
最新
cqiwen

在12C之前的版本,对分区表进行删除分区或者TRUNCATE分区,合并或者分裂分区,MOVE分区等DDL操作时,分区表上的全局索引会失效,通常要加上UPDATE GLOBAL INDEXES或者ONLINE关键字,可是加上这些关键字之后,本来很快的DDL操作可能就要花费很长的时间,而且还要面临锁的问题。

Oracle 12C推出了分区表全局索引异步维护特性,这个特性有效的解决了这个问题,在对分区表进行上述DDL操作时,既能快速完成操作,也能保证全局索引有效,然后通过调度JOB在固定的时候对全局索引进行维护。

其实在这个新特性实现之前,我们对分区表进行DDL操作,通常也是会选择一个业务相对比较空闲的时间来做,通常是后半夜加班来弄,有了这个新特性,就可以在白天选择一个业务相对空闲的时间来做,然后在夜间业务比较空闲的时候,让ORACLE通过JOB统一来维护全局索引。


结论:12C以前的版本选择在夜间业务比较空闲的时候进行分区的drop或truncate操作,或者将数据库升级为12C,其新特性解决了这个问题。

暂无图片 评论
暂无图片 有用 0
打赏 0
暂无图片
Lucifer三思而后行
暂无图片

而如果我使用全局索引,则在对历史分区进行truncate或drop时出现全局索引直接失效的问题。一旦此索引失效,则会对大多数条件中使用此索引的查询造成重大影响,大量锁等待,业务无法进行。


关于上面的这个问题不可避免,唯一索引只能创建为全局索引,不过可以在操作时加上 update index 来避免问题,就是速度比较慢。

暂无图片 评论
暂无图片 有用 0
打赏 0
神武天尊
题主
2022-03-09
表很大,用在线重建索引的方式也解决不了这个问题。大佬还有其它解决方案没?
吾喾

尝试在字段ORDERID和SPID上面选其一改为二级hash分区,这样创建唯一索引就不会报错了,但是不能保证全局唯一

暂无图片 评论
暂无图片 有用 0
打赏 0
神武天尊
题主
2022-03-09
这种方法不行。还是会报错,提示必须包含主要的分区键,而不是二级分区键。
吾喾
答主
2022-03-09
俩字段创建一个主键就能保证唯一了 alter table CZ_ORDERLIST add constraint PK_CZ_ORDERLIST primary key (ORDERID, SPID) using INDEX;
ycc

这个的确是个难解,但又有业务场景的问题,个人认为完全依赖分区还是解决不了,两种思路:

1、数据库层用分区,解决清理问题,但唯一索引不建,推到应用层去保障与解决; 

2、利用分区的方式来分表,同时满足清理与唯一,但这个应用架构也得调,可能还很复杂; ^_^

暂无图片 评论
暂无图片 有用 0
打赏 0
神武天尊
题主
2022-03-09
目前我们这边有用第2种方式,虽然会产生较多的归档日志,但总比直接影响业务好。但我实际上也想知道,难道oracle搞个分区表,就没有想到我这种场景的解决方案吗?
ycc
答主
2022-03-10
不是没有想到,而是技术实现上有冲突,做不到两全吧
回答交流
Markdown


请输入正文
提交
相关推荐
Oracle 在rman全库备份的时候,登录名rman target system/oracle@CDB和rman target / 有区别吗 ?
回答 3
单实例的话没什么区别,多实例就有区别!
Oracle adg里面能跑存储过程吗?
回答 2
已采纳
不可以
哪本书里面有对10053事件有详细的描述和案例呢
回答 1
已采纳
10053目前oracle官方不对外开放文档,只能在网上搜搜看了,这里我推荐几篇:Oracle的10053事件详解Oracle性能优化之10053事件DBA手记:DBA诊断利器Event10046和1
ORA-17507 如何解决?
回答 30
这是Oracle数据库的错误信息,主要是因为I/O请求的大小不是逻辑块大小的倍数导致的。Oracle数据库的逻辑块大小通常是2KB、4KB、8KB、16KB、32KB等,而I/O请求的大小必须是这些逻
大家好 新手一枚 请多关照哈
回答 2
相互交流学习
sql server management 导出数据到oracle出错
回答 2
先保证ODBC的配置可以正常访问到Oracle实例。另外检查path等环境变量设置是否包含了Oracle的相关路径
oracle 报错:ORA-12518:TNS:监听程序无法分发客户机连接,怎么解决?
回答 1
已采纳
1、首先判断是否由于监听配置不正确的原因导致?2、是否因为数据库服务器处于共享服务器模式,是否会因为DISPATCHERS的数量太少,导致在高峰期的时候无法及时的分配客户机连接呢?3、判断是否PROC
AHF orachk是什么
回答 2
AHF打错了
求一个红帽7生成oracle udev.rule的脚本。谢谢各位
回答 2
已采纳
供ASM使用的磁盘为sddsdi,defghi盘为ASM共享盘可以使用lsblk命令查看磁盘信息:lsblkNAMEMAJ:MINRMSIZEROTYPEMOUNTPOINTsda8:0020G0di
大佬们,Oracle系统的理论知识可以从哪找到啊,还有一些实战经验那些
回答 1
已采纳
可以多读点书,如果对那个问题点不懂,直接网上搜一下。实战经验的话这得实战没办法,即使看人家的故障总结报告,效果也不是太好,毕竟看和经历不是一回事儿。没事儿搭个测试环境,对有些问题做个复盘,测测,这样应