переполнение сегмента отката

iceman

говнокодер
переполнение сегмента отката

обновляю КЛАДР - 1017718 записей...

PHP:
    merge into KLADR k
      using (
        select
          substr(x.code, 1, 15) code,
          substr(x.code, 1, 11) parent_id,
          substr(x.code, 16, 2) actual_flag,
          t.type_id, x."INDEX" zip, x.ocatd, x.name
        from KLADR_STREET x
          inner join KLADR_DISTRICT_TYPE t on x.socr = t.abbreviation and t.type_level = 5
        where substr(x.code, 16, 2) in ('00', '51', '99')
       ) n on (k.kladr_id = n.code)
    when not matched then
       insert (kladr_id, parent_id, actual_flag, district_type, district_level, zip, okato, district_name)
       values (n.code, n.parent_id, n.actual_flag, n.type_id, 5, n.zip, n.ocatd, n.name);
    commit;
данный код выполняется больше часа, при этом переполняется сегмент отката.

Подскажите как модифицировать код, чтобы COMMIT'ить данные например каждые 1000 итераций...

Могу только циклом по курсору, но проверить нужно обновить или добавить запись могу только еще одним селектом, а это накладно, обновляться будет еще дольше...
 

Falc

Новичок
Вообще не понятно нафига тут мердж? Обычный селект и интесрт нагляднее будут.

Обновляй по частям, хотя я бы просто увеличил сегмент отката.
 

iceman

говнокодер
Falc
ой, и правда, я же решил не обновлять записи, а только добавлять xDDDDDDDD
вопрос снимается...

pilot911
у тебя есть альтернативы?)
 

zerkms

TDD infected
Команда форума
Подскажите как модифицировать код, чтобы COMMIT'ить данные например каждые 1000 итераций...
типичная ошибка. увеличение числа итераций только увеличит сегмент отката.

самое разумное решение - увеличить его временно, на выполнение этой операции.
 

Falc

Новичок
zerkms
>>типичная ошибка. увеличение числа итераций только увеличит сегмент отката.

Нету тут ошибки, если не считать что некоторое время данные будут не в совсем согласованном состоянии.

Вытащил 1000 записей вставил недостающие, вытащил следующие 1000. Сегмент отката тут большой не нужен.
 

zerkms

TDD infected
Команда форума
Falc
"Плохие привычки при работе с транзакциями" в той самой книжке Кайта. Там он всё подробно описывает.
 

Falc

Новичок
Плохие привычки это одно, а безысходность другое :)

Конечно увеличивать число транзакций если можно увеличить ролбексегмент не правильно, но что делать если например место на диске ограничено или длинная транзакция блокирует пользователей а согласованность изменяемых данных не критична.
 

zerkms

TDD infected
Команда форума
но что делать если например место на диске ограничено
именно в той главе (и в ряде других) Кайт неоднозначно указывает на то, что транзакция должна быть такой, какой должна быть - не нужно пытаться "оптимизировать", делая комиты чаще, потому как это увеличивает сегмент отката ;-)
 

iceman

говнокодер
zerkms
сегмент отката не увеличить, потому что память закончилась
 

Falc

Новичок
Автор оригинала: zerkms
именно в той главе (и в ряде других) Кайт неоднозначно указывает на то, что транзакция должна быть такой, какой должна быть - не нужно пытаться "оптимизировать", делая комиты чаще, потому как это увеличивает сегмент отката ;-)
Во-первых книжка кайта для начинающих, для тех кто не понимает что такое транзакции, бинд переменных и прочее. Он показывает достоинства Оракле по сравнению с другими БД. Там где он писал про частые комиты он приводил пример с одним селектом и множеством коммитов внутри цикла по селекту, конечно такой код увеличит необходимый размер сегмента отката. Если же каждую итерацию делать новый селект инсерты и коммит, то сегмент отката большой не нужен.
Частые коммиты конечно же увеличат общий объем redo и undo инормации, но большой сегмент отката для выполнения такой операции не потребуется. Возможно увеличивая общий объем undo вызовет проблемы в другом месте где идет обращение к "старым" данным, но если делать коммит каждые например 10к записей то дополнительный объем undo будет мизерным.
 

iceman

говнокодер
я использую курсор, и каждые 1000 итерации - коммит, думаю тут ничего страшного...
 

Falc

Новичок
Если после коммита ты курсор заново не открываешь, то ты только ухудшишь ситуацию.

Вообще я думаю в твоем случае ты мог бы обойтись конструкции INSERT SELECT, и если оптимизировать селект то все должно работать быстро и проблем с сегментом отката не вызывать.

Вообще в решении подобной проблемы оптимизация лучший друг, ускорил запрос и нет проблем с ролбек сегментом.
 

iceman

говнокодер
я делаю в цикле, for i in cMyCursor loop ... end loop;

что будет не так?
 

Falc

Новичок
Комит должен быть вне цикла этого, иначе он никак не уменьшит требуемый сегмент отката а только увеличит. Это как раз та ошибка про которую говорил zerkms и про которую говорил Том Кайт.

Вообще почитай про согласованность чтения и тогда все станет понятно.
 

iceman

говнокодер
.

-~{}~ 21.09.10 15:48:

с INSERT SELECT точно проблем не будет???

-~{}~ 21.09.10 15:49:

запрос я оптимизировал по максимуму, временную таблицу почистил, от не нужной мне инфы...
 
Сверху