Программирование >>  Oracle 

1 ... 244 245 246 [ 247 ] 248 249 250 ... 469


Фрагментация 1151

7 PARTITION fy 1999 VALUES LESS THAN

8 (to date(01-jan-2000,dd-mon-yyyy)),

9 PARTITION fy 2000 VALUES LESS THAN

10 (to date(Ol-jan-2001,dd-mon-yyyy)),

11 PARTITION the rest VALUES LESS THAN

12 (maxvalue)

13 )

14 /

Table created.

tkyte@TKYTE816> insert into partitioned partition(fy 1999)

2 select to date(31-dec-1999)-mod(rownum,360), object id

3 from all objects

21914 rows created.

tkyte@TKYTE816> insert into partitioned partition(fy 2000)

2 select to date(31-dec-2000)-mod(rownum,360), object id

3 from all objects

21914 rows created.

tkyte@TKYTE816> create index partitioned idx local

2 on partitioned(id)

3 LOCAL

4 / Index created.

tkyte@TKYTE816> create index partitioned idx global

2 on partitioned (timestamp)

3 GLOBAL

4 / Index created.

Итак, мы создали таблицу хранилища данных . Данные фрагментированы по финансовому году; оперативно доступны данные за последние два года. По этой таблице создано два фрагментированных индекса; один - как LOCAL, а другой - как GLOBAL. Обратите внимание, что я оставил пустой фрагмент, THE REST, в конце таблицы. Это поможет быстро добавлять новые данные. Предположим, очередной финансовый год закончился, и необходимо сделать следующее.

1. Удалить данные за самый давний финансовый год. Эти данные не теряются, они просто считаются устаревшими и архивируются.

2. Добавить данные за последний финансовый год. Для их загрузки, преобразования, индексирования и т.д. потребуется определенное время. Хотелось бы, чтобы эти действия не влияли на доступность остальных данных.

Итак, можно выполнить следующее:

tkyte@TKYTE816> create table fy 1999 (timestamp date, id int) ;

Table created.



1152 Глава 14

tkyte@TKYTE816> create index fy 1999 idx on fy 1999(id)

2 / Index created.

tkyte@TKYTE816> create table fy 2001 (timestamp date, id int) ; Table created.

tkyte@TKYTE816> insert into fy 2001

2 select to date(31-dec-2001)-mod( rownum,360), object id

3 from all objects

21922 rows created.

tkyte@TKYTE816> create index fy 2001 idx on fy 2001(id) nologging

2 / Index created.

Здесь я создал новую пустую таблицу- оболочку и индекс для самых старых данных. Преобразуем текущий полный фрагмент в пустой и создадим полную таблицу с данными фрагмента FY 1999. Кроме того, я заранее выполнил все необходимые действия по подготовке данных для фрагмента FY 2001. Речь идет о проверке достоверности данных, преобразовании и любых других сложных действиях по их подготовке.

Теперь все готово изменения актуальных данных:

tkyte@TKYTE816> alter table partitioned

2 exchange partition fy 1999

3 with table fy 1999

4 including indexes

5 without validation

Table altered.

tkyte@TKYTE816> alter table partitioned

2 drop partition fy 1999

Table altered.

Вот и все, что необходимо сделать для удаления устаревших данных. Мы превратили фрагмент в отдельную целую таблицу, а пустую таблицу - во фрагмент. Это бхло просто изменение словаря данных, никаких больших объемов ввода-вывода. Теперь можно экспортировать эту таблицу (возможно, с помощью перемещаемого табличного пространства) из базы данных с целью архивирования. При необходимости ее очень легко присоединить снова.

Теперь добавим новые данные:

tkyte@TKYTE816> alter table partitioned

2 split partition the rest

3 at (to date(01-jan-2002,dd-mon-yyyy))

4 into (partition fy 2001, partition the rest)

Table altered.



Фрагментация 1153

tkyte@TKYTE816> alter table partitioned

2 exchange partition fy 2 0 01

3 with table fy 2001

4 including indexes

5 without validation

Table altered.

Изменение словаря данных б1ло выполнено моментально. Отделение пустого фрагмента требует очень мало времени, поскольку данных там никогда не было и не будет. Вот зачем я поместил пустой фрагмент в конец таблицы, - чтобы упросить отделение. Затем вновь созданный пустой фрагмент заменяется всей таблицей, а таблица - пус-т]м фрагментом. Новые данные оперативно доступны.

Однако, если посмотреть на индексы, оказывается:

tkyte@TKYTEi816> select indexname, status from userindexes; INDEX NAME STATUS

FY 1999 IDX VALID

FY 2001 IDX VALID

PARTITIONED IDX GLOBAL UNUSABLE PARTITIONED IDX LOCAL N/A

Глобально фрагментированный индекс после этих действий, несомненно, недоступен. Поскольку каждый фрагмент индекса может указывать на фрагмент таблицы, и мы удалили один фрагмент, и добавили другой, индекс некорректен. В нем есть записи, ссылающиеся на удаленный фрагмент. В нем нет записей, сстлающихся на добавленный фрагмент. Запрос, использующий этот индекс, не будет выполнен:

tkyte@TKYTE816> select count(*)

2 from partitioned

3 where timestamp between sysdate-50 and sysdate;

select count(*)

ERROR at line 1:

ORA-01502: index TK.PARTITIONED IDX GLOBAL or partition of such index is in unusable state

Можно установить параметр SKIP UNUSABLE INDEXES=TRUE, но тогда мы теряем повышение производительности, которое обеспечивал индекс (это работает в Oracle 8.1.5 и более поздних версиях; до этого оператор SELECT все равно пытался бы использовать индекс, помеченный как UNUSABLE). Этот индекс надо пересоздать, чтобы снова обеспечить возможность использования данных. Процесс перемещения окна, который до сих пор происходил без задержек, теперь будет выполняться очень долго, пока не будет пересоздан глобальный индекс. Придется просмотреть все данные и полностью пересоздать индекс по данным таблицы. Если таблица имеет размер в сотни гигабайт, для этого потребуются существенные ресурсы.

Любая операция с фрагментом таблицы сделает невозможным использование глобально фрагментированного индекса. Если необходимо перенести фрагмент на другой диск, все глобально фрагментированные индексы надо пересоздавать (для локально фрагмен-



1 ... 244 245 246 [ 247 ] 248 249 250 ... 469

© 2006 - 2025 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки.
Яндекс.Метрика