【问题标题】:ORA-14097: column type or size mismatch in ALTER TABLE EXCHANGE PARTITIONORA-14097: ALTER TABLE EXCHANGE PARTITION 中的列类型或大小不匹配
【发布时间】:2021-10-03 19:35:11
【问题描述】:

我在交换分区时遇到了 ORA-14097。谁能给我点灯?

我有以下 source_tbl(非分区)表,打算使用“VALID_PERIOD_END”列对其进行分区

CREATE TABLE source_tbl
   (    INVOICE_ID NUMBER(15,0) NOT NULL ENABLE, 
    LATEST_FLAG_NAME VARCHAR2(3000), 
    STD_HASH **RAW**(1000), 
    VALID_PERIOD_START TIMESTAMP (6), 
    VALID_PERIOD_END **TIMESTAMP** (6), 
    OVERSEAS NUMBER, 
   .. <another 20 number columns)
    VIP_NO NUMBER
   ) partition by range(VALID_PERIOD_END)
nologging;

这个表现在有 5M 行,我想按 VALID_PERIOD_END 对其进行分区,这样如果它是 '9999-12-31 23:59:59' (当前)将在一个分区中,而其余的则在另一个分区中

我创建了第二个名为 TEMP_tbl 的表

CREATE TABLE TEMP_tbl
   (    INVOICE_ID NUMBER(15,0) NOT NULL ENABLE, 
    LATEST_FLAG_NAME VARCHAR2(3000), 
    STD_HASH **RAW**(1000), 
    VALID_PERIOD_START TIMESTAMP (6), 
    VALID_PERIOD_END **TIMESTAMP** (6), 
    OVERSEAS NUMBER, 
   .. <another 20 number columns)
    VIP_NO NUMBER
   )partition by range(VALID_PERIOD_END)
(partition p1 values less than(maxvalue)) nologging;

TEMP_tbl 具有与 source_tbl 完全相同的数据结构,因为脚本是使用驱动的 dbms_metadata.get_ddl

我已经执行了收集表状态,没有返回任何错误

EXEC DBMS_STATS.gather_table_stats(USER, upper('source_tbl'), cascade => TRUE);

但是,当我尝试执行以下交换分区语句时,出现上述错误

alter table TEMP_tbl
          exchange partition p1
          with table source_tbl
          without validation
          update global indexes
;

我已检查“user_tab_cols”,并确认 source_tbl 中没有隐藏列。会不会是因为我表中的原始列?

提前致谢!

【问题讨论】:

  • 关于类似主题的另一个问题。它不完全是重复的,但它可能会有所帮助:stackoverflow.com/questions/41684333/…
  • @Del,是的,我确实注意到了,并尝试了答案中的说明。但是,我没有任何隐藏的列。这就是我建立博客的原因。
  • 我确实在在线文档中看到了有关移动具有 LONG RAW 列的表的注释,但在 RAW 上没有任何内容或关于使用这些数据类型交换分区。
  • 作为替代方法,您可以考虑将dbms_redefinition添加 分区到现有表。它还自己处理所需的依赖关系。
  • 是你实际的sql(除了***)吗?因为您的 source_tbl 代码显示“按范围分区..”

标签: sql oracle query-optimization table-partitioning


【解决方案1】:

Oracle 12.2 引入了两个新的分区功能,这将帮助您在此处获得很棒的交易。

  1. 引入了新的ALTER TABLE MODIFY PARTITION BY DDL,它允许将非分区表转换为分区表。此操作会将现有非分区表中的数据复制到新表分区中,因此可以长时间运行。您可以指定ONLINE 关键字在联机模式下进行操作,这意味着在ALTER TABLE 运行时将允许对表进行DML 操作。例如:
    ALTER TABLE source_tbl
      MODIFY PARTITION BY RANGE(VALID_PERIOD_END)
      (partition p1 values less than (timestamp '9999-12-31 23:59:59'),
       partition p2 values less than (maxvalue))
      ONLINE;
  1. 为了帮助您解决您面临的EXCHANGE PARTITION 问题,CREATE TABLE 中引入了FOR EXCHANGE WITH TABLE 子句。这专门用于在创建将与现有表交换的新表时精确匹配物理列。可选地,FOR EXCHANGE WITH TABLE 可以与PARTITION BY 一起使用,以创建可以与源表交换的分区表。例如:
    CREATE TABLE TEMP_tbl
      PARTITION BY RANGE(VALID_PERIOD_END)
      (partition p1 values less than(maxvalue))
      FOR EXCHANGE WITH TABLE source_tbl;

Here is a blog article 描述了这两种分区增强功能。而here is another blog article 则专门讨论使用CREATE TABLE ... FOR EXCHANGE WITH TABLE 来解决EXCHANGE PARTITION 错误。

您没有提及您使用的是哪个版本的 Oracle,因此您可能仍在运行 11g。在这种情况下,您可能需要深入了解USER_TAB_COLS 以查看两个表之间的区别。您提到您已经检查了隐藏列(这很好),但可能会发生其他不匹配。

要记住的一点是NULLABLE 列属性必须在两个表之间匹配。如果一个表有主键约束,而另一个没有,则该列可能在主键表中不可为空,而在另一表中为可空,这将导致 ORA-14097。

如果这不能解释问题,您还可以查看SEGMENT_COLUMN_ID ordering、DATA_TYPEDATA_LENGTHDATA_PRECISIONDATA_PRECISION。由于您使用dbms_metadata.get_ddl 创建表,这些东西应该匹配,但必须有一些差异,否则您不会收到错误。

RAW(1000) 列对于EXCHANGE PARTITION 来说应该不是问题。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-06-04
    • 2021-12-21
    • 2016-07-03
    • 1970-01-01
    • 1970-01-01
    • 2020-05-04
    • 2017-06-24
    相关资源
    最近更新 更多