UNUSED COLUMNS и дисковое пространствоИсточник: oracle
На написание этого небольшого материала автора подтолкнул очередной вопрос разработчиков о том, каково влияние операции SET UNUSED COLUMN на последующий расход дискового пространства. Вопрос вовсе не праздный, если учесть современные объемы данных и время, потребное для их реорганизации. Поэтому автор решил продемонстрировать, а что же собственно происходит, когда выполняется операция SET UNUSED COLUMN. Начнем с того, что весьма распространено заблуждение, гласящее, что unused column удаляется из словаря данных. Разумеется, это не так, и существуют представления ..._TAB_COLS, позволяющие увидеть, что происходит с полями, помеченными как UNUSED. SQL> CREATE TABLE table1(x int primary key); Table created. SQL> CREATE TABLE table2(x int, y int default 0, 2 constraint y_c1 primary key(y), 3 constraint y_c2 foreign key(y) references table1(x), 4 constraint y_c3 check (y > 0)); Table created. SQL> col data_default format a10 SQL> col nullable format a10 SQL> col column_name format a30 SQL> col hidden_column format a10 SQL> select column_name, data_default, nullable, hidden_column 2 from user_tab_cols where table_name = 'TABLE2'; COLUMN_NAME DATA_DEFAU NULLABLE HIDDEN_COL ------------------------------ ---------- ---------- ---------- X Y NO Y 0 N NO SQL> select constraint_name, constraint_type from user_constraints 2 where table_name = 'TABLE2'; CONSTRAINT_NAME C ------------------------------ - Y_C3 C Y_C1 P Y_C2 R SQL> alter table table2 set unused column y; Table altered. SQL> select column_name, data_default, nullable, hidden_column 2 from user_tab_cols where table_name = 'TABLE2'; COLUMN_NAME DATA_DEFAU NULLABLE HIDDEN_COL ------------------------------ ---------- ---------- ---------- X Y NO SYS_C00002_09100918:16:50$ Y YES SQL> select constraint_name, constraint_type from user_constraints 2 where table_name = 'TABLE2'; no rows selected В-общем, этого можно было ожидать - Oracle переименовал колонку, присвоив ей сгенерированное системой имя, и - что существенно - отменил наложенное на нее ограничение NOT NULL и значение по умолчанию DEFAULT. Кроме того, исчезли все ограничения, связанные с этой колонкой - PRIMARY KEY, FOREIGN KEY и CHECK. Осталась скрытая от конечного пользователя колонка с системным именем, допускающая хранение NULL-величин и не имеющая значения по умолчанию. Логично предположить, что при операциях вставки это поле неявным образом будет учитываться при формировании физической записи внутри блока -несмотря на то, что разработчик более не имеет с ним дела явно. В противном случае Oracle потребовалось бы каким-то образом отличать "старые" записи - когда поле было еще "живым", от новых, когда поле уже "умерло". Этакий кот Шредингера внутри базы данных... Давайте выполним несколько простых манипуляций и посмотрим на содержимое блока таблицы после их завершения. SQL> CREATE TABLE T_EXP (x int, y varchar2(254)) 2 / Table created. SQL> insert into T_EXP values(1,'a'); 1 row created. SQL> commit; Commit complete. SQL> alter table t_EXP set unused column y; Table altered. SQL> insert into T_EXP values(2); 1 row created. SQL> commit; Commit complete. SQL> alter table t_exp add (y varchar2(255)); Table altered. SQL> insert into T_EXP values(3,'b'); 1 row created. SQL> commit; Commit complete. SQL> select distinct dbms_rowid.rowid_relative_fno(rowid) "file", 2 dbms_rowid.rowid_block_number(rowid) "block" 3 from T_exp; file block ---------- ---------- 9 599 SQL> alter system dump datafile 9 block 599; System altered. Дамп блока содержит следующую информацию tab 0, row 0, @0x1f90 tl: 8 fb: --H-FL-- lb: 0x0 cc: 2 col 0: [ 2] c1 02 col 1: [ 1] 61 tab 0, row 1, @0x1f8a tl: 6 fb: --H-FL-- lb: 0x0 cc: 1 col 0: [ 2] c1 03 tab 0, row 2, @0x1f81 tl: 9 fb: --H-FL-- lb: 0x1 cc: 3 col 0: [ 2] c1 04 col 1: *NULL* col 2: [ 1] 62 Итак, наши подозрения вполне подтвердились - поле, помеченное как unused ведет себя как самое обычное nullable - поле со значением по умолчанию NULL. И если это поле не является последним в словарном списке колонок таблицы (в соответствии со значением поля COLUMN_ID), то при внесении каждой новой записи или изменении старой оно будет добавлять 1 байт, содержащий значение 0xFF, к общему содержимому записи в блоке - при условии, если хотя бы одна колонка, следующая за ней, принимает значение, отличное от NULL. |