Czy Klauzula UPDATE INDEXES W Instrukcji DDL Odświeża Lokalne I Globalne Indeksy

Jakakolwiek modyfikacja na partycjach powoduje unieważnienie indeksów przypisanych do partycji, a co za tym idzie wymusza konieczność przebudowy tych indeksów. Czy można się tego wystrzec stosując klauzulę UPDATE INDEXES? Odpowiedź poniżej.

Poniższy kod przygotowuje tabelę, indeksy (zarówno lokalne jak i globalne) jak i nabija tabelę danymi do testu. Jak widać poniżej zarówno indeks lokalny jak i globalny mają statusy sugerujące ich prawidłowość, co jest jak najbardziej prawidłowe.

DROP TABLE T1
/

CREATE TABLE T1(id NUMBER, descr VARCHAR2(100))
PARTITION BY RANGE(id)
(
  PARTITION p1 VALUES LESS THAN (100),
  PARTITION p2 VALUES LESS THAN (200),
  PARTITION p3 VALUES LESS THAN (MAXVALUE)
)
/

CREATE INDEX idx_local on t1(id) local
/
CREATE INDEX idx_global on t1(descr) --default: global
/

INSERT INTO t1
  SELECT ROWNUM, CASE WHEN MOD(ROWNUM, 2) = 0 THEN 'A' ELSE 'B' END FROM dual
  CONNECT BY ROWNUM <= 300
/

COMMIT
/
SELECT index_name, status 
  FROM dba_indexes
 WHERE table_name = 'T1'
/
INDEX_NAME   STATUS
----------   ------
IDX_LOCAL    N/A   <-- to jest prawidłowe, index jest partycjonowany, więc status znajduje się w dba_ind_partitions
IDX_GLOBAL   VALID
SELECT index_name, high_value, partition_position, status 
  FROM dba_ind_partitions
 WHERE index_name IN (SELECT index_name FROM dba_indexes
                       WHERE table_name = 'T1')
/
INDEX_NAME   HIGH_VALUE  PARTITION_POSITION  STATUS
----------   ----------  ------------------  ------
IDX_LOCAL	100	         1           USABLE
IDX_LOCAL	200	         2	     USABLE
IDX_LOCAL	MAXVALUE         3           USABLE

Poniższy kod przebudowuje partycję P1 i umożliwi sprawdzenie, jak po takiej instrukcji zachowają się indeksy.

ALTER TABLE T1 MOVE PARTITION P1
/

SELECT index_name, status 
  FROM dba_indexes
 WHERE table_name = 'T1'
/
INDEX_NAME   STATUS
----------   ------
IDX_LOCAL    N/A   
IDX_GLOBAL   UNUSABLE
SELECT index_name, high_value, partition_position, status 
  FROM dba_ind_partitions
 WHERE index_name IN (SELECT index_name FROM dba_indexes
                       WHERE table_name = 'T1')
/
INDEX_NAME   HIGH_VALUE  PARTITION_POSITION  STATUS
----------   ----------  ------------------  ------
IDX_LOCAL	100	         1           UNUSABLE
IDX_LOCAL	200	         2	     USABLE
IDX_LOCAL	MAXVALUE         3           USABLE

Statusy prawidłowo wskazują, że na partycji P1 miały miejsce jakieś działania, ale nie odświeżono indeksów. Potwierdziło to, zresztą słusznie, że samo polecenie ALTER TABLE w żaden sposób nie nakazuje działań na indeksach.

Do dalszych działań konieczne jest odświeżenie indeksów, aby uzyskać stan indeksów jak na początku.

ALTER INDEX idx_global REBUILD
/
ALTER INDEX idx_local REBUILD PARTITION P1
/


ALTER TABLE T1 MOVE PARTITION P1 UPDATE INDEXES
/


SELECT index_name, status 
  FROM dba_indexes
 WHERE table_name = 'T1'
/
INDEX_NAME   STATUS
----------   ------
IDX_LOCAL    N/A   
IDX_GLOBAL   VALID
SELECT index_name, high_value, partition_position, status 
  FROM dba_ind_partitions
 WHERE index_name IN (SELECT index_name FROM dba_indexes
                       WHERE table_name = 'T1')
/
INDEX_NAME   HIGH_VALUE  PARTITION_POSITION  STATUS
----------   ----------  ------------------  ------
IDX_LOCAL	100	         1           USABLE
IDX_LOCAL	200	         2	     USABLE
IDX_LOCAL	MAXVALUE         3           USABLE

Reasumując. Klauzula UPDATE INDEXES w poleceniu ALTER TABLE odświeża zarówno indeksy lokalne jak i globalne. Nie dzieje się to jednak bezkosztowo, bo taki zabieg kosztuje dodatkowy czas i zasoby i jeżeli wymogiem nie jest wydajność to warto z niej korzystać.

Szymon

Komentarze |0|

Legenda *) Pola oznaczone gwiazdką są wymagane
**) Możesz używać tych znaczników i atrybutów HTML: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>