У меня есть таблица с 20 разделами. Каждый раздел имеет около 190 миллионов записей. Мне нужно периодически собирать статистику для таблицы во время обработки, которую я делаю с помощью команды DBMS_STATS.GATHER_TABLE_STATS. Когда в таблице был только 1 раздел, на его завершение уходило около 4 минут. Со временем количество разделов выросло, и время, которое требуется для collect_table_stats, также увеличилось. Затем я переключился на сбор статистики только по разделу, добавив параметр PARTNAME в команду GATHER_TABLE_STATS, но время, которое требуется, не уменьшилось. Я даже создал новый раздел, в котором всего 1000 строк, и когда я собираю статистику по этому разделу, это все равно занимает от 22 до 25 минут.
Я посмотрел в таблице USER_TAB_PARTITIONS и вижу, что столбец LAST_ANALYZED обновляется только для раздела, указанного в GATHER_TABLE_STATS, поэтому я считаю, что статистика собирается только для моего отдельного раздела, но почему это так? долго?
Если это поможет, это мой DDL. Обратите внимание, что я создаю ЛОКАЛЬНЫЙ индекс. Нет другой таблицы, в которой есть ссылки на внешние ключи в этой таблице.
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;
И это команда, которую я использую для сбора статистики:
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;
Я пытался установить для CASCADE значение FALSE, для параметра DEGREE установить значение 32, даже для значения ESTIMATE_PERCENT установить значение 10, но ничто не оказывает статистически значимого влияния на время выполнения.
Я только что увидел ответ об использовании инкрементной статистики, и я собираюсь попробовать это, но я хотел бы понять, почему сбор статистики по разделу занимает так много времени, и если я что-то делаю неправильно.