
Март 2005
Профессионалу администратору
Аруп Нанда
Oracle Database 10g:
20 наиболее привлекательных для АБД возможностей
(Oracle Database 10g: The Top 20 Features for DBAs
by Arup Nanda)
Часть VII
Источник: журнал Oracle Magazine,
OTN Technical Articles ( http://www.oracle.com/oramag/webcolumns/windex.html),
http://otn.oracle.com/pub/articles/10gdba/index.html
В течение 20 недель Arup Nanda, “Лучший АБД 2003 года” по версии журнала Oracle Magazine, рассказывал о наиболее, по его мнению, привлекательных для администраторов баз данных возможностях Oracle Database 10g.
[От редакции OM/RE: мы продолжаем публикацию переводов этих заметно окрашенных индивидуальной авторской
интонацией небольших по объему заметок, но удивительно емких по содержаниею и точных по существу рассматриваемых вопроcов.
В каждом выпуске журнала предполагается по две-три “недели” от Arup Nanda. В этот раз мы предлагаем
вниманию читателей
"Неделю 15" и "Неделю 16".]
План публикаций
Неделя 15
Управление Сегментами
(Segment Management)
Эффективное управление памятью сегментов в Oracle Database10g возвращает впустую распределенное пространство, оперативно реорганизует таблицы и дает оценки их разрастания.
Недавно меня попросили оценить RDBMS, который конкурирует с Oracle Database. На презентации продавца самой большой особенностью, которая преподносилась для собравшихся как "из ряда вон выходящая" ("wow"), была ее поддержка оперативной реорганизации, то есть, продукт мог перемещать блоки данных, формируя оперативный более компактный эквивалент сегментов, не затрагивая работающих пользователей.
В то время Oracle не предлагал такую возможность в Oracle9i Database. Но сегодня в Oracle Database 10g Вы можете легко востребовать распределенное впустую пространство и интерактивно уплотнить объекты - стоит только захотеть.
Перед исследованием этой возможности давайте, однако, посмотрим на "традиционный" подход к задаче.
Сегодняшняя практика
Рассмотрим, скажем, табличный сегмент, блоки в котором заполнены, как показано в Рисунке 1. В ходе нормальных операций некоторые строки удаляются, как показано в Рисунке 2. Теперь мы имеем много впустую распределенного пространства:
- между предыдущим концом таблицы и последним наполненным в данный момент блоком и
- внутри некоторых блоков, в которых остались и не были удалены какие-то строки.
Рисунок 1: Распределенные для таблицы блоки. Строки обозначены серыми квадратами.
Oracle не отдает это пространство для использования другими объектами по той простой причине, что оно зарезервировано для новых вставок или предназначено для обеспечения расширения существующих строк. Самая дальняя отметка занятого пространства известна как HWM (High Water Mark - отметка наивысшего подъема, паводка), как показано на Рисунке 2.
Рисунок 2: Блоки после [“серых”] строк были опустошены; HWM остается неизменным.
Однако, в этом подходе есть две основные проблемы:
- когда пользователь заказывает полный просмотр таблицы, Oracle должен просмотреть сегмент полностью до HWM, даже при том, что ничего не находит. Эта задача увеличивает полное время просмотра (сканирования) таблицы.
- когда строки вставляются прямым образом, например, посредством вставки Direct Load (Прямая Загрузка) - вставка с подсказкой APPEND (добавить в конец), или посредством утилиты SQL*Loader с опцией direct path (прямой путь) блоки данных помещаются непосредственно за HWM. Пространство ниже этой отметки остается неиспользуемым.
В Oracle9i и ранее можно востребовать пространство, удаляя и воссоздавая таблицу, а затем перезагружая в нее данные; или же перемещая таблицу в другое табличное пространство, используя команду ALTER TABLE MOVE [скорее всего, неточность автора. Он явно подразумевает последовательность действий import-drop-create-export с одновременной межблочной дефрагментацией таблицы. Команда ALTER TABLE MOVE используется как раз для оперативной реорганизации, о которой говорится несколькими словами позже – прим. науч.ред.]. Оба этих процесса должны происходить автономно. Альтернативно, можно воспользоваться возможностью оперативной реорганизации таблицы, но это требует двойного, как минимум, пространства, занимаемого существующей таблицей.
В 10g эта задача стала тривиальной. Теперь можно сжать сегменты, таблицы и индексы, востребовав свободные блоки, и отдать их базе данных для другого использования, но при условии, что ASSM (Automatic Segment Space Management – механизм Автоматического Управления Пространством Сегментов) может работать в этом табличном пространстве. Давайте посмотрим, как это происходит.
Путь Управления Сегментами в 10g
Предположим, что Вы имеете таблицу BOOKINGS (ЗАКАЗЫ), которая содержит оперативные заказы, поступающие через web-сайт. После того, как заказ выполнен, он сохраняется в архивной таблице BOOKINGS_HIST, а его строка удаляется из BOOKINGS. Время между поступлением и выполнение заказа существенно разнится по клиентам, так что много строк вставляется выше табличной HWM, потому что нет достаточного пространства из-за неудаленных строк.
Теперь Вы должны востребовать впустую распределенное пространство. Сначала нужно точно узнать, сколько пространства простаивает в том сегменте, который может быть реорганизован. Поскольку он принадлежит табличному пространству с ASSM-поддержкой, Вы должны использовать процедуру SPACE_USAGE из пакета DBMS_SPACE, как показано ниже.
declare
l_fs1_bytes number;
l_fs2_bytes number;
l_fs3_bytes number;
l_fs4_bytes number;
l_fs1_blocks number;
l_fs2_blocks number;
l_fs3_blocks number;
l_fs4_blocks number;
l_full_bytes number;
l_full_blocks number;
l_unformatted_bytes number;
l_unformatted_blocks number;
begin
dbms_space.space_usage(
segment_owner => user,
segment_name => 'BOOKINGS',
segment_type => 'TABLE',
fs1_bytes => l_fs1_bytes,
fs1_blocks => l_fs1_blocks,
fs2_bytes => l_fs2_bytes,
fs2_blocks => l_fs2_blocks,
fs3_bytes => l_fs3_bytes,
fs3_blocks => l_fs3_blocks,
fs4_bytes => l_fs4_bytes,
fs4_blocks => l_fs4_blocks,
full_bytes => l_full_bytes,
full_blocks => l_full_blocks,
unformatted_blocks => l_unformatted_blocks,
unformatted_bytes => l_unformatted_bytes
);
dbms_output.put_line(' FS1 Blocks = '||l_fs1_blocks||' Bytes = '||l_fs1_bytes);
dbms_output.put_line(' FS2 Blocks = '||l_fs2_blocks||' Bytes = '||l_fs1_bytes);
dbms_output.put_line(' FS3 Blocks = '||l_fs3_blocks||' Bytes = '||l_fs1_bytes);
dbms_output.put_line(' FS4 Blocks = '||l_fs4_blocks||' Bytes = '||l_fs1_bytes);
dbms_output.put_line('Full Blocks = '||l_full_blocks||' Bytes = ||l_full_bytes);
end;
/
Ответ таков:
FS1 Blocks = 0 Bytes = 0
FS2 Blocks = 0 Bytes = 0
FS3 Blocks = 0 Bytes = 0
FS4 Blocks = 4148 Bytes = 0
Full Blocks = 2 Bytes = 16384
Выход показывает, что имеется 4 148 блоков со свободным на 75-100% пространством (FS4); нет других доступных свободных блоков; есть только 2 полных блока. Эти 4 148 блоков могут быть возвращены.
Далее Вы должны убедиться, что таблица допускает перемещение строк. Если это не так, то Вы можете разрешить это действие или командой:
alter table bookings enable row movement;
или посредством Enterprise Manager 10g на странице Administration. Вы должны также убедиться, что на этой таблице заблокированы все триггеры, использующие идентификаторы (rowid) записей, потому что при перемещении строк могут измениться их идентификаторы (rowids).
Наконец, Вы можете реорганизовать существующие строки таблицы следующим образом:
alter table bookings shrink space compact;
Эта команда перераспределяет строки в блоках, как показано в Рисунке 3, приводя к большему числу свободных блоков ниже отметки HWM. Но самая граница HWM не нарушается.
Рисунок 3: Блоки таблицы после реорганизации строк.
После этой операции давайте посмотрим на изменения в использовании пространства. Применяя PL/SQL-блок, показанный на первом шаге, можно увидеть, как теперь организованы блоки:
FS1 Blocks = 0 Bytes = 0
FS2 Blocks = 0 Bytes = 0
FS3 Blocks = 1 Bytes = 0
FS4 Blocks = 0 Bytes = 0
Full Blocks = 2 Bytes = 16384
Обратите внимание на важное изменение: число блоков FS4 (со свободным пространством в 75-100 %) теперь 0, а было 4 148. Мы также видим увеличение блоков FS3 (свободное пространство в 50-75 %) с 0 до 1. Однако, поскольку HWM не была сброшена, полная занятость пространства остается той самой. Мы можем проверить объем используемого пространства:
SQL> select blocks from user_segments where segment_name = 'BOOKINGS';
BLOCKS
---------
4224
Число блоков, занятых в таблице, - 4,224, то есть, то же самое, поскольку HWM не изменялась по сравнению с первоначальным значением. Вы можете переместить HWM на более низкую позицию и востребовать пространство командой:
alter table bookings shrink space;
Обратите внимание, что не присутствует фраза COMPACT. Эта операция возвратит неиспользованные блоки базе данных и снизит HWM. Вы можете проверить это, оценив объем пространства, распределенного таблице:
SQL> select blocks from user_segments where segment_name = 'BOOKINGS';
BLOCKS
----------
8
Число блоков уменьшилось с 4 224 до 8; все неиспользованное в таблице пространство было возвращено табличному пространству для задействования в других сегментах, как показано в Рисунке 4.
Рисунок 4: Свободные блоки возвращены базе данных после сокращения.
Эта операция сжатия происходит полностью в оперативном (online) режиме и не затрагивает пользователей.
Также одной командой можно уплотнить индексы таблицы:
alter table bookings shrink space cascade;
Оперативная команда сжатия является мощным средством для востребования впустую распределенного пространства и сброса HWM. Я считаю, что последнее - сброс HWM, - самым полезным результатом этой операции, потому что это улучшает выполнение полного сканирования таблицы.
Нахождение кандидатов на сжатие
Перед выполнением оперативного сжатия следует узнать, какие сегменты могут быть сжаты в наибольшей степени. Можно просто воспользоваться встроенной функцией verify_shrink_candidate из пакета dbms_space. Выполните этот PL/SQL-код, чтобы проверить, может ли сегмент быть сокращен, скажем, до 1 300 000 байтов:
begin
if (dbms_space.verify_shrink_candidate
('ARUP','BOOKINGS','TABLE',1300000)
) then
:x := 'T';
else
:x := 'F';
end if;
end;
/
PL/SQL procedure successfully completed.
SQL> print x
X
--------------------------------
T
Но если задать меньшее число для итогового сжатия объекта, скажем 3,000, то:
begin
if (dbms_space.verify_shrink_candidate
('ARUP','BOOKINGS','TABLE',30000)
) then
:x := 'T';
else
:x := 'F';
end if;
end;
и значение переменной “x” устанавливается в 'F', означая, что таблица не может быть сокращена до 3 000 байтов.
Предположения о потребностях пространства для индексов
Теперь, скажем, Вы ставите задачу создания индекса или даже набора индексов на таблице. Помимо обычных структурных элементов, таких как: столбцы и ограничения уникальности, самым важным вопросом, который нужно решить, является ожидаемый размер индекса. Нужно гарантировать, что табличное пространство имеет достаточно места, чтобы вместить новый индекс.
В Oracle9i Database и ранее многие АБД использовали различные инструментальные средства от электронных таблиц до самостоятельных программ, чтобы оценить размер будущего индекса. В 10g с помощью пакета DBMS_SPACE эта задача стала чрезвычайно простой. Давайте увидим его в действии.
Нам задали создать индекс на столбцах booking_id и cust_name таблицы BOOKINGS. В каком объеме пространства нуждается индекс? Все, что нужно сделать, это выполнить следующий PL/SQL-скрипт.
declare
l_used_bytes number;
l_alloc_bytes number;
begin
dbms_space.create_index_cost (
ddl => 'create index in_bookings_hist_01 on bookings_hist '||
'(booking_id, cust_name) tablespace users',
used_bytes => l_used_bytes,
alloc_bytes => l_alloc_bytes
);
dbms_output.put_line ('Used Bytes = '||l_used_bytes);
dbms_output.put_line ('Allocated Bytes = '||l_alloc_bytes);
end;
/
Ответ таков:
Used Bytes = 7501128 [будет использовано байтов - ред.]
Allocated Bytes = 12582912 [всего потребуется байтов - ред.]
Предположим, что Вы захотите использовать некоторые параметры, которые потенциально увеличат размер индекса, например, определив параметр INITRANS 10.
declare
l_used_bytes number;
l_alloc_bytes number;
begin
dbms_space.create_index_cost (
ddl => 'create index in_bookings_hist_01 on bookings_hist '||
'(booking_id, cust_name) tablespace users initrans 10',
used_bytes => l_used_bytes,
alloc_bytes => l_alloc_bytes
);
dbms_output.put_line ('Used Bytes = '||l_used_bytes);
dbms_output.put_line ('Allocated Bytes = '||l_alloc_bytes);
end;
/
Ответ таков:
Used Bytes = 7501128 [будет использовано байтов - ред.]
Allocated Bytes = 13631488 [всего потребуется байтов - ред.]
Обратите внимание на увеличение числа требуемых байтов, вследствие определения более высокого значения INITRANS. Используя этот подход, Вы легко определите требования индекса к объему пространства памяти.
Однако, следует предупредить о двух существенных опасностях. Во-первых, этот процесс применяется только к табличным пространствам с включенной опцией SEGMENT SPACE MANAGEMENT AUTO (автоматическое управление пространством сегмента). Во вторых, пакет вычисляет расчетный размер индекса по табличной статистике. Следовательно, очень важно иметь относительно свежую статистику по таблицам. И будьте осторожны: отсутствие табличной статистики не приведет к ошибке при использовании пакета, но приведет к неправильному результату.
Оценка размера таблицы
Предположим, что имеется таблица BOOKINGS_HIST, у которой средняя длина строки 30, число строк 30,000 и значение параметра PCTFREE 20. Что произойдет, если Вы захотите увеличить значение параметра PCT_FREE до 30? Как таблица увеличит в размере? Поскольку 30 по сравнению с 20 - это 10%-ое увеличение [резервной свободной памяти в каждом блоке при начальной загрузке блока – ред.], увеличится ли размер таблицы на 10%? Вместо обращения к экстрасенсу, лучше спросим процедуру CREATE_TABLE_COST из пакета DBMS_SPACE. Приведем пример, как Вы можете оценить размер:
declare
l_used_bytes number;
l_alloc_bytes number;
begin
dbms_space.create_table_cost (
tablespace_name => 'USERS',
avg_row_size => 30,
row_count => 30000,
pct_free => 20,
used_bytes => l_used_bytes,
alloc_bytes => l_alloc_bytes
);
dbms_output.put_line('Used: '||l_used_bytes);
dbms_output.put_line('Allocated: '||l_alloc_bytes);
end;
/
Ответ таков:
Used: 1261568
Allocated: 2097152
Изменив табличный параметр PCT_FREE с 20 до 30, специфицируя
pct_free => 30
мы получаем следующий ответ:
Used: 1441792
Allocated: 2097152
Обратите внимание, что используемое пространство увеличилось с 1,261,568 до 1,441,792, потому что увеличенный PCT_FREE оставляет меньше места для данных пользователя в памяти блока. Увеличение составляет приблизительно 14%, а не 10%, как ожидалось. Используя этот пакет, можно легко вычислить воздействие параметров типа PCT_FREE на объем таблицы, сохраняя ее в этом или перемещая таблицу в другое табличное пространство.
[Прим. А.Бачина – Откровенно говоря, мне не понятно, почему в этом примере не увеличилось распределяемое пространство, ведь параметр PCT_FREE влияет на количество блоков табличного пространства, отводимых сегменту. Больше PCT_FREE - меньше строк в блоке – больше блоков в сегменте при том же числе строк. Но поскольку под рукой нет 10g, я предлагаю нашим читателям произвести проверку этого суждения автора. В любом случае ценность приведенной информации существенно не изменится.]
Предсказание роста сегмента
Сегодня праздничные каникулы, и в гостиницах Acme Hotels ожидается волна запросов. Как АБД, Вы интерпретируете эту ситуацию в плане, можно ли гарантировать наличие достаточного доступного места. Как Вы предскажете использование пространства таблицы?
Достаточно спросить 10g. Вы будете удивлены, как точно и разумно она сделает для Вас это предсказание. Выполним следующий запрос:
select * from
table(dbms_space.OBJECT_GROWTH_TREND
('ARUP','BOOKINGS','TABLE'));
Функция dbms_space.object_growth_trend () возвращает строку в формате PIPELINE, которая может быть отображена преобразованием TABLE(). Ниже представлен выход:
TIMEPOINT SPACE_USAGE SPACE_ALLOC QUALITY
------------------------------ ----------- ----------- ------------
05-MAR-04 08.51.24.421081 PM 8586959 39124992 INTERPOLATED
06-MAR-04 08.51.24.421081 PM 8586959 39124992 INTERPOLATED
07-MAR-04 08.51.24.421081 PM 8586959 39124992 INTERPOLATED
08-MAR-04 08.51.24.421081 PM 126190859 1033483971 INTERPOLATED
09-MAR-04 08.51.24.421081 PM 4517094 4587520 GOOD
10-MAR-04 08.51.24.421081 PM 127469413 1044292813 PROJECTED
11-MAR-04 08.51.24.421081 PM 128108689 1049697234 PROJECTED
12-MAR-04 08.51.24.421081 PM 128747966 1055101654 PROJECTED
13-MAR-04 08.51.24.421081 PM 129387243 1060506075 PROJECTED
14-MAR-04 08.51.24.421081 PM 130026520 1065910496 PROJECTED
Этот листинг явно показывает размеры таблицы BOOKINGS в различные точки времени (столбец TIMEPOINT (тип данных TIMESTAMP)). Столбец SPACE_ALLOC показывает число байтов, распределенных таблице, а в столбце SPACE_USAGE - сколько байтов из них использовалось. Эта информация собиралась каждый день AWR (Automatic Workload Repository - Автоматизированный Репозиторий Рабочей нагрузки (см. Неделю 6 <http://otn.oracle.com/pub/articles/10gdba/10gdba_week6.html> этой серии статей)). В приведенном выше листинге хорошие данные были собраны 9 марта 2004, что показано в столбце QUALITY (качество) - значение "GOOD" (хорошо). Распределенное и используемое пространство в этот день почти совпадают. Однако, во все последующие дни значение этого столбца "PROJECTED" (проекция), указывая, что вычисление пространства проецируется по данным, собранным механизмом AWR, а не полученных непосредственно от сегмента.
Обратите внимание на значения в этом столбце до 9 марта - они все "INTERPOLATED" (интерполяция). Другими словами, значение на самом деле не собиралось или проецировалось, а просто интерполировалось по образцу использования любых доступных данных. Наиболее вероятно, что тогда данные не были доступны и, следовательно, значения должны были быть интерполированы.
Заключение
Благодаря возможности манипулирования на сегментном уровне, теперь имеется детализированный контроль использования пространства в сегменте, что может понадобиться для удаления свободного пространства из таблицы, для реорганизации строк таблицы, чтобы делать ее в оперативном режиме более компактной и многое другое. Эти средства помогают АБД освободиться от стандартных и рутинных задач типа реорганизации таблиц. Возможность оперативного сжатия сегментов особенно полезна в устранении внутренней фрагментации и понижения сегментной отметки HWM, что может значительно уменьшить затраты на полное сканирование таблицы.
Более подробную информацию об операции SHRINK можно получить в ее
секции в книге
Oracle Database SQL Reference. О пакете DBMS_SPACE можно больше узнать в Главе 88 книги PL/SQL Packages and Types Reference. Всесторонний обзор всех новых особенностей управления пространством в Oracle Database 10g можно прочитать в Technical Whitepaper The Self-Managing Database: Proactive Space & Schema Object Management. Наконец, демонстрационная версия управление пространством в Oracle Database 10g доступна в он-лайн
по этому адресу.
Неделя 16
Транспортабельные Табличные пространства
(Transportable Tablespaces)
Транспортабельные табличные пространства теперь переносимы между платформами, что делает более быструю и простую публикацию данных. Добавим, что внешняя загрузка таблиц делает более простой и быстрой задачу перемещения данных с преобразованием.
Как Вы перемещаете данные из одной базы данных в другую? Среди многих методов особенно выделяется механизм транспортабельных табличных пространств. В этом случае берется набор самодостаточных (self-contained) табличных пространств только-для-чтения (read-only), экспортируются только метаданные, копируются на уровне OS (операционной системы) и переносятся на целевую платформу файлы данных только этих табличных пространств и метаданные импортируются в словарь данных - этот процесс известен как plugging (подключение).
Копирование файлов OS вообще намного быстрее, чем другие традиционные средства передвижения данных, типа экспорт/импорт (export/import) или SQL*Loader (утилита Загрузчик). Однако, в базе данных Oracle9i и ранее некоторые ограничения снижают ценность этого решения только до нескольких вариантов, в которых и исходная, и целевая базы данных реализуются на одной и той же самой OS-платформе. То есть, Вы не можете транспортировать табличные пространства между, например, Solaris и HP-UX.
В Oracle Database 10g, это ограничение устранено: теперь можно транспортировать табличные пространства между платформами, если идентичен порядок байтов в OS. Детальное обсуждение порядка байтов лежит вне границ этой статьи, но удовлетворения любопытства скажу, что некоторые операционные системы, включая Windows, хранят много байтовые двоичные данные, начиная с младшего байта в самом младшем адресе памяти; поэтому, такую систему называют little endian (прямой порядок байтов - остроконечник) [Прим.А.Бачина: little и big endian - прямой – соответственно - обратный порядок байтов (формат для хранения и передачи двоичных данных, при котором младший (наименее значимый) - соответственно - старший (наиболее значимый) бит (или байт) передается сначала; термин происходит от "остроконечников"/"тупоконечников" из "Путешествия Гулливера" Джонатана Свифта – словарь Lingvo]. Наоборот, другие OS, включая Solaris, хранят в самых младших адресах памяти наиболее значимые байты, и поэтому называются big endian (обратный порядок байтов - тупоконечник). Когда big-endian система попробует читать данные из системы little-endian, потребуется процесс конверсии, иначе другой порядок байтов приведет к неправильной интерпретации прочитанных данных. (Детальное объяснение порядка байтов можно прочесть в превосходной статье "Introduction to Endianness"<http://www.netrino.com/Publications/Glossary/Endianness.html> в январском выпуске 2002г. журнала "Embedded Systems Programming” - примечание автора.) При транспортировке табличных пространств между платформами того же самого порядка байтов никакое преобразование не требуется.
Как узнать, какие операционные системы, какому порядку байтов следуют? Не надо догадываться или предпринимать поиски в Интернете, просто надо задать запрос:
SQL> select * from v$transportable_platform order by platform_id;
PLATFORM_ID PLATFORM_NAME ENDIAN_FORMAT
----------- ----------------------------------- --------------
1 Solaris[tm] OE (32-bit) Big
2 Solaris[tm] OE (64-bit) Big
3 HP-UX (64-bit) Big
4 HP-UX IA (64-bit) Big
5 HP Tru64 UNIX Little
6 AIX-Based Systems (64-bit) Big
7 Microsoft Windows IA (32-bit) Little
8 Microsoft Windows IA (64-bit) Little
9 IBM zSeries Based Linux Big
10 Linux IA (32-bit) Little
11 Linux IA (64-bit) Little
12 Microsoft Windows 64-bit for AMD Little
13 Linux 64-bit for AMD Little
15 HP Open VMS Little
16 Apple Mac OS Big
Предположим, что Вы хотите транспортировать табличное пространство USERS от хост-машины SRC1 с операционной системой Linux в архитектуре Intel на машину TGT1, работающей под Windows Microsoft. И исходная, и целевая платформы имеют тип little endian. Файл данных табличного пространства USERS - users_01.dbf. Вы должны действовать примерно следующим образом.
- Перевести табличное пространство в состояние READ ONLY (ТОЛЬКО-ДЛЯ-ЧТЕНИЯ):
alter tablespace users read only;
- Экспортировать табличное пространство. В командной строке OS вводится:
exp tablespaces=users transport_tablespace=y file=exp_ts_users.dmp
Файл exp_ts_users.dmp содержит только метаданные, а не содержание табличного пространства USERS, поэтому он будет очень маленьким.
- Скопировать файлы exp_ts_users.dmp и users_01.dbf на машину TGT1. Если используется протокол передачи файлов FTP, необходимо определить двоичную (binary option) передачу.
- Подключить табличное пространство к базе данных. В командной строке OS вводится:
imp tablespaces=users transport_tablespace=y
file=exp_ts_users.dmp datafiles='users_01.dbf'
- После Шага 4, целевая база данных будет иметь табличное пространство по имени USERS, и содержание табличного пространства будет доступно.
Мы помним, что системы SRC1 и TGT1 - соответственно - Linux и Windows. База данных Oracle9i, функционирующая на TGT1, не сможет на Шаге 4 распознать файл данных users_01.dbf, что делает выполнение всего этого процесса бесполезным. В этом случае нужно было прибегнуть к некоему другому подходу, например, обычному экспорту и импорту, или созданию плоских файлов, которые загружаются через SQL*Loader, или прямой загрузке, используя связи (database links) баз данных.
В 10g эти альтернативные способы не нужны, потому что целевая база данных распознает файл данных от другой платформы. В нашем примере порядок байтов в OS исходной и целевой машин одинаков (little endian), поэтому нет необходимости в каком-либо преобразовании.
Эта возможность особенно полезна в хранилищах данных, когда меньшие, ориентированные на определенные темы витрины данных часто пополняются из большого хранилища данных после его обновления. Применяя 10g, эти витрины данных можно теперь разместить на более скромных и более дешевых машинах, типа Intel-стоек с Linux, в то время как сервером хранилища данных располагается на большей машине класса предприятия. В сущности, используя транспортабельные табличные пространства, теперь можно лучше использовать различные аппаратные средства и OS.
Преодолевая различия порядка байтов платформ
Но если все же платформы имеют различный порядок байтов (endianness), как обеспечить переносимость? Как я объяснил выше, если порядок байтов целевой машины отличен от машины-источника, то чтение файлов данных будет неправильным, делая невозможным простое копирование файлов данных. Но не падайте духом; помощь придет от утилиты RMAN в Oracle 10g, которая обеспечивает преобразование файлов данных от одного порядка байтов к другому.
В приведенном выше примере, если хост-машины SRC1 использует Linux (little endian) и целевая хост- машина TGT1 работает с HP-UX (big endian), нужно ввести между Шагами 3 и 4 дополнительный шаг для преобразования. Используя RMAN, Вы конвертируете файл данных от формата Linux в формат HP-UX на исходной машине SRC1 (предполагая, что табличное пространство уже переведено в состояние только-для-чтения):
RMAN> convert tablespace users
2> to platform 'HP-UX (64-bit)'
3> format='/home/oracle/rman_bkups/%N_%f';
Starting backup at 14-MAR-04
using channel ORA_DISK_1
channel ORA_DISK_1: starting datafile conversion
input datafile fno=00004 name=/usr/oradata/dw/starz10/users01.dbf
converted datafile=/home/oracle/rman_bkups/USERS_4
channel ORA_DISK_1: datafile conversion complete, elapsed time: 00:00:07
Finished backup at 14-MAR-04
Этот шаг продуцирует файл в стандартном RMAN-формате файла <tablespace_name> _ <absolute_datafile_no> в директории /home/oracle/rman_bkups. Обратите внимание, что файл данных для табличного пространства USERS не затронут; более того, для HP-UX создан новый файл. Теперь этот файл может быть скопирован в целевую систему и просто выполнены остальные шаги.
Эта конверсионная команда RMAN представляет собой мощный механизм. В заданном выше шаблоне она может создать последовательность файлов данных. Для табличного пространства, содержащего несколько файлов данных, можно задать выполнение параллельного преобразования. Чтобы сделать это, надо добавить вышеупомянутой команде такое предложение:
parallelism = 4
что породит четыре RMAN-канала, каждый из которых работает с файлом данных. Однако, более полезный подход состоит в том, чтобы конвертировать большое количество табличных пространств за один прием, когда и проявляется действительная эффективность параллелизма. Ниже мы конвертируем для HP-UX два табличных пространства, USERS и MAINTS:
RMAN> convert tablespace users, maints
2> to platform 'HP-UX (64-bit)'
3> format='/home/oracle/rman_bkups/%N_%f'
4> parallelism = 5;
Starting backup at 14-MAR-04
using target database controlfile instead of recovery catalog
allocated channel: ORA_DISK_1
channel ORA_DISK_1: sid=244 devtype=DISK
allocated channel: ORA_DISK_2
channel ORA_DISK_2: sid=243 devtype=DISK
allocated channel: ORA_DISK_3
channel ORA_DISK_3: sid=245 devtype=DISK
allocated channel: ORA_DISK_4
channel ORA_DISK_4: sid=272 devtype=DISK
allocated channel: ORA_DISK_5
channel ORA_DISK_5: sid=253 devtype=DISK
channel ORA_DISK_1: starting datafile conversion
input datafile fno=00004 name=/usr/oradata/dw10/dw10/users01.dbf
channel ORA_DISK_2: starting datafile conversion
input datafile fno=00005 name=/usr/oradata/dw10/dw10/users02.dbf
channel ORA_DISK_3: starting datafile conversion
input datafile fno=00006 name=/usr/oradata/dw10/dw10/maints01.dbf
channel ORA_DISK_4: starting datafile conversion
input datafile fno=00007 name=/usr/oradata/dw10/dw10/maints02.dbf
converted datafile=/home/oracle/rman_bkups/USERS_4
channel ORA_DISK_1: datafile conversion complete, elapsed time: 00:00:03
converted datafile=/home/oracle/rman_bkups/USERS_5
channel ORA_DISK_2: datafile conversion complete, elapsed time: 00:00:00
converted datafile=/home/oracle/rman_bkups/MAINTS_6
channel ORA_DISK_3: datafile conversion complete, elapsed time: 00:00:01
converted datafile=/home/oracle/rman_bkups/MAINTS_7
channel ORA_DISK_4: datafile conversion complete, elapsed time: 00:00:01
Finished backup at 14-MAR-04
В приведенных выше примерах имена преобразованных файлов трудно расшифровать и связывать их с именами оригинальных файлов (например, файл users01.dbf становится USERS_4). Однако, имеется возможность использовать другой формат для именования файлов данных. Этот процесс подобен тому, как переименовываются файлы данных в механизме Data Guard (Защита Данных). Следует задать:
RMAN> convert tablespace users
2> to platform 'HP-UX (64-bit)'
3> db_file_name_convert '/usr/oradata/dw10/dw10','/home/oracle/rman_bkups'
4> ;
Starting backup at 14-MAR-04
using channel ORA_DISK_1
channel ORA_DISK_1: starting datafile conversion
input datafile fno=00004 name=/usr/oradata/dw10/dw10/users01.dbf
converted datafile=/home/oracle/rman_bkups/users01.dbf
channel ORA_DISK_1: datafile conversion complete, elapsed time: 00:00:03
channel ORA_DISK_1: starting datafile conversion
input datafile fno=00005 name=/usr/oradata/dw10/dw10/users02.dbf
converted datafile=/home/oracle/rman_bkups/users02.dbf
channel ORA_DISK_1: datafile conversion complete, elapsed time: 00:00:01
Finished backup at 14-MAR-04
что сохранит имена файлов после преобразования. Если Вы перейдете в директорию /home/oracle/rman_bkups, то увидите файлы users01.dbf и users02.dbf, имена которых соответствуют первоначальным именам файлов.
В приведенных выше случаях мы конвертировали файлы на исходной платформе. Однако, это можно также сделать и на целевой платформе. Например, можно скопировать файл users01.dbf на хост-машину TGT1, работающую с HP-UX, а затем преобразовать файл в формату HP-UX:
RMAN> convert
2> datafile '/usr/oradata/dw10/dw10/users01.dbf'
3> format '/home/oracle/rman_bkups/%N_%f'
4> ;
Это решение создаст файл в формате, определенном в директории.
Но с чего может понадобиться конвертирование файлов данных на целевой платформе? Одной причиной может стать требование обеспечить минимальное простоя, то есть, чтобы табличные пространства были в состоянии READ ONLY (ТОЛЬКО-ДЛЯ-ЧТЕНИЯ) только в течение процесса их копирования в целевую хост-машину. Если, предположим, файл находится на тройном зеркале (triple-mirror), то после того, как табличное пространство переведено в состояние только-для-чтения, можно вывести из-под управления третье зеркало и немедленно восстановить состояние read/write (чтение/запись) табличного пространства. А это третье зеркало может тогда быть установлено на целевой системе, и файл сконвертирован на досуге. Эта схема минимизирует продолжительность пребывания табличного пространства в режиме только-для-чтения.
Другой причиной может стать производительность. База данных класса OLTP (on-line transaction processing - оперативная обработка транзакций (в реальном времени)) может работать с устойчивой нагрузкой, и использование RMAN-операции конвертирования может более чем следует перенапрячь систему. Вместо этого работа по конвертированию может быть передана на сервер хранилища данных, где большинство CPU обычно задействуется в параллельных операциях.
Использование внешних таблиц в качестве механизма передачи данных
База данных Oracle9i ввела внешние таблицы, которые позволяют отформатированным плоским текстовым файлам быть видимыми в базе данных как таблицы, из которых может быть сделана обычная SQL-выборка. Предположим, что нужно переместить содержимое таблицы по имени TRANS из базы данных класса OLTP в базу хранилища данных, используя этот механизм внешних таблиц. Ниже приведены шаги, как это выполнить.
- В базе данных OLTP создайте плоский текстовый файл с содержимым таблицы TRANS. Файл можно назвать trans_flat.txt в директории /home/oracle/dump_dir. Обычно такой файл создается таким SQL-предложением:
spool trans_flat.txt
select <column_1> ||','|| <column_2> ||','|| ...
from trans;
spool off
- Скопируйте файл на сервер хранилища данных, используя ftp, rcp или какой-либо другой механизм. Файл помещается в директорию /home/oracle/dump_dir.
- В базе данных хранилища создайте объект типа directory (директория) с именем dump_dir:
create directory dump_dir as '/home/oracle/dump_dir';
- Создайте внешнюю таблицу:
create table trans_ext
(
... <columns of the table> ...
)
organization external
(
type oracle_loader
default directory admin
access parameters
(
records delimited by newline
badfile 'trans_ext.bad'
discardfile 'trans_ext.dis'
logfile 'trans_ext.log'
fields terminated by "," optionally enclosed by '"'
(
... <columns> ...
)
)
location ('trans_flat.txt')
)
reject limit unlimited;
- Теперь перегрузите внешнюю таблицу в обычные таблицы, используя любой обычный метод, типа вставки прямой загрузкой или слияния.
Наиболее затратный по времени шаг 1, на котором создается плоский текстовый файл. Этот файл можно создать, используя простой SQL-запрос и посылая выход в spool-файл – простой, но достаточно длительный процесс. Его можно сделать несколько быстрее, используя программу Pro*C или OCI вместо SQL*Plus, чтобы выгрузить строки на плоский файл, но это все еще будет требовать времени. Другой "удар по скорости" – это ручное определение столбцов, еще один отнимающий много времени процесс.
Обе эти проблемы разрешились в 10g. Теперь можно быстро разгрузить таблицу в переносимый формат, используя процесс создания внешней таблицы. Выше приведенный Шаг 1 становится этим простым SQL:
create directory dump_dir as '/home/oracle/dump_dir';
create table trans_dump
organization external
(
type oracle_datapump
default directory dump_dir
location ('trans_dump.dmp')
)
as
select * from trans
/
Эта команда создает в директории /home/oracle/dump_dir файл, названный trans_dump.dmp. Этот файл не является в строго ASCII-текстом; метаданные - явный текст, но фактические данные находятся в неформатированном (raw) виде. Однако, этот файл может быть перенесен между операционными системами, подобным экспортному дамп-файлу, но, в отличие от экспорта, загрузка данных чрезвычайно быстра. Вы копируете этот файл на сервер хранилища данных и создаете внешнюю таблицу тем же самым способом, как прежде, но на сей раз подставляя этот файл как источник.
Так в чем же различия между предыдущими механизмами передачи данных и этим? Есть несколько. Во-первых, можно создать переносимый файл чрезвычайно быстро без написания сколько-либо сложного SQL-предложения, выбирающего столбцы таблицы и так далее. Во вторых, можно использовать этот файл как вход для внешней таблицы, рассматривая данные как обычную таблицу и загружая данные в другие таблицы после манипулирования с данными. Можно также повысить производительность выгрузки данных в эту внешнюю таблицу, как показано ниже.
create table trans_dump
organization external
(
type oracle_datapump
default directory dump_dir
location ('trans_dump.dmp')
)
parallel 2
as
select * from trans
/
Эта команда создает тот же самый файл, но только параллельно. Вы можете сделать это, чтобы использовать в своих интересах несколько CPU, если они доступны. В дополнение к параллельной разгрузке, можно также выгружать таблицу в несколько внешних файлов, как показано ниже.
create table trans_dump
organization external
(
type oracle_datapump
default directory dump_dir
location ('trans_dump_1.dmp','trans_dump_2.dmp')
)
parallel 4
as
select * from trans
/
Эта команда создает два файла trans_dump_1.dmp и trans_dump_2.dmp, вместо одного в предыдущем примере. Этот подход полезен в случае файлов, распределенных на многих физических устройствах или контроллерах, что уменьшает ожидания, связанные с I/O-операциями (ввод/вывод).
Заключение
Реализовав транспортабельность табличных пространств между платформами, 10g предлагает мощное решение по перемещению данных в хранилищах данных. Вместе с механизмом загрузки External Table (Внешние таблицы) эта функциональность заполняет промежуток между исходными и целевыми базами данных (являются ли они OLTP-базами, хранилищами данных или витринами данных) в целях публикации, что позволяет Вам выбрать подходящие платформы для специфических типов приложений.
Кроме того, построив жизнеспособные транспортабельные табличные пространства, 10g делает обновление данных более быстрым и более частым с тем, чтобы проанализированные данные были доступны конечным пользователям как можно скорее. Эта возможность может также использоваться для передачи данных к различным базам данных через автономные носители, независимо от их ведущих систем. Использование внешних таблиц делает рентабельным перемещение больших объемов данных, поскольку инструмент ETL наконец-то становится доступным конечному пользователю.
Более подробная информация о транспортировке табличных пространств в 10g находится в Главе 8 в секции "Transporting Tablespaces Between Databases" руководства “Oracle Database Administrator's Guide”. |