Одной из возможных причин низкой производительности является цепочка строк. Все ваши строки изначально имеют столбцы C3 и C4 null, а затем вы обновляете их все, чтобы иметь значение. Новые данные не будут вписываться в существующие блоки, поэтому Oracle должен связать строки в новые блоки.
Если вы заранее знаете, что будете этим заниматься, вы можете заранее выделить достаточно свободного места, например:
CREATE TABLE J_TEST
(
ID NUMBER(10) PRIMARY KEY,
C1 VARCHAR2(50 BYTE),
C2 VARCHAR2(250 BYTE),
C3 NUMBER(5),
C4 NUMBER(10)
) PCTFREE 40;
... где PCTFREE указывает процент пространства для хранения обновлений. По умолчанию установлено значение 10, что недостаточно для этого примера, где строки более или менее удваиваются в размере (от средней длины от 8 до 16 байт в соответствии с моей базой данных).
Этот тест показывает разницу:
SQL> CREATE TABLE J_TEST
2 (
3 ID NUMBER(10) PRIMARY KEY,
4 C1 VARCHAR2(50 BYTE),
5 C2 VARCHAR2(250 BYTE),
6 C3 NUMBER(5),
7 C4 NUMBER(10)
8 );
Table created.
SQL> insert into j_test (id)
2 select rownum
3 from transactions
4 where rownum < 100000;
99999 rows created.
SQL> update j_test
2 set C3 = 1,
3 C2 = 'NEU'
4 /
99999 rows updated.
Elapsed: 00:01:41.60
SQL> analyze table j_test compute statistics;
Table analyzed.
SQL> select blocks, chain_cnt from user_tables where table_name='J_TEST';
BLOCKS CHAIN_CNT
---------- ----------
694 82034
SQL> drop table j_test;
Table dropped.
SQL> CREATE TABLE J_TEST
2 (
3 ID NUMBER(10) PRIMARY KEY,
4 C1 VARCHAR2(50 BYTE),
5 C2 VARCHAR2(250 BYTE),
6 C3 NUMBER(5),
7 C4 NUMBER(10)
8 ) PCTFREE 40;
Table created.
SQL> insert into j_test (id)
2 select rownum
3 from transactions
4 where rownum < 100000;
99999 rows created.
SQL> update j_test
2 set C3 = 1,
3 C2 = 'NEU'
4 /
99999 rows updated.
Elapsed: 00:00:27.74
SQL> analyze table j_test compute statistics;
Table analyzed.
SQL> select blocks, chain_cnt from user_tables where table_name='J_TEST';
BLOCKS CHAIN_CNT
---------- ----------
232 0
Как вы можете видеть, с PCTFREE 40 обновление занимает 27 секунд вместо 81 секунды, а полученная таблица потребляет 232 блока без цепочек вместо 694 блоков с 82034 цепочками строк!