问题
As I partitioned the target table for interval partitioning by month, and only keep 27 months data(so need drop the eldest partition monthly). After I use below SQL to drop it,I ran the SP, the SP was very slowly.
alter table target_table drop partition target_eldest_partition;
So I cancel the SP and analyzed the table
ANALYZE TABLE target_table COMPUTE STATISTICS;
but it encountered an error
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
So I googled it and got some questions,Please help.
Question 1: ANALYZE TABLE does not rebuild the index,right?
Question 2: index error cause,what does *Cause: ........ by a direct load mean?
Question 3: background ,actually the index for my target table are unusable now by checked with below SQL.
SELECT owner, index_name, tablespace_name
FROM dba_indexes
WHERE status = 'UNUSABLE';
I create my index when created my partitioned table with below 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" ;
I know when use partitioned table,there are two type for indexes, Global index and Local index, what does my index definition belong to? seems I did not use the partitioned index as I did not found my target table partition name here.
Question 4: What should I do to solve the unusable index issue, I need a mature solutions after I drop the partition.
Question 5:My target table has 50 million data,and for each month about 1,900,000, So I think use DBMS_STATS.GATHER_TABLE_STATSor ANALYZE TABLE target_table COMPUTE STATISTICS to update the statistics is necessary, but that was too slow,have any other solutions.
Please help give advice. Thanks.
回答1:
ANALYZE TABLE does not rebuild the index,right?
I don't know but nowadays you should use
DBMS_STATS.GATHER_TABLE_STATSrather thanANALYZE TABLEDirect load means data is not inserted row by row but as bulk, see Direct Path Load
If your index become
UNUSABLEthen it must be a global index.Use the
UPDATE GLOBAL INDEXESclause, i.e.alter table target_table drop partition target_eldest_partition UPDATE GLOBAL INDEXES;or create local indexes.Depends on which columns you have indexed. Instead of entire table you can also run
DBMS_STATS.GATHER_INDEX_STATS. WithDBMS_STATS.GATHER_TABLE_STATSyou can also specify just single partitions and even single columns.
btw, for many questions my answer actually should be: "Did you consult the Oracle documentation"? or "Do you know google"? According to your screenshots you use schema SYS and tablespace SYSAUX for your user objects. You should not do that. Create your own user and create any object in this schema.
In general there are three types of partitioned indexes:
- GLOBAL INDEX: You have one big index spanning over entire table. This is mandatory for instance for UNIQUE INDEXES if the indexed columns are not part of the partition key. Actually such index is not partitioned. (as shown in
ALL_INDEXES) - LOCAL INDEX: This index is partitioned in the same way as the underlying table is. Each table partition has an according index partition.
- PARTITIONED INDEX: This index is partitioned but different than the underlying table. I think it is even possible to create a partitioned index on a non-partitioned table. Partitioned indexes are limited to very special use cases only. Actually I cannot imagine where such index would make sense.
回答2:
To cover your questions:
- ANALYZE TABLE does not rebuild the index,right?
You should never use ANALYZE TABLE - use DBMS_STATS.GATHER_TABLE_STATISTICS. And no, gathering statistics does not rebuild indexes.
- Index error cause,what does *Cause: ........ by a direct load mean?
In this case, the "direct load" issue is not the problem. The problem is that you dropped a partition, and you have non-LOCAL indexes on the table.
- What does my index definition belong to?
The index you showed is a non-LOCAL index. Thus whenever you drop a partition it's going to become invalid because any rows in the dropped partition are no longer present. The solution is to drop and recreate your indexes as LOCAL indexes. They're also much simpler to build. For example:
CREATE INDEX "schema_name"."target_index1"
ON "schema_name"."target_table" ("col1")
LOCAL;
Done.
- What should I do to solve the unusable index issue, I need a mature solutions after I drop the partition.
Use LOCAL indexes.
- My target table has 50 million data,and for each month about 1,900,000, So I think use DBMS_STATS.GATHER_TABLE_STATS or ANALYZE TABLE target_table COMPUTE STATISTICS to update the statistics is necessary, but that was too slow,have any other solutions.
Use the ESTIMATE_PERCENT argument to GATHER_TABLE_STATS to tell it to only sample a certain percentage of the rows. For example
DBMS_STATS.GATHER_TABLE_STATS(OWNNAME=> 'NAME_OF_OWNER',
TABNAME => 'PER_LIMRA',
ESTIMATE_PERCENT => 5);
You can also use the DEGREE argument to tell the system to gather statistics in parallel. You can try different values to see if it helps in your situation.
Best of luck.
来源:https://stackoverflow.com/questions/51354262/after-drop-the-partition-the-index-became-unusable-what-should-i-do