27 июня 2012

IOT, фактор кластеризации

Вывод: IOT-таблицы неоходимо проектировать и заполнять так, чтобы обращения к сегменту OVERFLOW происходили редко. Если мы выносим в сегмент OVERFLOW поля, к которым обращаемся всегда или часто, то при большом объёме данных скорость её чтения по мере заполнения будет падать лавинообразно. В таком случае IOT-таблица вырождается в обычную HEAP и её лучше было бы с самого начала создавать как HEAP.


Вот как это обнаружил...
Как известно, для B-tree индексов одним из параметров, которые определяются на сборе статистики, является фактор кластеризации (clustering factor). Этот числовой параметр показывает, сколько раз приходилось читать другой блок таблицы при переходе к следующему значению индекса.

Так вот, этот параметр оказался ненулевым для некоторых IOT-таблиц. Это стало для меня сюрпризом. Об этом не написано в документации.
Потребовалось некоторое время, чтобы сообразить, что имеется ввиду кластеризация сегмента OVERFLOW по отношению к основному сегменту IOT-таблиц.

Этот имеет практическое применение. Для больших таблиц время полного просмотра (с извлечением полей, которые находятся в OVERFLOW) и время сбора статистики будет расти лавинообразно и может стать неприемлемым -- сессия "зависнет" (так это и было обнаружено).
Большой таблицей здесь можно считать такую, которая не помещается полностью в буферный кэш.
Это связано с тем, что при переходе к следующему значению индекса в IOT сервер вынужден снова и снова читать блоки OVERFLOW, которые уже читал ранее. Пока блоки есть в кэше -- все нормально, но при достижении некоторого порога -- начнётся лавина.

На тестовом экземпляре при увеличении количества строк в 4 раза время сбора статисики увеличилось с 70 секунд до 2222 секунд (в 31 раз). Полный просмотр даёт тот-же результат

Как такие таблицы найти ?
select * from ALL_INDEXES
where INDEX_TYPE = 'IOT - TOP' and CLUSTERING_FACTOR > 0
Небольшое значение CF приемлемо.
Также, необходимо поискать в DBA_SEGMENTS размеры сегментов -- основного и OVERFLOW.

Как исправить ?
Фактор кластеризации и сама таблица и её OVERFLOW улучшаются (реорганизуются) если выполнить

alter table <iot_table_name> move
alter table <iot_table_name> move overflow

При этом IOT–таблицу НЕ придётся переиндексировать, поскольку B–tree индексы IOT–таблиц строятся на логических rowid, которые не изменяются при MOVE, в отличие от физических.

После подобной операции MOVE время сбора статистики и полных просмотров IOT–таблицы сокращается (возможно, очень существенно, в 5 раз, но зависит от данных).

16 июня 2012

SEG$


Мой некоторый опыт по этой таблице

Хронология такова:

Событие 1.

Пытаюсь дропнуть tablespace, получаю ORA-01561: failed to remove all objects in the tablespace specified
Хотя там точно ничего нет. DBA_SEGMENTS и DBA_EXTENTS пусты для этого тэйблспейса и его датафайлов.
Данная проблема решена и описана в http://www.sql.ru/forum/actualthread.aspx?tid=243553
Именно так её и решил -- удалил 2 записи из SEG$, тэйблспейс дропнулся
Но, отметил для себя, что такая проблема может быть не одна -- надо будет как-то поискать подобные проблемы. При этом DBV говорит, что все ок, backup validate check logical -- тоже ок

Событие 2.


Восстанавливался из бэкапа, сделал RESTORE, RECOVERY until SCN, прошло нормально.
Но в итоге получил более 100 corrupted блоков. Тип повреждения--NOLOGGING, поэтому, не страшно, но исправлять надо.

Часть блоков была занята данными -- поправил путем move на другое табличное пространство и обратно. Починилось.

Но некоторая часть битых блоков, согласно DBA_EXTENTS, была распределена под такой сегмент, для которого _не_ существовало таблицы.
А дело было в чем.
Это была IOT-таблица.
Я их именую определенным образом, если таблица называется QDEMANDS, то её первичный ключ -- QDEMANDS_PKIOT.
Я вижу экстент сегмента QDEMANDS_PKIOT, пробую подвинуть таблицу
alter table move QDEMANDS tablespace <другое TS>
вижу, что такой таблицы нет. Я предположил, что опять столкнулся с ситуацией, которую описал в "событии 1". Ну и решил её таким же способом. Я жестоко ошибался.
Таблица от этого сегмента называлась QDEMAND, я её переименовывал.

При обычном экспорте на этой таблице получил EXP-00003: no storage definition found for segment(number, number).
Интернет рекомендует решать эту проблему вот так
http://www.dbacorner.com/2007/02/exp-00003-no-storage-definition-found.html

Я посчитал данный метод опасным.
Восстановил удалённую строку из SEG$ путём flashback

select * from SEG$ as of timestamp systimestamp - numtodsinterval (1, 'HOUR')
minus
select * from SEG$

Там оказалось 6 строк, свою удалённую я узнал, и сделал её insert обратно в SEG$
Проблему экспорта решил, таблицу помувал туда-сюда и её блоки перестали быть CORRUPTED NOLOGGING

Мощная вещь -- flashback

Не лишне будет напомнить, что самостоятеьно редактировать SEG$ -- последнее дело. Надо в саппорт обращаться
Здесь буду писать интересные фишки, которые нашел в Oracle Database, как решал некоторые проблемы