DeepEdit!

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

  • Увеличить размер шрифта
  • Размер шрифта по умолчанию
  • Уменьшить размер шрифта

Влияние на производительность

Обычно часто фиксировать получается отнюдь не быстрее — почти всегда бы­стрее все сделать единственным оператором SQL. Для небольшого примера пред­ставим, что у нас есть таблица T с множеством строк, и мы хотим обновить значе­ние столбца для каждой строки в этой таблице. Для демонстрации используются две таблицы — T1 и T2: 
ops$tkyte@ORA10G> create table t1 as select * from all_objects;
Table created. 
Таблица создана. 
ops$tkyte@ORA10G> exec dbms_stats.gather_table_stats( user, 'T1' );
PL/SQL procedure successfully completed.
Процедура PL/SQL успешно завершена. 
ops$tkyte@ORA10G> create table t2 as select * from t1;
Table created. 
Таблица создана. 
ops$tkyte@ORA10G> exec dbms_stats.gather_table_stats( user, 'T2' );
PL/SQL procedure successfully completed.
Процедура PL/SQL успешно завершена. 
Приступая к обновлению, мы можем просто выполнить его единственным опе­ратором UPDATE, как здесь: 
ops$tkyte@ORA10G> set timing on
ops$tkyte@ORA10G> update t1 set object_name = lower(object_name);
48306 rows updated.
48306 строк обновлено. 
Elapsed: 00:00:00.31
Общее время: 00:00:00.31 
Многие люди по разным причинам предпочитают делать это так, как показано ниже: 
ops$tkyte@ORA10G> begin
2 for x in ( select rowid rid, object_name, rownum r
3 from t2 )
4 loop
5 update t2
6 set object_name = lower(x.object_name)
7 where rowid = x.rid;
8 if ( mod(x.r,100) = 0 ) then
9 commit;
10  end if; 
11 end loop;
12 commit;
13 end;
14 / 
PL/SQL procedure successfully completed.
Процедура PL/SQL успешно завершена. 
Elapsed: 00:00:05.38
Общее время: 00:00:05.38 
На этом простом примере видно, что многократная фиксация в цикле в не­сколько раз замедляет операцию. Если вы можете сделать что-то единственным оператором SQL, так и делайте — это почти наверняка будет быстрее. Даже если “оптимизировать” код процедуры, используя групповую обработку обновлений, как показано ниже: 
ops$tkyte@ORA10G> declare

9 begin
10  open c; 11 loop12 fetch c bulk collect into l_rids, l_names LIMIT 100;13 forall i in 1 .. l_rids.count 14    update t2 15 set object_name = lower(l_names(i))16 where rowid = l_rids(i);17 commit;18 exit when c%notfound;19   end loop; 20   close c; 21 end;22 / 
PL/SQL procedure successfully completed.
Процедура PL/SQL успешно завершена. 
Elapsed: 00:00:02.36
Общее время: 00:00:02.36 
будет действительно намного быстрее, но все же много медленнее, чем могло бы быть. И, кроме того, вы должны заметить, что код становится все более и более сложным. От предельной простоты единственного оператора UPDATE к процедур­ному коду, затем к еще более сложному процедурному коду — мы явно движемся в неверном направлении! 
Теперь, просто чтобы поддержать контрапункт этой дискуссии, вспомним гла­ву 7, где мы говорили о концепции согласованной записи и о том, как оператор UPDATE, например, может автоматически перезапускаться. В случае, когда про­цедурный оператор UPDATE должен работать с подмножеством записей (имея кон­струкцию WHERE), а другие пользователи модифицируют столбцы, которые этот оператор UPDATE использует в своей конструкции WHERE, тогда имеет смысл либо использовать серии мелких транзакций вместо одной большой, или же блокиро­вать таблицу перед тем, как выполнять массовое обновление. Целью этого является снижение вероятности перезапусков. Если мы собираемся обновить UPDATE значи­тельную часть строк таблицы, это приводит к необходимости применения коман­ды LOCK TABLE. Согласно моему опыту, однако, подобного рода массовые обновле­ния или массовые удаления (только этого типа операторы могут быть субъектами перезапуска) выполняются в изоляции. Такие крупные единовременные пакетные 
обновления или удаления старых данных обычно не выполняются в период высо­кой активности. В самом деле, удаление данных вообще не должно быть затрону­то этим, поскольку вы обычно работаете с некоторыми полями типа даты, чтобы найти старую информацию, подлежащую удалению, а другие приложения обычно эти даты не модифицируют. 
 









jAntivirus