Как избежать перестройки индекса по исходной таблице после обмена

У меня есть ежедневная работа, и эта работа делает в основном

  1. LOAD Temp таблица
  2. Раздел Exchange с исходной таблицей
  3. Перестройте локальные индексы
  4. Перестройте глобальные индексы

Однако проблема в том, что перестройка индексов занимает много времени, и это делает исходную таблицу недоступной в течение этого периода. Исходная таблица является очень важной таблицей для поддержки приложений в реальном времени. Из-за этого веб-службы, использующие эту таблицу, получают исключения тайм-аута.

Есть ли у меня какой-либо альтернативный способ, а не строить эти индексы на исходной таблице?

Любая помощь или обсуждение очень ценится.

Вы можете найти фрагмент кода ежедневной работы, а также структуру исходной таблицы (TABLEX) и временной таблицы (TABLEX_TEMP).

Ежедневная работа:

`СОЗДАТЬ ИЛИ ЗАМЕНИТЬ ПРОЦЕДУРУ X.LOAD__TABLES_X IS

BEGIN


EXECUTE IMMEDIATE 'TRUNCATE TABLE TABLEX_TEMP REUSE STORAGE';
   INSERT /*+ APPEND */ INTO TABLEX_TEMP(CUST_NO ,IDNO,SEX,NAME,SURNAME)
   SELECT CUST_NO ,IDNO,SEX,NAME,SURNAME,PHONE
FROM T_X WHERE MAINT !='D';
COMMIT;

EXECUTE IMMEDIATE 'ALTER TABLE TABLEX EXCHANGE PARTITION DUMMY WITH TABLE TABLEX_TEMP WITHOUT VALIDATION';
EXECUTE IMMEDIATE 'ALTER TABLE TABLEX MODIFY PARTITION DUMMY REBUILD UNUSABLE LOCAL INDEXES';
EXECUTE IMMEDIATE 'ALTER INDEX PK_CUST_NO REBUILD NOCOMPRESS NOPARALLEL TABLESPACE TS_X_INDEX';
EXECUTE IMMEDIATE 'ALTER INDEX PK_CUST_NO_TMP REBUILD NOCOMPRESS NOPARALLEL TABLESPACE TS_X_INDEX';
EXECUTE IMMEDIATE 'ALTER INDEX IDX_TABLEX REBUILD NOCOMPRESS NOPARALLEL TABLESPACE TS_X_INDEX';
EXECUTE IMMEDIATE 'ALTER INDEX IDX_TABLEX_TMP REBUILD NOCOMPRESS NOPARALLEL TABLESPACE TS_X_INDEX';
EXECUTE IMMEDIATE 'TRUNCATE TABLE TABLEX_TEMP REUSE STORAGE';

COMMIT;
END LOAD_TABLES_X;`

Структура таблиц и индексов:

`

CREATE TABLE X.TABLEX_TEMP (CUST_NO NUMBER (9), NAME VARCHAR2 (54 байта), SARNAME VARCHAR2(100 байт), SEX VARCHAR (1 байт), IDNO NUMBER (11)

)
TABLESPACE TS_X_DATAA
RESULT_CACHE (MODE DEFAULT)
PCTUSED    0
PCTFREE    0
INITRANS   1
MAXTRANS   255
STORAGE    (
        INITIAL          8M
        NEXT             1M
        MINEXTENTS       1
        MAXEXTENTS       UNLIMITED
        PCTINCREASE      0
        BUFFER_POOL      DEFAULT
        FLASH_CACHE      DEFAULT
        CELL_FLASH_CACHE DEFAULT
       )
LOGGING 
COMPRESS FOR QUERY HIGH 
NOCACHE
NOPARALLEL
MONITORING;


CREATE INDEX X.IDX_TABLEX_TMP ON X.TABLEX_TEMP
(IDNO)
NOLOGGING
TABLESPACE TS_X_INDEX
PCTFREE    10
INITRANS   2
MAXTRANS   255
STORAGE    (
        INITIAL          64K
        NEXT             1M
        MINEXTENTS       1
        MAXEXTENTS       UNLIMITED
        PCTINCREASE      0
        BUFFER_POOL      DEFAULT
        FLASH_CACHE      DEFAULT
        CELL_FLASH_CACHE DEFAULT
       )
NOPARALLEL;


CREATE UNIQUE INDEX X.PK_CUST_NO_TMP ON X.TABLEX_TEMP
(CUST_NO)
NOLOGGING
TABLESPACE TS_X_INDEX
PCTFREE    10
INITRANS   2
MAXTRANS   255
STORAGE    (
        INITIAL          64K
        NEXT             1M
        MINEXTENTS       1
        MAXEXTENTS       UNLIMITED
        PCTINCREASE      0
        BUFFER_POOL      DEFAULT
        FLASH_CACHE      DEFAULT
        CELL_FLASH_CACHE DEFAULT
       )
NOPARALLEL;


ALTER TABLE X.TABLEX_TEMP ADD (
  CONSTRAINT PK_CUST_NO_TMP
  PRIMARY KEY
  (CUST_NO)
  USING INDEX X.PK_CUST_NO_TMP
   ENABLE NOVALIDATE);

 ----------------------------------------------------------

CREATE TABLE X.TABLEX
 (
   CUST_NO       NUMBER(9),
   NAME            VARCHAR2(54 BYTE),
   SURNAME         VARCHAR2(100 BYTE),
   SEX              VARCHAR (1 BYTE)
   IDNO            NUMBER(11)
 )
COMPRESS FOR QUERY HIGH 
TABLESPACE TS_X_DATA
RESULT_CACHE (MODE DEFAULT)
PCTUSED    0
PCTFREE    0
INITRANS   1
MAXTRANS   255
STORAGE    (
        BUFFER_POOL      DEFAULT
        FLASH_CACHE      DEFAULT
        CELL_FLASH_CACHE DEFAULT
       )
PARTITION BY RANGE (CUST_NO)
(  
   PARTITION DUMMY VALUES LESS THAN (999999999)
   LOGGING
   COMPRESS FOR QUERY HIGH 
    TABLESPACE TS_X_DATA
    PCTFREE    0
    INITRANS   1
    MAXTRANS   255
    STORAGE    (
            INITIAL          64K
            NEXT             1M
            MINEXTENTS       1
            MAXEXTENTS       UNLIMITED
            BUFFER_POOL      DEFAULT
            FLASH_CACHE      DEFAULT
            CELL_FLASH_CACHE DEFAULT
           )
   )
 NOCACHE
 NOPARALLEL
 MONITORING;


 CREATE INDEX X.IDX_TABLEX ON X.TABLEX
 (IDNO)
 NOLOGGING
 TABLESPACE TS_X_INDEX
 PCTFREE    10
 INITRANS   2
 MAXTRANS   255
 STORAGE    (
        INITIAL          64K
        NEXT             1M
        MINEXTENTS       1
        MAXEXTENTS       UNLIMITED
        PCTINCREASE      0
        BUFFER_POOL      DEFAULT
        FLASH_CACHE      DEFAULT
        CELL_FLASH_CACHE DEFAULT
       )
 NOPARALLEL;


 CREATE UNIQUE INDEX X.PK_CUST_NO ON X.TABLEX
 (CUST_NO)
 NOLOGGING
 TABLESPACE TS_X_INDEX
 PCTFREE    10
 INITRANS   2
 MAXTRANS   255
 STORAGE    (
        INITIAL          64K
        NEXT             1M
        MINEXTENTS       1
        MAXEXTENTS       UNLIMITED
        PCTINCREASE      0
        BUFFER_POOL      DEFAULT
        FLASH_CACHE      DEFAULT
        CELL_FLASH_CACHE DEFAULT
       )
 NOPARALLEL;



 ALTER TABLE X.TABLEX ADD (
   CONSTRAINT PK_CUST_NO
   PRIMARY KEY
   (CUST_NO)
   USING INDEX X.PK_CUST_NO
   ENABLE NOVALIDATE);

`

1 ответ

Решение

Что ж, поскольку обмен разделами изменяет существенную часть данных, индекс становится непригодным для использования. Однако вы можете избежать невозможности использования индекса, обновив индексы во время обмена разделами.

По моему опыту лучше всего использовать двухэтапный подход:

  • Перед обменом разделами вы должны построить те же локальные индексы для временной таблицы. Затем вы должны добавить INCLUDING INDEXES к команде ALTER TABLE.
  • Если вам нужно использовать глобальные индексы, вы можете обновить их во время обмена разделами, добавив UPDATE GLOBAL INDEXES в команду ALTER TABLE. Это гарантирует, что глобальные индексы не будут непригодными для использования в течение всей операции.

Таким образом, все ваше утверждение станет примерно таким:

ALTER TABLE TABLEX EXCHANGE PARTITION DUMMY WITH TABLE TABLEX_TEMP INCLUDING INDEXES WITHOUT VALIDATION UPDATE GLOBAL INDEXES;

Вы можете посмотреть официальную документацию Oracle для деталей:

Другие вопросы по тегам