-- blevel не должен быть больше, чем 3-4
-- clustering_factor- если он превышает 50% от числа строк таблицы, то индекс
можно перестроить (а лучше перезалить таблицу с сортировкой согласно этому индексу)
-- этот % показывает поле proc_clust
SELECT owner,index_name,table_name,blevel,leaf_blocks,distinct_keys, avg_data_blocks_per_key avg_data_blocks,clustering_factor cl_factor, num_rows,decode(num_rows,0,0,clustering_factor*100/num_rows) proc_clust, avg_leaf_blocks_per_key avg_leaf_blocks FROM dba_indexes WHERE owner ='UBC' AND blevel IS NOT null ORDER BY blevel desc,leaf_blocks desc
Более точную информацию о конкретном индексе можно получить, если его проанализировать таким образом.
ANALYZE INDEX index_name VALIDATE STRUCTURE;
результаты анализа записываются в однострочную таблицу,
которую можно просмотреть так :
SELECT * FROM INDEX_STATS
Для того, чтобы просмотреть расширенную информацию по всем индексам, нужно создать вспомогательную таблицу
CREATE TABLE ind_stats AS SELECT * FROM sys.INDEX_STATS;
и пропустить в базе ( очень желательно в нерабочее время ) такой анонимный блок:
DECLARE CURSOR c_ind IS SELECT 'analyze index '||owner||'.'||index_name||' validate structure' txt_sql FROM DBA_INDEXES WHERE owner IN ('UBC') -- список нужных владельцев индексов ORDER BY owner,index_name; BEGIN DBMS_OUTPUT.PUT_LINE(SYSDATE); FOR cind IN c_ind LOOP begin toad.execute_immediate(cind.txt_sql); -- !!! убедитесь, что это у вас есть !!!
INSERT INTO apt.ind_stats SELECT * FROM sys.INDEX_STATS;
exception WHEN others THEN -- в случае, если индекс занят, вывести сообщение DBMS_OUTPUT.PUT_LINE( cind.txt_sql);END; END LOOP; DBMS_OUTPUT.PUT_LINE(SYSDATE); END;
Тут надо обратить внимание, что процедура execute_immediate появляется только после установки TOAD.
Для Oracle 8,9 можно воспользоваться родной аналогичной командой.
Ну и проматриваем результаты с акцентом на наиболее важные поля:
SELECT NAME, lf_rows, height, del_lf_rows, pct_used FROM apt.ind_stats
ORDER BY height DESC, lf_rows DESC
желательно пересоздать индекс (опять таки лучше в нерабочее время :):
ALTER INDEX your_name_index REBUILD tablespace USERS
и сделать стандартный analyze:
ANALYZE INDEX your_name_index compute statistics
Полный перечень столбцов во вьюшке
HEIGHT | количество уровней индексного дерева |
BLOCKS | общее число блоков в индексе |
NAME | имя индекса |
LF_ROWS | Число строк листьев (значений в индексе) |
LF_BLKS | Число блоков занятых листьями в B-дереве |
LF_ROWS_LEN | Сумма длин всех строк листьев |
LF_BLK_LEN | Сумма длин всех строк в ветвях В-дерева ? |
BR_ROWS | Число строк ветвей в B-дереве ( number of branch rows) |
BR_BLKS | Число блоков ветвей в B-дереве (number of branch blocks in the b-tree) |
BR_ROWS_LEN | Сумма длин всех блоков ветвей в B-дереве ( sum of the lengths of all the branch blocks in the b-tree ) |
BR_BLK_LEN | Занятое пространство в блоке ветвей (useable space in a branch block) |
DEL_LF_ROWS | Число удаленных строк листьев в индексе |
DEL_LF_ROWS_LEN | Общая длина удаленных строк в индексе |
DISTINCT_KEYS | число уникальных значений в индексе (может включать строки, которые были удалены) |
MOST_REPEATED_KEY | Максимальное число повторений ключа (может включать строки, которые были удалены) |
BTREE_SPACE | Общая память, распределенная B-дереву |
USED_SPACE | Занятая память в B-дереве |
PCT_USED | Процент используемой памяти в B-дереве |
ROWS_PER_KEY | Среднее число строк на значение ключа с учетом повторений |
BLKS_GETS_PER_ACCESS | Ожидаемое количество согласованных чтений блоков на строку в предположении, что строка выбирается произвольно. Используется для расчета количества согласованных чтений, которые должны быть выполнены при просмотре индекса. |
SELECT i.TABLE_NAME,i.index_name,si.bytes size_ind, st.bytes size_tab FROM dba_indexes i, (SELECT segment_name, sum(bytes) bytes FROM dba_extents WHERE owner='UBC' AND segment_type='INDEX' GROUP BY segment_name) si, (SELECT segment_name, sum(bytes) bytes FROM dba_extents WHERE owner='UBC' AND segment_type='TABLE' GROUP BY segment_name) st WHERE i.index_name=si.segment_name AND st.segment_name=i.TABLE_NAME AND st.bytes < si.bytes
Индексы - кандидаты на изменение параметра PCTFREE.
Если индекс основан на столбце, который заполняется только строго по возростанию и не изменяется, например на основе последовательности, то его можно пересоздать с параметром PCTFREE=0.
Такие индексы можно поискать среди уникальных индексов на основе одного столбца :
SELECT di.index_name, di.table_name, di.pct_free FROM DBA_INDEXES di, (SELECT index_name, table_name, count(*) FROM DBA_IND_COLUMNS GROUP BY index_name, table_name HAVING count(*)=1) dc WHERE di.UNIQUENESS='UNIQUE' AND di.table_owner='UBC' AND di.index_name=dc.index_name AND di.table_name=dc.table_name
Изменить pct_free можно так:
ALTER INDEX name_index REBUILD tablespace USERS_S PCTFREE 0;
Этот же запрос можно использовать и для поиска сжатых уникальных индексов из одного столбца (нонсенс, но изредка бывает :) Для этого к запросу добавить
and compression='ENABLED'
Поиск индексов - кандидатов на перенос в таблспэйс для миниатюрных объектов базы данных (в моём случае до 40-64 К)
SELECT 'alter index '|| index_name||' rebuild tablespace users_ro_s STORAGE (INITIAL 4K);', table_name, distinct_keys, num_rows, bytes/1024 FROM USER_INDEXES i, dba_segments s WHERE i.tablespace_name<>'USERS_RO_S' AND blevel<2 AND num_rows<300 and segment_name=index_name
Из полученного результата нужно отсеять индексы из временных и индекс-организованных
таблиц.
Индексы с малой избирательной способностью:
SELECT index_name, distinct_keys, num_rows, to_char(decode(num_rows,0,1,num_rows)/decode(distinct_keys,0,1,distinct_keys),'999G999D00') rows_on_keys FROM user_indexes WHERE uniqueness<>'UNIQUE' and decode(num_rows,0,1,num_rows)/decode(distinct_keys,0,1,distinct_keys)>2 ORDER BY decode(num_rows,0,1,num_rows)/decode(distinct_keys,0,1,distinct_keys) desc
Чем меньше уникальных значений в индексе и чем больше на одно уникальное значение в индексе приходится строк в таблице, тем более бесполезнее становится индекс, так как избирательность его при этом уменьшается. Эти индексы - кандидаты на удаление, хотя с каждым индексом нужно решать вопрос индивидуально, особенно для больших таблиц с составными индексами.
Эти индексы, если они всё же нужны, также являются кандидатами на сжатие