【问题标题】:Concurrent queries to insert data in partitioned table in Oracle在 Oracle 的分区表中插入数据的并发查询
【发布时间】:2018-10-26 04:54:50
【问题描述】:

我正在通过 ETL 工具运行并发插入查询(同时 12 个查询)以将数据插入到 Oracle 中的分区表中。

表定义是

CREATE TABLE CUST_TRAN
(
TRAN_SEQ_NO NUMBER(20,0)
, TRAN_DATE DATE
) 
TABLESPACE USERS
STORAGE (INITIAL 256K NEXT 256K)
PARTITION BY RANGE (TRAN_DATE) 
INTERVAL(NUMTODSINTERVAL(1, 'DAY')) 
(  
   PARTITION CUST_TRAN_p_old VALUES LESS THAN (TO_DATE('1-1-2008', 'DD-MM-YYYY'))
)

这 12 个查询针对 4 个不同的日期运行(每个日期 3 个查询)。因此,12 个查询试图插入 4 个分区。这是示例插入查询 -

insert into cust_tran 
select a.tran_seq_no, trunc(a.tran_datetime) as tran_date
from table_a a
    inner join table_b b on a.store = b.store
        and a.tran_seq_no = b.tran_seq_no
        and trunc(a.tran_datetime) = to_date('2018-01-31', 'YYYY-MM-DD')
        and a.tran_type in ('SALE')

但是,我一直遇到以下问题之一 -

1) 我收到此错误 - ORA-14300: partitioning key maps to a partition outside maximum permitted number of partitions

或者

2) 作业运行良好,没有任何错误,但是将数据插入到 CUST_TRAN_SUMM_p_old 分区中,其中包含一个奇怪的日期,该日期不存在于任何源查询中,并且该日期不存在于源表中。那个奇怪日期的确切值很难说,因为当我使用 SQL Developer 并将日期格式化为 YYYY-MM-DD HH24:MI:SS(在工具 > 首选项 > 数据库 > NLS 中)时,它显示为 null 但当我将显示格式更改为 DD-MON-RR HH24:MI:SS 时,它显示 29-NOV-01 22:58:59。当我使用 DBeaver 时,它显示为 10101-11-29 22:58:59。当我使用 Toad for Oracle 时,它​​显示为 1/1/0001。

第一个问题真的很奇怪,因为我在过滤器中提供了日期,它无法获取另一个不在过滤器中的日期。另外,我在新创建表格后运行它。因此,它不可能达到最大分区数(1,023,999)。

第二个问题同样奇怪。

这是 Oracle 中的错误吗? Oracle 中是否有一些设置需要更改?使用并发插入查询将数据插入分区表有错吗?

【问题讨论】:

  • 据我所知,如果插入操作有多个来源,应该没有问题(你的那种)。你查过源吗?到底是什么?你能在里面找到日期“10101-11-29”吗?
  • 这听起来很奇怪,不应该发生。好消息是,几乎可以肯定它不会发生。但是,如果您希望我们解释实际发生的情况,则需要发布可重现的测试用例。
  • 什么是10101? - 它不能是一年、一个月或一天.... 以DD-MM-YYYY 格式发布您的日期
  • @MarmiteBomber - 当我使用 SQL Developer 并将日期格式化为 YYYY-MM-DD HH24:MI:SS 时,它显示为空。当我使用 DBeaver 时,它显示为 10101-11-29 22:58:59。

标签: oracle plsql partitioning database-administration oracle11gr2


【解决方案1】:

至少有一件事似乎很清楚。你提到的错误是

 ORA-14300: partitioning key maps to a partition outside maximum permitted number of partitions

当您在间隔分区表的分区键中插入值 NULL 时会发生这种情况。

简单试试这个插入

 insert into CUST_TRAN (TRAN_SEQ_NO,TRAN_DATE) Values(1,null); 

对于这个问题没有简单的解决方法,通常使用一些 奇怪的日期(例如 01.01.2999)来代替缺失的日期 - 参见例如here

在这里我将开始调查 - 假设您观察到的 奇怪的日期 可以替代无效日期的缺失。

仅仅调查源数据库是不够的,典型的 ETL 过程比简单的插入要复杂一些。你必须检查 ETL 脚本的代码,看看是否有这样的日期操作。

到您的观察日期 10101-11-29 - 允许的 range for years 排除 10101 作为一年。

Oracle 数据库可以存储儒略时代的日期,范围从公元前 4712 年 1 月 1 日到公元 9999 年 12 月 31 日(共同时代,或“公元”)。除非专门使用 BCE(格式掩码中的“BC”),否则 CE 日期条目是默认值。

事实上,这个日期在 old 分区中(即小于 2008 年),我假设它是 29 年的 11 月 - DATE'0029-11-01' 并且 DAY 以某种方式与其他字符串连接输出

【讨论】:

  • 我可以肯定地告诉您一件事 - ETL 工具或流程没有任何问题。我确实创建了一个非常简单的 ETL 流程,没有任何变量。我已经硬编码了所有的值和日期。通过 ETL 工具同时运行 12 个插入查询。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-04-13
  • 2015-10-20
相关资源
最近更新 更多