【问题标题】:After drop the partition,the index became unusable,what should I do,删除分区后,索引变得不可用,我该怎么办,
【发布时间】:2018-12-23 13:19:04
【问题描述】:

由于我按月对目标表进行了间隔分区,并且只保留 27 个月的数据(因此需要每月删除最旧的分区)。 在我使用下面的 SQL 删除它之后,我运行了 SP,SP 很慢。

alter table target_table drop partition target_eldest_partition;

于是我取消了SP并分析了表格

ANALYZE TABLE target_table  COMPUTE STATISTICS;     

但是遇到了错误

Error starting at line : 12 in command -
ANALYZE TABLE per_limra COMPUTE STATISTICS
Error report -
ORA-01502: index 'target_index' or partition of such index is in unusable state
01502. 00000 -  "index '%s.%s' or partition of such index is in unusable state"
*Cause:    An attempt has been made to access an index or index partition
           that has been marked unusable by a direct load or by a DDL
           operation
*Action:   DROP the specified index, or REBUILD the specified index, or
           REBUILD the unusable index partition

所以我google了一下,有一些问题,请帮忙。

问题1:ANALYZE TABLE不会重建索引吧?

问题2:索引错误原因,*Cause: ........ by a direct load是什么意思?

问题3:背景,通过下面的SQL检查,实际上我的目标表的索引现在无法使用。

SELECT owner, index_name, tablespace_name
FROM   dba_indexes
WHERE  status = 'UNUSABLE';

我在使用以下 SQL 创建分区表时创建了索引

  CREATE INDEX "schema_name"."target_index1" ON "schema_name"."target_table" ("col1") 
  PCTFREE 10 INITRANS 2 MAXTRANS 255 COMPUTE STATISTICS NOLOGGING 
  STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
  PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1
  BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT)
  TABLESPACE "target_tablespace" ;

我知道在使用分区表时,索引有两种类型,全局索引和本地索引,我的索引定义属于什么?看来我没有使用分区索引,因为我在这里没有找到我的目标表分区名称。

问题4:如何解决索引不可用的问题,删除分区后需要成熟的解决方案。

问题5:我的目标表有5000万条数据,每个月大概有190万条,所以我认为使用DBMS_STATS.GATHER_TABLE_STATSANALYZE TABLE target_table COMPUTE STATISTICS更新统计是必要的,但是太慢了,有什么其他的解决方案。

请帮忙提供建议。谢谢。

【问题讨论】:

  • 索引是全局的(一个段代表整个索引),不是分区的(按分区键分割)。如果您想要分区索引,请在您的 create index 命令中使用 local 关键字。或者,将其保留为全局,但在管理表分区时包含update global indexes 子句,以便它不会失效。您的 Oracle 版本在这里很重要,因为更高版本具有更多功能。
  • 明白了,非常感谢@Wernfried

标签: oracle indexing partitioning


【解决方案1】:
  • ANALYZE TABLE 不会重建索引,对吧?

    我不知道,但现在你应该使用 DBMS_STATS.GATHER_TABLE_STATS 而不是 ANALYZE TABLE

  • 直接加载意味着数据不是逐行插入而是批量插入,参见Direct Path Load

  • 如果您的索引变为UNUSABLE,那么它必须是全局索引。

  • 使用UPDATE GLOBAL INDEXES 子句,即alter table target_table drop partition target_eldest_partition UPDATE GLOBAL INDEXES; 或创建本地索引。

  • 取决于您为哪些列建立了索引。您也可以运行DBMS_STATS.GATHER_INDEX_STATS,而不是整个表。使用DBMS_STATS.GATHER_TABLE_STATS,您还可以仅指定单个分区甚至单个列。

顺便说一句,对于许多问题,我的回答实际上应该是:“您是否查阅过 Oracle 文档”?或“你知道谷歌”吗?根据您的屏幕截图,您对用户对象使用架构 SYS 和表空间 SYSAUX。你不应该那样做。创建您自己的用户并在此架构中创建任何对象。

通常有三种类型的分区索引:

  1. GLOBAL INDEX:您有一个跨越整个表的大索引。如果索引列不是分区键的一部分,则这是强制性的,例如 UNIQUE INDEXES。实际上这样的索引是没有分区的。 (如ALL_INDEXES所示)
  2. LOCAL INDEX:此索引的分区方式与基础表相同。每个表分区都有一个相应的索引分区。
  3. PARTITIONED INDEX:此索引已分区但不同于基础表。我认为甚至可以在非分区表上创建分区索引。分区索引仅限于非常特殊的用例。实际上我无法想象这样的索引在哪里有意义。

【讨论】:

  • 谢谢,@Wernfried,有些概念没有google到oracle doc,除非有混淆,不会发这样的问题,
  • ,请参考我新添加的问题3截图,为什么分区列是'No'但它是全局分区索引。它不应该是非分区索引吗?请指教。
【解决方案2】:

回答您的问题:

  1. ANALYZE TABLE 不会重建索引,对吧?

您永远不应该使用分析表 - 使用 DBMS_STATS.GATHER_TABLE_STATISTICS。不,收集统计信息不会重建索引。

  1. 索引错误原因,*Cause: ........ by a direct load 是什么意思?

在这种情况下,“直接加载”问题不是问题。问题是您删除了一个分区,并且表上有非本地索引。

  1. 我的索引定义属于什么?

您显示的索引是非本地索引。因此,无论何时删除一个分区,它都会变得无效,因为删除的分区中的任何行都不再存在。解决方案是将索引删除并重新创建为 LOCAL 索引。它们的构建也简单得多。例如:

CREATE INDEX "schema_name"."target_index1"
  ON "schema_name"."target_table" ("col1")
  LOCAL;

完成。

  1. 如何解决索引不可用的问题,我删除分区后需要一个成熟的解决方案。

使用本地索引。

  1. 我的目标表有 5000 万条数据,每个月大约 190 万条,所以我认为使用 DBMS_STATS.GATHER_TABLE_STATS 或 ANALYZE TABLE target_table COMPUTE STATISTICS 来更新统计信息是必要的,但这太慢了,有没有其他解决方案。

使用ESTIMATE_PERCENT 参数GATHER_TABLE_STATS 告诉它只对一定百分比的行进行采样。例如

DBMS_STATS.GATHER_TABLE_STATS(OWNNAME=> 'NAME_OF_OWNER',
                              TABNAME => 'PER_LIMRA',
                              ESTIMATE_PERCENT => 5);

您还可以使用DEGREE 参数告诉系统并行收集统计信息。您可以尝试不同的值,看看它是否对您的情况有帮助。

祝你好运。

【讨论】:

    猜你喜欢
    • 2020-09-28
    • 1970-01-01
    • 2021-11-22
    • 1970-01-01
    • 2021-10-15
    • 2013-12-17
    • 2021-12-10
    • 2019-05-09
    • 2019-07-14
    相关资源
    最近更新 更多