Hi.
The nature of the work and the type of index has a big impact. Check this out:
Create and populates a test table with a PK and two non-unique indexed columns.
- Code: Select all
DROP TABLE t1;
CREATE TABLE t1 (
id NUMBER(10),
num NUMBER(10),
str VARCHAR2(10),
description VARCHAR2(50),
CONSTRAINT t1_pk PRIMARY KEY (id)
);
CREATE INDEX t1_num_idx ON t1(num);
CREATE INDEX t1_str_idx ON t1(str);
BEGIN
-- row-by-row insert rather than bulk on purpose.
FOR i IN 1 .. 400000 LOOP
INSERT INTO t1 (id, num, str, description)
VALUES (i, i, TO_CHAR(i), 'Description for ' || TO_CHAR(i));
END LOOP;
COMMIT;
END;
/
EXEC DBMS_STATS.gather_table_stats(USER, 'T1', cascade => TRUE);
Get information about the index.
- Code: Select all
SET LINESIZE 120
SELECT index_name,
blevel,
leaf_blocks,
distinct_keys,
avg_leaf_blocks_per_key AS avg_lbpk,
avg_data_blocks_per_key AS avg_dbpk,
clustering_factor
FROM user_indexes
ORDER BY index_name;
INDEX_NAME BLEVEL LEAF_BLOCKS DISTINCT_KEYS AVG_LBPK AVG_DBPK CLUSTERING_FACTOR
------------------------------ ---------- ----------- ------------- ---------- ---------- -----------------
T1_NUM_IDX 2 799 400000 1 1 2451
T1_PK 2 750 400000 1 1 2451
T1_STR_IDX 2 1666 398144 1 1 77980
SQL>
SELECT segment_name,
blocks
FROM user_segments
WHERE segment_type = 'INDEX'
ORDER BY segment_name;
SEGMENT_NAME BLOCKS
--------------------------------------------------------------------------------- ----------
T1_NUM_IDX 896
T1_PK 896
T1_STR_IDX 1792
SQL>
Reusing Index KeysDelete 100,000 rows (25%) of table and repopulate using the same keys we deleted (1 to 100,000).
- Code: Select all
DELETE FROM t1 WHERE id BETWEEN 1 AND 100000;
COMMIT;
BEGIN
-- row-by-row insert rather than bulk on purpose.
FOR i IN 1 .. 100000 LOOP
INSERT INTO t1 (id, num, str, description)
VALUES (i, i, TO_CHAR(i), 'Description for ' || TO_CHAR(i));
END LOOP;
COMMIT;
END;
/
EXEC DBMS_STATS.gather_table_stats(USER, 'T1', cascade => TRUE);
Get information about the index.
- Code: Select all
SET LINESIZE 120
SELECT index_name,
blevel,
leaf_blocks,
distinct_keys,
avg_leaf_blocks_per_key AS avg_lbpk,
avg_data_blocks_per_key AS avg_dbpk,
clustering_factor
FROM user_indexes
ORDER BY index_name;
INDEX_NAME BLEVEL LEAF_BLOCKS DISTINCT_KEYS AVG_LBPK AVG_DBPK CLUSTERING_FACTOR
------------------------------ ---------- ----------- ------------- ---------- ---------- -----------------
T1_NUM_IDX 2 799 400000 1 1 2453
T1_PK 2 750 400000 1 1 2453
T1_STR_IDX 2 1666 398144 1 1 77982
SQL>
SELECT segment_name,
blocks
FROM user_segments
WHERE segment_type = 'INDEX'
ORDER BY segment_name;
SEGMENT_NAME BLOCKS
--------------------------------------------------------------------------------- ----------
T1_NUM_IDX 896
T1_PK 896
T1_STR_IDX 1792
SQL>
Not Reusing Index KeysDelete 100,000 rows (25%) of table and repopulate using different keys to those that were deleted (1 to 100,000).
- Code: Select all
DELETE FROM t1 WHERE id BETWEEN 1 AND 100000;
COMMIT;
BEGIN
-- row-by-row insert rather than bulk on purpose.
FOR i IN 400001 .. 500000 LOOP
INSERT INTO t1 (id, num, str, description)
VALUES (i, i, TO_CHAR(i), 'Description for ' || TO_CHAR(i));
END LOOP;
COMMIT;
END;
/
EXEC DBMS_STATS.gather_table_stats(USER, 'T1', cascade => TRUE);
Get information about the index.
- Code: Select all
SET LINESIZE 120
SELECT index_name,
blevel,
leaf_blocks,
distinct_keys,
avg_leaf_blocks_per_key AS avg_lbpk,
avg_data_blocks_per_key AS avg_dbpk,
clustering_factor
FROM user_indexes
ORDER BY index_name;
INDEX_NAME BLEVEL LEAF_BLOCKS DISTINCT_KEYS AVG_LBPK AVG_DBPK CLUSTERING_FACTOR
------------------------------ ---------- ----------- ------------- ---------- ---------- -----------------
T1_NUM_IDX 2 999 500000 1 1 3075
T1_PK 2 937 500000 1 1 3075
T1_STR_IDX 2 2092 497536 1 1 97489
SQL>
SELECT segment_name,
blocks
FROM user_segments
WHERE segment_type = 'INDEX'
ORDER BY segment_name;
SEGMENT_NAME BLOCKS
--------------------------------------------------------------------------------- ----------
T1_NUM_IDX 1152
T1_PK 1024
T1_STR_IDX 2176
SQL>
Conclusions:
- If the data loaded into an indexed column is similar to the previously deleted data, the index will not alter drastically.
- If the data loaded is different, the affect on the index can be substantial.
- Unique and non-unique indexes are different, but react similarly (in terms of proportions).
- Indexes on VARCHAR2 and NUMBER columns are different, but react similarly (in terms of proportions).
- Changes to clustering factor and unique keys should be considered.
In total, having a plan to do the same maintenance scheme for every index in your system is a waste of resources. Monitor your indexes and only do COALESE and REBUILD operations on those that need them.
Cheers
Tim...