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