テーブル容量見積

 

(19c)

http://otndnld.oracle.co.jp/skillup/oracle9i/3_1/index.html


【1】見積手順

1. 1レコードの平均長を求める

[1レコードの平均長] = [レコードヘッダ] + Σ([列ヘッダ] + [列データ])

[レコードヘッダ] = 3バイト

[列ヘッダ] = 対応する列のデータ長が250バイト以下(NULL含む)の場合は1バイト、251バイト以上の場合は3バイト

[列データ]
CHAR → テーブル定義の長さ
VARCHAR2 → 実際に格納されているデータの長さ
NUMBER → 1 + CEIL(n / 2) ; nは格納された数値の整数部・小数部を合わせた総桁数。n>38の場合は38
DATE → 7バイト
TIMESTAMP → 11バイト

※vsize関数で内部表現でのバイト数を確認可能

2. 1ブロックに収まるレコード数を求める

[ブロックヘッダ] = 90 + [INITRANS] - 1

[予備領域] = CEIL( ([ブロックサイズ] - [ブロックヘッダ]) * [PCTFREE])

[データ格納部] = [ブロックサイズ] - [ブロックヘッダ] - [予備領域]

[1ブロックに収まるレコード数] = TRUNC([データ格納部] / [1レコードの平均長])

3. テーブル容量算出


[テーブル容量] = CEIL( [レコード件数] / [1ブロックに収まるレコード数]) * [ブロックサイズ]

 

【2】計算例
前提:
下記デフォルト値を使用する
[ブロックサイズ] = 8192バイト
[INITRANS] = 1
[PCTFREE] = 10%

データ件数 = 100万件

対象テーブル定義:
create table tab1(col1 number(12,3),col2 varchar2(10),col3 date);

[1レコードの平均長]= 3 + {(1 + 9) + (1 + 10) + (1 + 7)} = 32
[ブロックヘッダ] = 90 + 1 - 1 = 90
[予備領域] = CEIL( (8192 - 90) * 0.1) = 811
[データ格納部] = 8192 - 90 - 811 = 7291
[1ブロックに収まるレコード数] = TRUNC(7291/32) = 227
[テーブル容量] = CEIL( 1000000/227 ) * 8192 = 36093952 ≒ 34 Mバイト

 

【3】実測値との比較

declare
begin
for i in 1..1000000 loop
insert into tab1 values(100,'1234567890',sysdate);
commit;
end loop;
end;
/

select sum(bytes/1024/1024) from user_segments where segment_name = 'TAB1';

→ 30Mバイトとなりおよそ一致

 

【4】dbms_space.create_table_costプロシージャとの比較
http://system3support.jp/pdf/oracle_knowledge/606_meaningful/p204.pdf


set serveroutput on
declare
used_bytes number;
alloc_bytes number;
c1 sys.create_table_cost_columns;
begin
c1 := sys.create_table_cost_columns(
sys.create_table_cost_colinfo( 'number', 12 ),
sys.create_table_cost_colinfo( 'varchar2', 10 ),
sys.create_table_cost_colinfo( 'date', null )
) ;

dbms_space.create_table_cost( 'USERS', c1, 1000000, 10, used_bytes, alloc_bytes );
dbms_output.put_line( 'ユーザーデータ使用サイズ(MB)' || to_char( used_bytes/1024/1024 ) );
dbms_output.put_line( '割当てサイズ(MB)' || to_char( alloc_bytes/1024/1024 ) );
end;
/

→ 35Mバイトとなりおよそ一致

 


https://dev.mysql.com/doc/refman/5.6/ja/storage-requirements.html
https://dev.mysql.com/doc/refman/5.6/ja/innodb-physical-record.html
https://dev.mysql.com/doc/refman/5.6/ja/innodb-physical-structure.html


【1】見積手順

1. 1レコードの平均長を求める

[1レコードの平均長] = [レコードヘッダ] + [可変長ヘッダ] + Σ([列ヘッダ] + [列データ])


[レコードヘッダ] = 5バイト
[可変長ヘッダ] = CEILING(N/8) ;NはNULLにすることができるカラム数

[列ヘッダ]
→ 0バイト ; 対応する列がNULL可変長フィールドや固定長フィールドの場合
→ 1バイト ; 対応する列が非NULL可変長でデータ長が127バイト以下の場合
→ 2バイト ; 対応する列が非NULL可変長でデータ長が128バイト以上の場合


[列データ]

CHAR(M) → 実バイト数
VARCHAR(M) → 文字数Mに対するバイト長Lが255以下の場合実バイト数+1、Lが256以上の場合実際のバイト数+2
INTEGER → 4バイト
DATE → 3バイト
DATETIME → 5 バイト + 小数秒ストレージ(0~3バイト)


2. 1ブロックに収まるレコード数を求める

[fillfactor] = 15/16
[データ格納部] = TRUNC([ブロックサイズ] * [fillfactor])

[1ブロックに収まるレコード数] = TRUNC([データ格納部] / [1レコードの平均長])

3. テーブル容量算出

[テーブル容量] = CEIL( [レコード件数] / [1ブロックに収まるレコード数]) * [ブロックサイズ]


【2】計算例
前提:
下記デフォルト値を使用する
[ブロックサイズ] = 16384バイト

データ件数 = 100万件

対象テーブル定義:
create table tab1(col1 int not null primary key,col2 varchar(10),col3 datetime);


[1レコードの平均長] = 5 + 1 + {(1+4) + (1+10+1) + (0+5)} = 28
[データ格納部] = TRUNC( 16384 * 15/16 ) = 15360
[1ブロックに収まるレコード数] = TRUNC( 15360/28 ) = 548
[テーブル容量] = CEIL( 1000000 / 548 ) * 16384 = 29900800 = 29 Mバイト


【3】実測値との比較

drop procedure proc1;

delimiter //
create procedure proc1()
begin
declare i int;

set i = 1;

while i <= 1000000 do
insert into tab1 values(i,'1234567890',CURRENT_TIMESTAMP);
set i = i + 1;
end while;
end
//
delimiter ;


call proc1();


SELECT
table_name, engine, table_rows AS tbl_rows,
avg_row_length AS rlen,
floor( (data_length+index_length)/1024/1024) AS allmb, #総容量
floor( (data_length)/1024/1024) AS dmb, #データ容量
floor( (index_length)/1024/1024) AS imb #インデックス容量
FROM
information_schema.tables
WHERE
table_schema = database()
AND
table_name = 'tab1'
;

→ 37Mバイトとなりおよそ一致

【1】見積手順

1. 1レコードの平均長を求める

[1レコードの平均長] = [タプルヘッダ] + [ラインポインタ] + Σ([列データ])

[タプルヘッダ] = 24バイト
[ラインポインタ] = 4バイト

[列データ]
char(n) → 文字数nに対するバイト長Nが125以下の場合N+1、126以上の場合N+4
varchar(n) → 文字数nに対するバイト長Nが125以下の場合実バイト数+1、126以上の場合実バイト数+4
integer → 4バイト
date → 4バイト
timestamp → 8バイト


2. 1ブロックに収まるレコード数を求める

[ページヘッダ] = 24バイト

[データ格納部] = TRUNC([ブロックサイズ] * [fillfactor] - [ページヘッダ])

[1ブロックに収まるレコード数] = TRUNC([データ格納部] / [1レコードの平均長])

3. テーブル容量算出


[テーブル容量] = CEIL( [レコード件数] / [1ブロックに収まるレコード数]) * [ブロックサイズ]


【2】計算例
前提:
下記デフォルト値を使用する
[ブロックサイズ] = 8192バイト
[fillfactor] = 100%

データ件数 = 100万件

対象テーブル定義:
create table tab1(col1 integer,col2 varchar(10),col3 timestamp);


[1レコードの平均長]= 24 + 4 + (4 + 10+1 + 8) = 51
[データ格納部] = TRUNC(8192 * 1 - 24) = 8168
[1ブロックに収まるレコード数] = TRUNC(8168/51) = 160
[テーブル容量] = CEIL( 1000000/160 ) * 8192 = 51200000 ≒ 49 Mバイト


【3】実測値との比較


insert into tab1 select generate_series(1,1000000),'1234567890',now();

SELECT pg_size_pretty(pg_relation_size('tab1'));

→ 50Mバイトとなりおよそ一致

 

https://docs.microsoft.com/ja-jp/sql/relational-databases/databases/estimate-the-size-of-a-table?redirectedfrom=MSDN&view=sql-server-ver15
https://docs.microsoft.com/ja-jp/sql/t-sql/data-types/data-types-transact-sql?view=sql-server-ver15


【1】見積手順

1. 1レコードの平均長を求める

[1レコードの平均長] = [レコードヘッダ] + [NULLビットマップ] + [可変長列追跡] + Σ([列データ])

[レコードヘッダ] = 4バイト
[NULLビットマップ] = TRUNC( 2 + ( ( 列総数 + 7) / 8) )
[可変長列追跡] = 2 + ( 可変長列の数 * 2)

[列データ]
char(n) → n
varchar(n) → n+2
int → 4バイト
date → 3バイト
datetime2 → 9バイト


2. 1ブロックに収まるレコード数を求める

[ページヘッダ] = 96バイト

[データ格納部] = [ブロックサイズ] - [ページヘッダ]

[1ブロックに収まるレコード数] = TRUNC([データ格納部] / ([1レコードの平均長] + 2) )

3. テーブル容量算出


[テーブル容量] = CEIL( [レコード件数] / [1ブロックに収まるレコード数]) * [ブロックサイズ]


【2】計算例
前提:
下記デフォルト値を使用する
[ブロックサイズ] = 8192バイト

データ件数 = 100万件
テーブルタイプ = ヒープ

対象テーブル定義:
create table tab1(col1 int,col2 varchar(10),col3 datetime2);


[1レコードの平均長]= 4 + 3 + { 2 + (1 * 2) } + { 4 + (10+2) + 9 } = 36

[データ格納部] = 8192 - 96 = 8096

[1ブロックに収まるレコード数] = TRUNC(8096/(36 + 2)) = 213

[テーブル容量] = CEIL( 1000000/213 ) * 8192 = 38461440 ≒ 37 Mバイト


【3】実測値との比較

DECLARE @counter int;
SET @counter = 1;

WHILE (@counter <= 1000000)
BEGIN
INSERT INTO tab1 VALUES (@counter,'1234567890', GETDATE());
SET @counter = @counter + 1;
END
go


EXEC sp_spaceused 'dbo.tab1';
go


→ 36Mバイトとなりおよそ一致