I have a table with about 20 partitions. Each partition has about 190 million records. I need to gather statistics on the table periodically during my processing, which I do using the DBMS_STATS.GATHER_TABLE_STATS command. When the table only had 1 partition, it used to take about 4 minutes to complete. Over time, the number of partitions has grown, and the time it takes to gather_table_stats has grown as well. I then switched to gathering stats on just the partition by adding a PARTNAME parameter to the GATHER_TABLE_STATS command, but the time it takes hasn't dropped. I have even created a new partition with only 1,000 rows in it, and when I gather stats on that partition, it still takes between 22 and 25 minutes to complete. I looked in the USER_TAB_PARTITIONS table, and I see that the LAST_ANALYZED column is only being updated for the partition I specified in the GATHER_TABLE_STATS, so I'm believe that the stats are only being gathered on my single partition, but why does it take so long? If it helps, this is my DDL. Note that I'm creating a LOCAL index. There are no other table that have foreign key references into this table.
CREATE TABLE LAR_ALLOCATION_PER_PART (
PROC_MONTH DATE NOT NULL,
COUNTRY_CODE VARCHAR2(2) NOT NULL,
PART_NUMBER VARCHAR2(20),
CUSTOMER_CODE VARCHAR2(32),
LAR_ID NUMBER NOT NULL,
GROSS_SALES_AMOUNT NUMBER,
ALLOCATION_AMOUNT NUMBER,
WARRANTY_AMOUNT NUMBER,
CURRENCY_CODE VARCHAR2(5),
CONSTRAINT LAR_ALLOC_PP_COUNTRY_CODE_FK FOREIGN KEY (COUNTRY_CODE) REFERENCES SUPPORTED_COUNTRY (COUNTRY_CODE),
CONSTRAINT LAR_ALLOC_PP_PART_NUM_FK FOREIGN KEY (PART_NUMBER) REFERENCES PART_CLASSIFICATION (ODS_PART_NUMBER),
CONSTRAINT LAR_ALLOC_PP_LAR_ID_FK FOREIGN KEY (LAR_ID) REFERENCES LEDGER_ALLOCATION_RULE (ID)
)
PARTITION BY RANGE(PROC_MONTH)
INTERVAL(NUMTOYMINTERVAL(1,'MONTH'))
(
PARTITION prior2017 VALUES LESS THAN (TO_DATE('01-JAN-2017', 'DD-MON-YYYY'))
);
CREATE INDEX LAR_ALLOCATION_PER_PART_IDX
ON LAR_ALLOCATION_PER_PART
(COUNTRY_CODE, LAR_ID, CUSTOMER_CODE, PART_NUMBER) LOCAL;
And this is the command I use to gather statistics:
BEGIN
DBMS_STATS.GATHER_TABLE_STATS(OWNNAME => 'MY_SCHEMA',
TABNAME => 'LAR_ALLOCATION_PER_PART',
PARTNAME => 'SYS_P40553', --Jan 2020: 1,000 records
OPTIONS => 'GATHER AUTO',
DEGREE => DBMS_STATS.DEFAULT_DEGREE,
CASCADE => TRUE);
END;
I've tried setting CASCADE to FALSE, adjusting the DEGREE to 32, even setting an ESTIMATE_PERCENT value to 10, but nothing have a statistically significant impact on run time.
I just saw an answer about using incremental statistics, and I'm going to try that out, but I'd like to understand why stat gathering on a partition takes so long, and if I'm doing something incorrectly.