The output of the procedure contains used_bytes and alloc_bytes :
- The used_bytes : represent the actual bytes used by the data. This includes the overhead due to the block metadata, pctfree etc.
- The alloc_bytes : represent the size of the table segment when it is created in the tablespace. This takes into account, the size of the extents in the tablespace and tablespace extent management properties.
Example for using Version 1:
This methode requires creating the table first with some sample data to calculate the average row size of the table ,
create table test (a NUMBER (10) , b VARCHAR2 (30) ,c VARCHAR2 (30), d date ) tablespace USERS pctfree 10;
INSERT INTO test VALUES (9999999999,'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' ,'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa',sysdate);
INSERT INTO test VALUES (9999999,'aaaaaaaaaaaaaaaaaaa' ,'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa',sysdate);
INSERT INTO test VALUES (999999,'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' ,'aaaaaaaaaaaaaaaaaa',sysdate);
exec DBMS_STATS.GATHER_TABLE_STATS (ownname=>'hr',tabname=>'test',estimate_percent=>100,block_sample=>true,method_opt=>'FOR ALL COLUMNS size 254');
select AVG_ROW_LEN from user_tables where TABLE_NAME='TEST';
AVG_ROW_LEN
-----------
68
Drop table test;
set serveroutput on
DECLARE
ub NUMBER;
ab NUMBER;
BEGIN
DBMS_SPACE.CREATE_TABLE_COST('USERS',68,100000,10,ub,ab);
DBMS_OUTPUT.PUT_LINE('Used Bytes = ' || TO_CHAR(ub));
DBMS_OUTPUT.PUT_LINE('Allocated Bytes = ' || TO_CHAR(ab));
END;
/
Used Bytes = 8036352
Allocated Bytes = 8388608
which is around 8 MB , now lets create and populate the actual table.
create table test (a NUMBER (10) , b VARCHAR2 (30) ,c VARCHAR2 (30), d date ) tablespace USERS pctfree 10;
BEGIN
FOR i IN 1..100000 LOOP
INSERT INTO test VALUES (i,'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' ,'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa',sysdate);
END LOOP;
END;
/
select BYTES,SEGMENT_TYPE from user_segments where SEGMENT_NAME='TEST';
BYTES SEGMENT_TYPE
---------- ------------------
9437184 TABLE
which is around 9 MB
Example for using Version 2:
This example estimate a Table size with one column NUMBER (10) , two columns VARCHAR2 (30) and one column date , with pct_free=10 and row_count=100000 :
set serveroutput on
DECLARE
ub NUMBER;
ab NUMBER;
cl sys.create_table_cost_columns;
BEGIN
cl := sys.create_table_cost_columns( sys.create_table_cost_colinfo('NUMBER',10),
sys.create_table_cost_colinfo('CHAR',30),
sys.create_table_cost_colinfo('CHAR',30),
sys.create_table_cost_colinfo('DATE',NULL));
DBMS_SPACE.CREATE_TABLE_COST('USERS',cl,100000,10,ub,ab);
DBMS_OUTPUT.PUT_LINE('Used Bytes = ' || TO_CHAR(ub));
DBMS_OUTPUT.PUT_LINE('Allocated Bytes = ' || TO_CHAR(ab));
END;
/
Used Bytes = 9314304
Allocated Bytes = 9437184
which is around 9 MB , now lets create and populate the actual table.
Note : we changed VARCHAR2 to CHAR to get the maximum possible estimation .
create table test (a NUMBER (10) , b VARCHAR2 (30) ,c VARCHAR2 (30), d date ) tablespace USERS pctfree 10;
BEGIN
FOR i IN 1..100000 LOOP
INSERT INTO test VALUES (i,'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' ,'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa',sysdate);
END LOOP;
END;
/
select BYTES,SEGMENT_TYPE from user_segments where SEGMENT_NAME='TEST';
BYTES SEGMENT_TYPE
---------- ------------------
9437184 TABLE
which is around 9 MB
You may notice that version 2 of The CREATE_TABLE_COST procedure is more accurate than version 1 , which is expected because version 2 estimates the size based on the table structure which includes the column data types and length , plus the storage attributes .
Estimate The Size Of Indexes
The CREATE_INDEX_COST Procedure of the DBMS_SPACE package helps to estimate the size of creating an index on an existing table.
The input is the DDL statement that will be used to create the index. The procedure will output the storage required to create the index.
Usage Notes :
- The table on which the index is created must already exist.
- The computation of the index size depends on statistics gathered on the segment.
- It is imperative that the table must have been analyzed recently.
- In the absence of correct statistics, the results may be inaccurate, although the procedure will not raise any errors.
The output of the procedure contains used_bytes and alloc_bytes :
- The used_bytes : how much space is for the index data
- The alloc_bytes : how much space is allocated within the tablespace for the index segment.
Estimate Index Size example :
create table test (a NUMBER (10) , b VARCHAR2 (30) ,c VARCHAR2 (30), d date ) tablespace USERS pctfree 10;
BEGIN
FOR i IN 1..100000 LOOP
INSERT INTO test VALUES (9999999999,'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' ,'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa',sysdate);
END LOOP;
END;
/
exec DBMS_STATS.GATHER_TABLE_STATS (ownname=>'hr',tabname=>'test',estimate_percent=>100,block_sample=>true,method_opt=>'FOR ALL COLUMNS size 254');
set serveroutput on
declare
l_used_bytes number;
l_alloc_bytes number;
begin
dbms_space.create_index_cost (
ddl => 'create index test_indx on test (a,b) tablespace users',
used_bytes => l_used_bytes,
alloc_bytes => l_alloc_bytes
);
dbms_output.put_line ('Used Bytes = '||l_used_bytes);
dbms_output.put_line ('Allocated Bytes = '||l_alloc_bytes);
end;
/
Used Bytes = 3800000
Allocated Bytes = 6291456
which is around 6 MB , now lets create the actual index.
create index test_indx on test (a,b) tablespace users
select BYTES,SEGMENT_TYPE from user_segments where SEGMENT_NAME='TEST_INDX';
BYTES SEGMENT_TYPE
---------- ------------------
6291456 INDEX
which is around 6 MB
Reference oracle support (Doc ID 1585326.1)