Вчера я пыталась создать копию таблицы, у которой был столбец типа BLOB. Заливка данных повисла, и я оставила ее висеть до утра :D К тому же это было не к спеху. Таблица была средненькая: около 700 тыс. записей, весит 2 гига. Знала, что это из-за LOBа так висит, и сегодня решила докапаться до истины. И так все по-порядку.
Сперва пыталась создать копию таблицы обычным "create table ... as select", думала средненькая таблица скопируется быстро, но не тут-то было. Висела больше часа, пока не кильнула сессию. С опцией nologging тоже самое, через несколько часов и ее убила:
create table new_blob_table as select * from orig_blob_table;А direct path insert командой insert /*+ append */ тоже висела пару часов, и я, добрая, оставила ее висеть до утра:
create table new_blob_table nologging as select * from orig_blob_table;
create table new_blob_table as select * from orig_blob_table where 1=2;Во время всех этих попыток, сессия ожидала события direct path write (lob):
insert /*+ append */ into new_blob_table select * from orig_blob_table;
SQL> select eventПри прямой записи - direct path write - запись происходит В ОБХОД буферного кеша прямо в файлы данных. Запись выполняется серверным процессом (а не процессом DBWR, как в обычной записи), который в pga сессии подготавливает блоки и записывать их за отметкой HWM.
from v$session_wait
where sid=969;
EVENT
-------------------------
direct path write (lob)
Бурлесон перечисляет список операций, которые могут выполнять операцию прямой записи (direct path write) и вызывать соответствущие ожидания:
Operations that could perform direct path writes include whenНаш случай - последний, связанный с LOBами. Вот что пишут в документации Oracle о прямой записи (direct path write) и параметре CACHE/NOCACHE LOB-сегментов:
1) a sort goes to disk,
2) during parallel DML operations,
3) direct-path inserts,
4) parallel create table as select, and
5) some LOB operations.
With the CACHE option, LOB data reads show up as wait event 'db file sequential read', writes are performed by the DBWR process.О параметре CACHE BLOB-сегментов, я писала недавно здесь. Получается, что когда я создавала таблицу командой create table ... as select ..., LOB-сегмент таблицы создались с параметром NOCACHE, который и ведет к ожиданиям direct path write (lob).
With the NOCACHE option, LOB data reads/writes show up as wait events:
direct path read (lob)/direct path write (lob).
Corresponding statistics are:
physical reads direct (lob) and physical writes direct (lob).
SQL> select table_name, column_name, cacheТо есть новую таблицу нужно либо изначально создать с параметром CACHE LOB-сегмента:
from dba_lobs
where table_name='NEW_BLOB_TABLE';
TABLE_NAME COLUMN_NAME CACHE
-------------------- -------------------- --------
NEW_BLOB_TABLE BLOB_COLUMN NO
create table new_blob_tableили после создания пустой таблицы (where 1=2), изменить параметр CACHE LOB-сегмента:
lob (blob_column) store as (cache)
as select * from orig_blob_table where 1=2;
alter table new_blob_table modify lob (request_content) (cache);Теперь, заливка длится чуть больше 1 минуты (!!!):
SQL> create table new_blob_tableДаже обычный инсерт отработал всего 4 минуты!
lob (blob_column) store as (cache)
as select * from orig_blob_table where 1=2;
Table created.
SQL> set timing on
SQL> insert /*+ append */ into new_blob_table select * from orig_blob_table;
642966 rows created.
Elapsed: 00:01:12.83
SQL> insert into new_blob_table select * from orig_blob_table;Странно, что если создавать НЕпустую таблицу командой create table ... as select ... с параметром CACHE LOB-сегмента, он все равно зависает с ожиданиями direct path write (lob):
642966 rows created.
Elapsed: 00:04:18.85
create table new_blob_tableТеперь, при заливке командой insert /*+ append */, ожидания записи direct path write (lob) исчезли, есть коротенькие ожидания, но это уже ожидания чтения db file sequential read и db file scattered read. А статистика physical writes direct (lob) заменилась на physical writes direct.
lob (blob_column) store as (cache)
as select * from orig_blob_table;
Вот. Получается, что с insert /*+ append */ происходит прямая запись, но видимо эта запись уже отличается прямой записи БЛОБов. Если у кого-то есть более подробное описание всего этого, буду рада послушать.
1 коммент.:
Данной решение подходит для случая когда размер LOB-а менее 4000Bytes и LOB-полей НЕМНОГО в таблице.
С большими LOB или c большим количеством небольших LOB ситуация была бы другая - быстрее работал бы режим NOCACHE
Если время заливки очень критично можно еще попробовать режим NOCACHE NOLOGGING:
alter tabe table_name modify lob (LOB_column_name) (nocache nologging)
- размер сгененрированного REDO значительно уменьшится :)
Кстати, в статье не указано какой режим использовался для хранения LOB(ENABLE/DISABLE ) - это тоже важно. Но, кажется, :) - DISABLE STORAGE IN ROW. Для ENABLE STORAGE IN ROW изменение параметра CACHE/NOCACHE не повлияло бы на производительность в данном случае.
Отправить комментарий