Export/Import PL/SQL
DBA's Dictionary |
Быстрая Архивация ДанныхВо всем мире объем данных, хранящихся в базах данных Oracle, продолжает неуклонно расти. Одновременно снижается и стоимость дисковой памяти, тем не менее вопрос архивации и вывода устаревших данных из системы остается актуальным. Во многих системах, использующих БД Oracle в качестве хранилища данных, бизнес требует периодической массовой загрузки и дальнейшей обработки большого объема данных. Периодичность поступления новых данных в систему может варьироваться в диапазоне от секунд до месяцев, размер - от десятков мегабайт до сотен гигабайт за период. Но в общем случае важно то, что природа таких данных имеет явную или неявную привязку ко времени. Это означает, что по истечении некоторого времени данные, обработанные в системе, теряют свою актуальность и вероятность их повторного использования уменьшается со временем. В качестве примера можно привести системы обработки телеметрической информации, биллинговые системы. Общим решением задачи вывода данных из системы является построение отдельного Хранилища Данных (Data Warehouse), куда с некоторой периодичностью переносят архивные данные. Однако такой подход решает не только и не столько задачу архивации, он может не оправдать себя по следующим причинам:
Oracle7 В Oracle7 эта задача решается через создание дополнительных архивных таблиц. С некоторой периодичностью устаревшие данные переносят в эти таблицы. Когда возникает потребность, часть архивных данных копируют обратно в базовые таблицы. Недостатки такого подхода очевидны:
Oracle8i Введем несколько терминов, чтобы формализовать дальнейшее описание.
Партицирование является прозрачным для пользовательских операций с данными. На размер партиции не накладывается жестких ограничений и, в общем случае, он должен определяться индивидуально для каждой системы с учетом объема данных, поступающих в систему, наличия свободного дискового пространства, требований к эффективности запросов по диапазону дат, ограничений offline-носителей. Почему мы обязаны использовать partitioning для быстрой архивации данных станет ясно чуть позже. Однако сейчас нужно упомянуть, что размер отдельной партиции по сути и определяет размер соответствующего архива. C учетом бизнес требований и объема дискового пространства, доступного для хранения звонковых данных, в системе определяется период online-хранения данных в базовой таблице(ах). Пример. Допустим, с учетом требований бизнеса заказчика в системе необходимо хранить звонковые данные за последние 2 месяца и выбрано суточное партицирование. Тогда в общем случае данный период будет покрыт 61 партицией. Каждые сутки звонковые данные самой старой партиции переводятся в offline-хранение, создается партиция для загрузки новых данных. Таким образом период online-хранения звонковых данных, покрываемый набором партиций остается неизменным. Это похоже на "временное окно", которое охватывает постоянный объем данных (в единицах времени) и двигается по времени с дискретным шагом, равным суткам. Период offline-хранения данных определяется исключительно потребностями бизнеса и может составлять значительный период времени. В зависимости от объема архивируемых данных и требований, предъявляемых к времени доступа, возможно применение двух базовых вариантов архивации/восстановления данных: Вариант 1.Время доступа к архивным данным некритично, есть дополнительное свободное дисковое пространство. Относительно небольшие объемы данных, подлежащих архивации. Архивация
Восстановление
Я не буду подробно останавливаться на этом варианте в силу его простоты. Наша цель - Быстрая Архивация! Вариант 2.
Большие объемы данных, подлежащих архивации. Жесткие требования к времени восстановления данных.
Предполагает использование механизма Transportable Tablespaces.
Пример Быстрой Архивации Данных с использованием механизма Transportable Tablespaces.
Таблица CALLS_TMP состоит из двух партиций CLD20000901, CLD20000902, в которых хранятся звонки за двое суток. Таблица имеет первичный ключ PK_CALLS_TMP. Необходимо провести архивацию звонков за 1ое сентября 2000 года (партиция CLD20000901) SQL> select partition_name, tablespace_name 2 from user_tab_partitions 3 where table_name = 'CALLS_TMP'; PARTITION_NAME TABLESPACE_NAME ------------------------------ ---------------- CLD20000901 CLD_20000901 CLD20000902 CLD_20000902 SQL> SQL> select partition_name, tablespace_name 2 from user_ind_partitions 3 where index_name = 'PK_CALLS_TMP'; PARTITION_NAME TABLESPACE_NAME ------------------------------ ---------------- CLD20000901 CLI_20000901 CLD20000902 CLI_20000902 SQL> SQL> create tablespace cld20000901_dummy 2 datafile '/export/home/edward/oradata/REED/cld20000901d_01.dbf' size 100K; Tablespace created. Обратите внимание на размер файла! SQL> alter user edward 2 quota unlimited on cld20000901_dummy; User altered. 1. Создание вспомогательной таблицы для развязки c таблицей CALLS_TMP SQL> SQL> create table cld20000901_archive_tab 2 storage(initial 10K next 10K minextent 1 pctincrease 0) 3 tablespace cld20000901_dummy 4 as select * from calls_tmp where 1 = 2; Table created. SQL> SQL> alter table cld20000901_archive_tab add constraint 2 pk_cld20000901_archive primary key (call_date, id) 3 using index storage(initial 10K) tablespace cld20000901_dummy; Table altered.
2. "Перенос" данных партиции в таблицу. Здесь важно заметить, что команда
SQL> alter table calls_tmp exchange partition cld20000901
2 with table cld20000901_archive_tab including indexes without validation;
Table altered.
SQL> select partition_name, tablespace_name
2 from user_tab_partitions
3 where table_name = 'CALLS_TMP';
PARTITION_NAME TABLESPACE_NAME
------------------------------ ---------------------
CLD20000901 CLD20000901_DUMMY
CLD20000902 CLD_20000902
SQL> select partition_name, tablespace_name
2 from user_ind_partitions
3 where index_name = 'PK_CALLS_TMP';
PARTITION_NAME TABLESPACE_NAME
------------------------------ ------------------
CLD20000901 CLD20000901_DUMMY
CLD20000902 CLI_20000902
SQL> select count(*) from cld20000901_archive_tab;
COUNT(*)
---------
749900
SQL>
SQL> select count(*) from calls_tmp partition (cld20000901);
COUNT(*)
---------
0
SQL> select tablespace_name
2 from user_tables
3 where table_name = 'CLD20000901_ARCHIVE_TAB';
TABLESPACE_NAME
------------------------------
CLD_20000901
SQL>
SQL> select tablespace_name
2 from user_indexes
3 where index_name = 'pk_cld20000901_archive';
TABLESPACE_NAME
------------------------------
CLI_200009013. Проверка на самодостаточность и создание переносимого набора (
SQL>
SQL> execute sys.dbms_tts.transport_set_check('CLD_20000901, CLI_20000901', TRUE);
PL/SQL procedure successfully completed.
SQL>
SQL> select * from sys.transport_set_violations;
no rows selected
SQL>
SQL> alter tablespace cld_20000901 read only;
Tablespace altered.
SQL> alter tablespace cli_20000901 read only;
Tablespace altered.3. Создание файла метаданных /export/home/edward/exp>cat exp_params.dat transport_tablespace=y tablespaces=(cld_20000901,cli_20000901) triggers=n constraints=y grants=y file=expdat.dmp /export/home/edward/exp>exp parfile=exp_params.dat Export: Release 8.1.7.0.0 - Production on Fri Apr 6 10:40:23 2001 (c) Copyright 2000 Oracle Corporation. All rights reserved. Username: sys as sysdba Password: Connected to: Oracle8i Enterprise Edition Release 8.1.7.0.0 - Production With the Partitioning option JServer Release 8.1.7.0.0 - Production Export done in CL8ISO8859P5 character set and CL8ISO8859P5 NCHAR character set Note: table data (rows) will not be exported About to export transportable tablespace metadata... For tablespace CLD_20000901 ... . exporting cluster definitions . exporting table definitions . . exporting table CLD20000901_ARCHIVE_TAB For tablespace CLI_20000901 ... . exporting cluster definitions . exporting table definitions . exporting referential integrity constraints . end transportable tablespace metadata export Export terminated successfully without warnings. /export/home/edward/exp> SQL> alter tablespace cld_20000901 offline; Tablespace altered. SQL> alter tablespace cli_20000901 offline; Tablespace altered. SQL> drop tablespace cld_20000901 including contents; Tablespace dropped. SQL> drop tablespace cli_20000901; Tablespace dropped. SQL> SQL> select tablespace_name 2 from dba_tablespaces 3 where tablespace_name like '%2000090_'; TABLESPACE_NAME ------------------------------ CLD_20000902 CLI_20000902 4. Перемещение файлов табличных пространств cld_20000901, cli_20000901 на offline-носитель. Восстановление
Пример Быстрого Восстановления Данных с использованием механизма
Необходимо восстановить архивные данные за сентябрь 2000 года.
/export/home/edward/exp>cat imp_params.dat
transport_tablespace=y
datafiles=('/export/home/edward/oradata/REED/cld_20000901_01.dbf',
'/export/home/edward/oradata/REED/cli_20000901_01.dbf')
tablespaces=('CLD_20000901', 'CLI_20000901')
/export/home/edward/exp>imp parfile=imp_params.dat
Import: Release 8.1.7.0.0 - Production on Fri Apr 6 11:47:09 2001
(c) Copyright 2000 Oracle Corporation. All rights reserved.
Username: sys as sysdba
Password:
Connected to: Oracle8i Enterprise Edition Release 8.1.7.0.0 - Production
With the Partitioning option
JServer Release 8.1.7.0.0 - Production
Export file created by EXPORT:V08.01.07 via conventional path
About to import transportable tablespace(s) metadata...
import done in CL8ISO8859P5 character set and CL8ISO8859P5 NCHAR character set
. importing SYS's objects into SYS
. importing EDWARD's objects into EDWARD
. . importing table "CLD20000901_ARCHIVE_TAB"
About to enable constraints...
Import terminated successfully without warnings.
SQL> select tablespace_name, status
2 from dba_tablespaces
3 where tablespace_name like '%2000090_';
TABLESPACE_NAME STATUS
------------------------------ ---------
CLD_20000901 READ ONLY
CLD_20000902 ONLINE
CLI_20000901 READ ONLY
CLI_20000902 ONLINE
SQL>
SQL> alter tablespace CLD_20000901 read write;
Tablespace altered.
SQL> alter tablespace CLI_20000901 read write;
Tablespace altered.
SQL>
SQL> select segment_name
2 from user_segments
3 where tablespace_name = 'CLD_20000901';
SEGMENT_NAME
-----------------------
CLD20000901_ARCHIVE_TAB
SQL> alter table calls_tmp
2 exchange partition cld20000901
3 with table cld20000901_archive_tab
4 including indexes without validation;
Table altered.
SQL>
SQL> select partition_name, tablespace_name
2 from user_tab_partitions
3 where table_name = 'CALLS_TMP';
PARTITION_NAME TABLESPACE_NAME
------------------------------ ------------------------------
CLD20000901 CLD_20000901
CLD20000902 CLD_20000902
SQL> select partition_name, tablespace_name
2 from user_ind_partitions
3 where index_name = 'PK_CALLS_TMP';
PARTITION_NAME TABLESPACE_NAME
------------------------------ ------------------------------
CLD20000901 CLI_20000901
CLD20000902 CLI_20000902
SQL> select count(*) from calls_tmp partition (cld20000901);
COUNT(*)
---------
749900
SQL> select count(*) from cld20000901_archive_tab;
COUNT(*)
---------
0
Таким образом, в любой момент времени таблица, данные которой подлежат архивации, будет представлена:
Например, бизнес требует иметь оперативный доступ к данным за последние полгода, хранить данные за
2 года, а шаг партицирования определен как ежемесячный. Тогда архивируемая таблица будет представлена
6 "реальными" партициями и 18 партициями-заглушками. Заключение
В этой статье я попытался передать общую идею процесса архивации, не учитывая второстепенных моментов. Конечно,
здесь есть поле для размышлений. Вы можете архивировать индексы или нет, хранить партиции-заглушки или же создавать
их на лету и т.д. Любое решение в базах данных Oracle - есть разумный компромисс! Однако, в любом случае, решение
быстрой архивации данных базируется на трех основных принципах: PARTITIONING - EXCHANGE PARTITION - TRANSPORTABLE TABLESPACES
Дополнительные ссылки:
Статья Валерия Юринского в Russian Oracle Magazine: "Перемещаем табличные пространства" - временно не доступна до переноса материалов журнала по новому адресу. Last Update: October 11, 2007 18:33:34
|