|
Программирование >> Oracle
20 21 22 23 24 25 26 28 29 30 31 32 33 34 35 36 37 38 39 40 41 redo redo redo (x.object id, x.object name, x.created); commit; end loop; report; select value into l redo size from redo size; for x in (select rowid rid from t) loop update t set у = lower (у) where rowid = x.rid; commit; end loop; report; select value into l redo size from redo size; for x in (select rowid rid from t) loop delete from t where rowid = x.rid; commit; end loop; report; end; / size = 530396 rows = 200 2,652.0 bytes/row size = 956660 rows = 200 4,783.3 bytes/row size = 537132 rows = 200 2,685.7 bytes/row PL/SQL procedure successfully completed. Как видите, фиксация кажждой строки заметно увеличила объем генерируемых дан-н1х повторного выполнения (итоговые результаты представлены в следующей таблице). Есть и другие причины, связанные с производительностью, объясняющие, почему не стоит фиксировать кажждую измененную строку (или группу строк). Мы видели непосредственное доказательство этого в примере выше, где фиксация каждой строки требует в три раза больше времени, чем фиксация после завершения транзакции. Дополнительные затраты времени связаны с обращением к ядру сервера, установкой дополнительных защелок и возникновением конфликтов при доступе к общим ресурсам при выполнении каждого оператора. Итак, если что-то можно сделать с помощью одного оператора SQL - делайте это именно так. Кроме того, фиксируйте транзакцию, только когда она закончена, не раньше.
Представленный выше метод пригодится и для оценки побочных эффектов различ-н1х вариантов работы. Один из часто возникающих вопросов связан с триггерами. Помимо того, что в триггере BEFORE можно изменять указанные значения строки, есть ли еще какие-то особенности применения триггеров? Как оказалось, есть. Триггер BEFORE создает дополнительные данные повторного выполнения, даже не изменив ни одного значения в строке. Этот вопрос достоин отдельного изучения, и с помощью представленных выше методов можно убедиться, что: триггер BEFORE или AFTER не влияет на объем данных повторного выполнения для операторов DELETE; оператор INSERT генерирует дополнительно одинаковый объем данных повторного выполнения при наличии триггера BEFORE или AFTER; на объем данных повторного выполнения, генерируемых оператором UPDATE, влияет только наличие триггера BEFORE - триггер AFTER не генерирует дополнительных данных; размер строки влияет на объем дополнительно генерируемых данных повторного выполнения для операторов INSERT, но не для операторов UPDATE. Используем таблицу Т из предгдущего примера: create table t (x int, у char(N), z date); но создадим несколько ее версий с разными значениями N. В данном случае мы используем значения N = 30, 100, 500, 1000 и 2000 для получения строк разного размера. Я использовал простую таблицу для регистрации результатов нескольких экспериментов: create table log (what varchar2(15), - будет иметь значения по trigger, after - или before op varchar2(10), - будет иметь значения insert, update или - delete rowsize int, - будет содержать размер столбца Y redo size int, - будет содержать объем сгенерированных - данных повторного выполнения rowcnt int) ; - будет содержать количество обработанных - строк Выполнив тест с различными размерами столбца Y, проанализируем результаты. Я использую следующую хранимую процедуру для генерации транзакций и записи объема сгенерированных данных повторного выполнения. Подпроцедура REPORT - это локальная процедура (видимая только в процедуре DO WORK), выдающая на экран информацию о происходящем и записывающая полученные результаты в таблицу LOG. Основное тело процедуры выполняет проверяемые транзакции. Все начинается с запоминания текущего объема данных повторного выполнения в текущем сеансе, выполнения определенных действий, а затем генерируется отчет: tkyte@TKYTE816> create or replace procedure do work (p what in varchar2) 2 as 3 l redo size number; 4 1 cnt number := 200; 6 procedure report(l op in varchar2) 7 is 8 begin 9 select value-l redo size into l redo size from redo size; 10 dbms output.put line(l op redo size = l redo size 11 rows = l cnt 12 to char(l redo size/l cnt, 99,999.9) 13 bytes/row); 14 insert into log 15 select p what, l op, data length, l redo size, l cnt 16 from user tab columns 17 where table name = T 18 and column name = У; 19 end; 20 begin 21 select value into l redo size from redo size; 22 insert into t 23 select object id, object name, created 24 from all objects 25 where rownum <= l cnt; 26 l cnt := sql%rowcount; 27 commit; 28 report(insert); 29 30 select value into l redo size from redo size; 31 update t set y=lower(y); 32 l cnt := sql%rowcount; 33 commit; 34 report(update); 35 36 select value into l redo size from redo size; 37 delete from t; 38 l cnt := sql%rowcount; 39 commit; 40 report(delete); 41 end; 42 / Procedure created. Теперь, когда все готово, я удалю и создам таблицу Т, изменяя размер столбца Y. Затем выполню следующий код для тестирования различнгх сценариев (без триггеров, с триггером BEFORE и с триггером AER): tkyte@TKYTE816> truncate table t; Table truncated. tkyte@TKYTE816> exec do work(no trigger); insert redo size = 443280 rows = 200 2,216.4 bytes/row update redo size = 853968 rows = 200 4,269.8 bytes/row delete redo size = 473620 rows - 200 2,368.1 bytes/row
|
© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки. |