Владимир Пржиялковский
Нередко перед пользователем Oracle стоит задача загрузить в БД большую таблицу. Если таблица действительно велика, то есть содержит по сегодняшним меркам миллион или более записей, то критичным становится время загрузки, за которое и приходится бороться. О чем в таких ситуациях полезно помнить?
В Oracle существует только два способа заполнения таблицы. Первый, самый распространенный, это вставка, то есть последовательное выполнение непосредственных операций уровня SQL INSERT. По этому способу работают:
- непосредственно предложение INSERT INTO …;
- предложение CREATE TABLE … AS …;
- программа imp;
- программа SQL*Loader.
Менее известно (хотя тайны в этом абсолютно никакой нет), что есть и второй способ - прямой загрузки, - который может применяться при работе с программой SQL*Loader (то есть SQL*Loader позволяет загружать данные и первым, и вторым способом). Именно о нем и пойдет речь.
SQL*Loader
SQL*Loader - программа-загрузчик для эффективного наполнения БД большими объемами данных. Она поставляется в любой поставке СУБД Oracle. Архитектура этой программы - живая иллюстрация милых сердцу ветеранов классических загрузчиков, создававшихся лет 20 назад для занесения данных с магнитных лент в базу. Однако "унаследованный" - вовсе не синоним словам "ненужный" или "плохой". Появившаяся в версии 6 Oracle, программа SQL*Loader дожила до нынешней 9i, пополнившись в этой версии "третьего тысячелетия" собственным скромным набором, но - усовершенствований. Такая эпикурейская жизнеспособность была бы маловероятна в отсутствии постоянного потребительского спроса.
Долгое время единственным видом исходных данных для него оставался текст, но сегодня SQL*Loader в состоянии также загружать и файлы произвольной структуры - имеется в виду, что в LOB-поля таблиц. Возможны использование разных форматов текстовых данных, предобработка загружаемой информации, выбор загрузки разными способами. Последним он нам сейчас и интересен - для повышения скорости загрузки SQL*Loader может использовать:
(а) параллельную загрузку данных (здесь не рассматриваемую) и
(б) прямую загрузку
Прямая загрузка данных
Прямая загрузка в SQL*Loader есть не что иное, как самостоятельное расписывание блоков поступающими из загрузочного файла данными и передача блоков в уже готовом виде ядру СУБД. Такой способностью в Oracle обладает только SQL*Loader, больше никто. Универсальный, но достаточно громоздкий механизм Oracle по выполнению вставки отдельной строки (подыскивание свободного блока, включающее работу со списками и так далее; генерация записей для отката и прочая "кухня") остается побоку, что и помогает выполнять эту специфичную серию вставок существенно быстрее.
Для того, чтобы загрузка выполнялась таким способом, в контрольный файл загрузчика нужно вставить строку
OPTIONS (DIRECT=TRUE)
(Контрольный файл загрузки задает название и формат файла с загрузочными данными, параметры и режимы загрузки).
Но это еще не все. Чтобы задействовать ресурс увеличения скорость полностью можно вдобавок отключить журнализацию. Для этого укажем в контрольном файле строку
UNRECOVERABLE
Таким образом, самую быструю загрузку сотрудников в базу можно получить примерно таким контрольным файлом:
OPTIONS (DIRECT=TRUE)
UNRECOVERABLE
LOAD DATA
INFILE 'c:\loaderdata\employee.txt'
INTO TABLE emp1
(
empno INTEGER EXTERNAL TERMINATED BY ',',
ename CHAR TERMINATED BY ',' OPTIONALLY ENCLOSED BY '"',
job CHAR TERMINATED BY ',' OPTIONALLY ENCLOSED BY '"',
mgr INTEGER EXTERNAL TERMINATED BY ',',
hiredate DATE "DD/MM/YYYY" TERMINATED BY ',',
sal DECIMAL EXTERNAL TERMINATED BY ',',
comm DECIMAL EXTERNAL TERMINATED BY ',',
deptno INTEGER EXTERNAL TERMINATED BY ','
)
Сами данные, загружаемые с использованием такого контрольного файла, могут выглядеть примерно так:
1000,"Clinton","President",,21/12/1999,3000.50,,40
1010,"Gore","VicePres",1000,23/12/1999,2000.00,,40
…
(Пример взят из моего учебного курса по администрированию Oracle).
На что рекомендуется обратить внимание
Отказ от универсальности не дается даром. При таком специфичном способе загрузки, как указанный, администратору полезно не забывать о следующем.
- При прямой загрузке Oracle никогда не использует
- первый экстент сегмента и
- свободное пространство ниже верхней отметки заполнения (high watermark)
По этой причине разумен следующий трюк: при прямой загрузке "с нуля" (когда загружается изначально пустая таблица) выставить в параметрах STORAGE для этой таблицы значение INIT в очень небольшую величину: все равно первый экстент заполняться не будет!
- Коль скоро мы отказались от журнализации, в результате потерялась возможность восстановить таблицу в базе при неприятностях. Подумайте над этим: если вас не устраивает для таких случаев повторная загрузка таблицы из того же файла, выполните резервное копирование табличного пространства сразу же после загрузки.
Последний ресурс
На самом деле у нас остался еще один незадействованный ресурс увеличения скорости загрузки. SQL*Loader позволяет вести загрузку параллельно, несколькими потоками. Справедливости ради, параллельную вставку (загрузку), если ваша СУБД Oracle работает на платформе с несколькими процессорами, можно выполнять и в обычных случаях. Но параллельная платформа не столь распространена в наших краях, а администраторы, с ней работающие, обычно люди продвинутые: еще и сами других научат, что и как можно делать.
Ссылки по теме