set serveroutput on; DECLARE total_blocks NUMBER; total_bytes NUMBER; unused_blocks NUMBER; unused_bytes NUMBER; last_used_extent_file_id NUMBER; last_used_extent_block_id NUMBER; last_used_block NUMBER; BEGIN DBMS_SPACE.UNUSED_SPACE( segment_owner => 'CONFIG_XD', segment_name => 'CONFIG_PARS', segment_type => 'TABLE', total_blocks => total_blocks, total_bytes => total_bytes, unused_blocks => unused_blocks, unused_bytes => unused_bytes, last_used_extent_file_id => last_used_extent_file_id, last_used_extent_block_id => last_used_extent_block_id, last_used_block => last_used_block); DBMS_OUTPUT.PUT_LINE('total_blocks '||total_blocks); DBMS_OUTPUT.PUT_LINE('total_bytes '||total_bytes); DBMS_OUTPUT.PUT_LINE('unused_blocks '||unused_blocks); DBMS_OUTPUT.PUT_LINE('unused_bytes '||unused_bytes); DBMS_OUTPUT.PUT_LINE('last_used_extent_file_id '||last_used_extent_file_id); DBMS_OUTPUT.PUT_LINE('last_used_extent_block_id '||last_used_extent_block_id); DBMS_OUTPUT.PUT_LINE('last_used_block '||last_used_block); END; /
Для сегментирования таблицы по одному полю и применения дополнительных параметров для другого, выполняем следующее:
CREATE TABLE "TABLE_NEW" ( "CARD_ID" CHAR(32 BYTE) NOT NULL ENABLE, "FILE_CATEGORY" NUMBER(4,0) NOT NULL ENABLE, "FILE_CONTENT" BLOB, PRIMARY KEY ("CARD_ID") USING INDEX PCTFREE 10 INITRANS 2 MAXTRANS 255 COMPUTE STATISTICS STORAGE( INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645 PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT ) TABLESPACE "USERS" ENABLE ) TABLESPACE USERS LOB ( "FILE_CONTENT" ) STORE AS BASICFILE ( TABLESPACE USERS ENABLE STORAGE IN ROW CHUNK 8192 NOCACHE LOGGING STORAGE( INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645 PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT ) ) PARTITION BY LIST ("FILE_CATEGORY") ( PARTITION p1 values (1) LOB ("FILE_CONTENT") STORE AS SECUREFILE( NOCACHE NOLOGGING DECRYPT COMPRESS HIGH DEDUPLICATE LOB ), PARTITION p4 values (4), PARTITION p5 values (5) );
В этом примере нужно обратить внимание на:
PARTITION BY LIST ("FILE_CATEGORY") ( PARTITION p1 values (1) LOB ("FILE_CONTENT") STORE AS SECUREFILE( NOCACHE NOLOGGING DECRYPT COMPRESS HIGH DEDUPLICATE LOB ),
Как видно из приведённого примера, сегментирование таблицы выполняется по полю FILE_CATEGORY, но, если поле FILE_CATEGORY имеет значение "1" (единица), для поля FILE_CONTENT типа LOB применяются дополнительные параметры, в частности COMPRESS.
В данном случае STORAGE для LOB выбран как SECUREFILE, так как в противном случае вы получаете ошибку "ORA-43854: использование BASICFILE LOB, когда ожидался SECUREFILE LOB"
Чтобы узнать, с какими параметрами была создана таблица, можно выполнить следующий запрос (от DBA):
SELECT DBMS_METADATA.GET_DDL('TABLE','TABLE_NAME','SCHEMA') FROM dual;
для владельца схемы можно упростить:
SELECT DBMS_METADATA.GET_DDL('TABLE','TABLE_NAME') FROM dual;
Наши разработчики знали, что им пригодятся партиции, но не было достаточных данных для определения критериев сегментирования. В связи с этим я создал партиционированную таблицу, которую в будущем предполагалось делить на "вменяемые" партиции. Покажу на примере. Создаём таблицу:
create table doc_type ( doc_type varchar(255) primary key not null ) partition by list (doc_type) ( partition other values(default) );
Вставляем данные:
insert into doc_type values ('Ар1'); insert into doc_type values ('Ар2'); insert into doc_type values ('Ар3'); insert into doc_type values ('Ар4');
Смотрим:
select table_name, partition_name, high_value from user_tab_partitions;
TABLE_NAME PARTITION_NAME HIGH_VALUE ------------------------------ ------------------------------ ----------------------------------------------------------- DOC_TYPE OTHER default
Теперь делим существующую партицию на две:
alter table doc_type split partition other values ('Ар1') into (partition ar1, partition other);
Здесь:
split partition other
- разделить партицию other
;
values ('Ар1')
- по значению "Ар1"
;
into (partition ar1, partition other)
- даные, соответствующие критерию, поместить в партицию ar1
, всё остальное оставить в other
.
Повторяем, при необходимости, операцию.
Смотрим теперь:
select table_name, partition_name, high_value from user_tab_partitions;
TABLE_NAME PARTITION_NAME HIGH_VALUE ------------------------------ ------------------------------ ----------------------------------------------------------- DOC_TYPE AR1 'Ар1' DOC_TYPE OTHER default
Ещё один полезный запрос:
select * from doc_type partition(other);
Он покажет данные, расположенные именно в партиции other
, а их уже можно использовать для очередного разделения этой партиции.
Эта операция обратная вышеописанной.
select table_name, partition_name, high_value from user_tab_partitions;
TABLE_NAME PARTITION_NAME HIGH_VALUE ------------------------------ ------------------------------ ----------------------------------------------------------- DOC_TYPE AR1 'Ар1' DOC_TYPE OTHER default
Операция тоже довольно проста:
alter table doc_type merge partitions ar1,other into partition other;
Здесь:
merge partitions ar1,other
- объединить партиции ar1
и other
;
into partition other
- даные обеих партиций поместить в партицию other
.
Повторяем, при необходимости, операцию.
Смотрим теперь:
select table_name, partition_name, high_value from user_tab_partitions;
TABLE_NAME PARTITION_NAME HIGH_VALUE ------------------------------ ------------------------------ ----------------------------------------------------------- DOC_TYPE OTHER default