Upload
hoangduong
View
240
Download
1
Embed Size (px)
Citation preview
領領領領域域域域ササササイイイイズズズズのののの見見見見積積積積ももももりりりり方方方方法法法法考考考考慮慮慮慮事事事事項項項項おおおおよよよよびびびび記記記記憶憶憶憶領領領領域域域域パパパパララララメメメメーーーータタタタのののの設設設設定定定定
White Paper
領域サイズ見積もり方法
1998年 3月 初版1998年7月 改訂版 NULL列のオーバーヘッドに関する項目を追加1998年 9月 改訂 2版 リリース 8.03マニュアルの内容を反映
日本オラクル株式会社 Design & Migration Services著作権 ©Oracle Corporation Japan 1998版版版版権権権権所所所所有有有有 Printed in Japan
この文書は情報の提供のみを意図したもので、ここに記載された情報は予告なしに変わることがあります。文書中に万一誤りなど、お気付きの点がありましたら、ご連絡をお願いいたします。オラクル社は、この情報を一切保証するものではなく、この文書に関するいかなる責任も負いかねますのでご了承ください。
Oracle and SQL*Loader are registered trademarks.Oracle7は Oracle Corporationの商標です。
上記以外の製品名あるいは会社名はいずれも、製品を指し示すだけの目的で使用しており、その製品等を推奨するものではありません。また、各所有者の商標である場合もあります。
1
領領領領域域域域ササササイイイイズズズズ見見見見積積積積ももももりりりり方方方方法法法法考考考考慮慮慮慮事事事事項項項項とととと記記記記憶憶憶憶領領領領域域域域パパパパララララメメメメーーーータタタタのののの設設設設定定定定
ははははじじじじめめめめにににに
この資料では、特定のオブジェクトの領域を概算する際に役立つ公式を説明します。また、計算結果を目安として、オブジェクトを作成する時のパラメータの選び方と注意事項についても説明します。なお、この資料は以下のセクションに分かれています。
· 表サイズの見積もり
· 索引サイズの見積もり
· 記憶領域パラメータ値の設定と注意事項
· おわりに
オブジェクトの領域の大きさを見積もることにより、作成するオブジェクトを格納するために必要なディスク容量を決定することができます。また、記憶領域パラメータを適切に設けることにより、Oracle の機能が最大限に発揮されない原因となる I/Oのパフォーマンスを改善することができます。
ここで説明する見積もり方法を理解するためには、データ・ブロック、エクステント、セグメント、表領域といった Oracle の論理データベース構造、および記憶領域単位についての知識が必要です。Oracle の論理データベース構造、および記憶領域単位については『Oracle8 Server 概要』第 2 章「データ・ブロック、エクステント、セグメント」を参考にしてください。
DMSグループでは、本書で説明する計算方法を用い、自動的に表および索引サイズを計算する EXCEL アプリケーション・ツール「領域サイズ見積シート」を提供しています。本書での見積もり方法を理解した上で、本書とともに実際の見積作業にお役立てください。
2
表表表表ササササイイイイズズズズのののの見見見見積積積積ももももりりりり ここでは、表サイズを見積もる方法を説明します。クラスタ表やインデックス構成表、オブジェクト・テーブルは含まれません。ここで算出される値は、理想な状態でデータが格納された場合の理論値です。実際には削除や更新があるので、理想的な状態で格納されるわけではありません。この計算値を最低限必要な値と考え、10~20%大きめに見積ってください。
表サイズの見積に必要な情報を以下に示します。l 表の行数l 各列の平均的な長さとデータ型l データ・ブロック・サイズl PCTFREE、INITRANSの値l V$TYPE_SIZE中の値
以下の手順に従って、表の大きさを見積もります。1. ブロック・ヘッダ領域サイズを計算します。2. データ・ブロック当たりの利用可能なデータ領域サイズを計算します。3. 行あたりに利用される領域サイズを計算します。4. データ・ブロックに格納可能な平均行数を計算します。5. 表に必要なブロック数とバイト数を計算します。
計算を実行する前に、表および索引サイズの計算に必要となる定数をV$TYPE_SIZEを検索して取得しておきます。
例 Windows95、Oracle8 Personal Edition Release 8.0.4.0.0 での V$TYPE_SIZE検索結果
SQL> select type, type_size from v$type_size 2 where type in ('KCBH','UB4','KTBBH','KTBIT','KDBH','KDBT','UB1','SB2');
TYPE TYPE_SIZE-------- ---------UB1 1UB4 4SB2 2KCBH 20KTBIT 24KTBBH 48KDBH 14KDBT 4
8行が選択されました。;
本書の表および索引の見積計算例では、これらの値を使用します。
3
1111....ブブブブロロロロッッッックククク・ヘッダ領域サイズの計算・ヘッダ領域サイズの計算・ヘッダ領域サイズの計算・ヘッダ領域サイズの計算
データ・ブロックの構成を図 1に示します。データ・ブロックには、まずブロック・ヘッダが格納されます。そしてヘッダ以降の領域中、PCTFREEの値によって決定される利用可能領域に行データが格納されます。
PCTFREE:現行ブロック更新のために確保する領域の割合。
行行行行デデデデ ーーーー タタタタ
行行行行ヘヘヘヘッッッッダダダダ
利利利利用用用用可可可可能能能能領領領領域域域域
共共共共通通通通ヘヘヘヘッッッッダダダダ ((((KKKKCCCCBBBBHHHH))))
固固固固定定定定トトトトラララランンンンザザザザククククシシシショョョョンンンン・・・・ヘヘヘヘッッッッダダダダ ((((KKKKTTTTBBBBBBBBHHHH))))
可可可可変変変変トトトトラララランンンンザザザザククククシシシショョョョンンンン・・・・ヘヘヘヘッッッッダダダダ((((KKKKTTTTBBBBIIIIT T T T * * * * ((((IIIINNNNIIIITTTTRRRRAAAANNNNSSSS----1111))))))))
デデデデ ーーーー タタタタ・・・・ヘヘヘヘッッッッダダダダ ((((KKKKDDDDBBBBHHHH))))
表表表表デデデデ ィィィィレレレレククククトトトトリリリリ ((((KKKKDDDDBBBBTTTT****表表表表数数数数))))
UUUUBBBB4444
図図図図 1::::デデデデーーーータタタタ・・・・ブブブブロロロロッッッックククク形形形形式式式式
ブロック・ヘッダ領域が必要とするサイズは、次の公式によって算出できます。
ブブブブロロロロッッッックククク・・・・ヘヘヘヘッッッッダダダダ領領領領域域域域==== KCBH + UB4 + KTBBH + (INITRANS - 1) * KTBIT + KDBH
ここで、KCBH、、、、UB4、、、、KTBBH、、、、KTBIT、、、、KDBH
:V$TYPE_SIZEを検索することで得られる定数
INITRANS :割り当てられたトランザクション・エントリの初期数。この値は 1~255 までの範囲内であり、デフォルト値は 1となります。通常このデフォルト値を変更することはありません。
例 INITRANS = 1 と仮定してヘッダーサイズを計算します。ブロック・ヘッダ領域= KCBH + UB4 + KTBBH + (INITRANS - 1) * KTBIT + KDBH= 20 + 4 + 48 + (1-1) * 24 + 14= 86 (Byte)
INITRANS はブロックあたりの同時実行トランザクションの最小数であり、テーブルあたりの値ではありません。
4
2222....利利利利用用用用可可可可能能能能領領領領域域域域ササササイイイイズズズズのののの計計計計算算算算
各ブロック内で、行データを格納するために確保されている利用可能データ領域のサイズは、次の公式によって算出されます。PCTFREEはブロック・ヘッダA 以降の領域に対する割合なので、(ブロック・サイズ - ブロック・ヘッダ)*(PCTFREE / 100)で求められる領域をブロック・ヘッダ以降の領域から差し引くことで利用可能領域のサイズを算出します。
利利利利用用用用可可可可能能能能デデデデーーーータタタタ領領領領域域域域====CEIL((((((((ブブブブロロロロッッッックククク・・・・ササササイイイイズズズズ ---- ブブブブロロロロッッッックククク・・・・ヘヘヘヘッッッッダダダダ))))
----((((((((ブブブブロロロロッッッックククク・サ・サ・サ・サイイイイズズズズ ---- ブブブブロロロロッッッックククク・ヘ・ヘ・ヘ・ヘッッッッダダダダ))))*((((PCTFREE / 100))))))))))))---- KDBT
====CEIL((((((((ブブブブロロロロッッッックククク・・・・ササササイイイイズズズズ ---- ブブブブロロロロッッッックククク・・・・ヘヘヘヘッッッッダダダダ))))*((((1 ---- PCTFREE / 100))))))))---- KDBT
ここで、
CEIL :計算結果が整数になるように切り上げる。PCTFREE :現行ブロック更新のために確保する領域の割合。KDBT :V$TYPE_SIZEを検索することで得られる定数。
例 Windows95、Oracle8 Personal Edition Release 8.0.4.0.0 での v$parameter検索結果
SQL> select name, value from v$parameter where name='db_block_size';
NAME----------------------------------------------------------------VALUE---------------------------------------------------------------------db_block_size2048
例 PCTFREE = 10、ブロック・サイズ = 2048、KDBT = 4 と仮定します。またステップ 1の例より、ブロック・ヘッダ = 86 とします。
利用可能データ領域=CEIL((ブロック・サイズ - ブロック・ヘッダ) *(1 - PCTFREE / 100))- KDBT=CEIL((2048 - 86) * (1 - 10 / 100)) - 4=CEIL(1962 * 0.9) - 4 = 1766 - 4 = 1962(Byte)
PCTFREE で確保される行の更新のための領域は、利用可能領域に含めません。
ブロック・サイズは、データベース作成時に決定します。初期化パラメータ DB_BLOCK_SIZE で指定できます。
5
3333....行行行行ああああたたたたりりりりにににに使使使使わわわわれれれれるるるる領領領領域域域域ササササイイイイズズズズのののの計計計計算算算算
行あたりに使用される領域サイズを求める最も簡単な方法は、サンプル表を作成し、各列に対して、(vsize(colname))を選択するか、そのテーブルに ANALYZEをかけ、データディクショナリ(USER_TABLESの AVG_ROW_LEN)を見ることです。
例 visize(colname)を使用して Windows95、Oracle8 Personal Edition Release8.0.4.0.0にデフォルトで作成されるscott.emp表の平均行サイズを求めてみます。
SQL> desc emp; 名前 NULL? タイプ ------------------------------- -------- ---- EMPNO NOT NULL NUMBER(4) ENAME VARCHAR2(10) JOB VARCHAR2(9) MGR NUMBER(4) HIREDATE DATE SAL NUMBER(7,2) COMM NUMBER(7,2) DEPTNO NUMBER(2)
各列の平均サイズは次のように求めることができます。SQL> select avg(vsize(empno)) empno, 2 avg(nvl(vsize(ename), 0)) ename, 3 avg(nvl(vsize(job), 0)) job, 4 avg(nvl(vsize(mgr), 0)) mgr, 5 avg(nvl(vsize(hiredate), 0)) hiredate, 6 avg(nvl(vsize(sal), 0)) sal, 7 avg(nvl(vsize(comm), 0)) comm, 8 avg(nvl(vsize(deptno), 0)) deptno 9 from emp;
EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO--------- --------- --------- --------- --------- --------- --------- ---------2.9285714 5 6.8571429 2.7857143 7 2.4285714 .5 2
平均的行サイズは次のように求めることもできます。SQL> select (avg(vsize(empno)) + avg(nvl(vsize(ename), 0)) 2 + avg(nvl(vsize(job), 0)) + avg(nvl(vsize(mgr), 0)) 3 + avg(nvl(vsize(hiredate), 0)) + avg(nvl(vsize(sal), 0)) 4 + avg(nvl(vsize(comm), 0)) + avg(nvl(vsize(deptno), 0)) ) 5 average_row_size 6 from emp;
AVERAGE_ROW_SIZE---------------- 29.5
これより、この表の平均行的サイズは約 30 バイトだとわかります。
6
データブロックに格納される、表の行データ構造を図 2に示します。各行には固定長の行ヘッダがあり、それぞれにオーバーヘッドを含む各列データ領域が続いて存在します。
行行行行ヘヘヘヘッッッッダダダダ ババババイイイイトトトト長長長長をををを含含含含むむむむ 列列列列ササササイイイイズズズズのののの和和和和
オオオオ ーーーー ババババーーーー ヘヘヘヘッッッッドドドド
列列列列デデデデ ーーーー タタタタ
図図図図 2222::::行行行行のののの要要要要素素素素
計算で表の平均的行サイズを求める場合、いくつかのステップがあります。最初に、バイト長を加えた、列のデータ領域サイズを計算する方法を説明します。バイト長を含む列のデータ領域サイズは、列のデータ領域にオーバーヘッドを加えることで算出できます。
ババババイイイイトトトト長長長長をををを含含含含むむむむ列列列列デデデデーーーータタタタ領領領領域域域域ササササイイイイズズズズ==== column size ++++ overhead
column size :列のデータ領域CHAR :定義した長さVARCHAR2 :実際に占有している長さNUMBER :定義した長さ(精度)を pとすると、次の式で計算でき
ます。 1(指数部)+ CEIL(p / 2) + 1(有効数字が 38桁未満の負数の場合のみ)
DATE :7Byte
CEIL:計算結果が整数になるように切り上げます。
overhead:各列に割り当てられるオーバーヘッドcolumn sizeが 250Byte以下の時:1column sizeが 250Byte以上の時:3
次の公式を用いて行サイズを計算します。行サイズは固定長の行ヘッダにバイト長を含む列データ領域サイズの和を加えて算出します。
行行行行ササササイイイイズズズズ====行行行行ヘヘヘヘッッッッダダダダーーーー((((3 * UB1))))++++ ババババイイイイトトトト長長長長をををを含含含含むむむむ列列列列デデデデーーーータタタタ領領領領域域域域ササササイイイイズズズズのののの和和和和
UB1:V$TYPE_SIZEを検索することで得られる定数
行連鎖が生じた場合、オーバーヘッドの領域が増加します。
7
例 列 1:CHAR(15)、列 2:DATE、列 3:NUMBER(10) の 3 列が表に設定されていると仮定します。
列 1:CHAR(15)バイト長を含む列データ領域サイズ= column size + overhead= 15 + 1 = 16 (Byte)
列 2:DATEバイト長を含む列データ領域サイズ= column size + overhead= 7 + 1 = 8 (Byte)
列 3:NUMBER(10)バイト長を含む列データ領域サイズ= column size + overhead= 6 + 1 = 7 (Byte)
例 以上の列データ領域サイズの和を用いて、行サイズを計算します。行サイズ= 行ヘッダー(3 * UB1) + バイト長を加えた列データ領域サイズの和= 3 * 1 + (16 + 7 + 8) = 34 (Byte)
これで、次の計算式を用いて行あたりに使用される領域サイズを計算できます。
行行行行ああああたたたたりりりりにににに使使使使用用用用さささされれれれるるるる領領領領域域域域ササササイイイイズズズズ==== MAX((((UB1*3 ++++ UB4 ++++ SB2, 行行行行ササササイイイイズズズズ))))++++ SB2
ここで、
MAX((((A, B)))) :Aか Bの大きい方の値を採用します。UB1、、、、UB4、、、、SB2 :V$TYPE_SIZEを検索することで得られる定数。
例 既に計算した値より、行サイズ = 35 と仮定すると、行あたりに使用される領域サイズは次のように計算されます。
行あたりに使用される領域サイズ= MAX(UB1*3 + UB4 + SB2, 行サイズ)+ SB2= MAX(1*3 + 4 + 2, 34)+ 2= MAX(9, 34)+ 2 = 34 + 2 = 36 (Byte)
8
4444....ブブブブロロロロッッッッククククああああたたたたりりりりのののの平平平平均均均均行行行行数数数数のののの計計計計算算算算
ブロックあたりの平均行数を次の公式を用いて求めます。ブロックあたりの平均行数は、利用可能領域を行あたりに使用される領域サイズで割ることで計算できます。
ブブブブロロロロッッッッククククああああたたたたりりりりのののの平平平平均均均均行行行行数数数数==== FLOORFLOORFLOORFLOOR((((利利利利用用用用可可可可能能能能領領領領域域域域 / 行行行行ああああたたたたりりりりにににに使使使使用用用用さささされれれれるるるる領領領領域域域域ササササイイイイズズズズ))))
ここで、
FLOORFLOORFLOORFLOOR:計算結果が整数になるように切り捨てる。
例 ステップ 2より、利用可能領域サイズ = 1762、ステップ 3より、行あたりに使用される領域サイズ = 36 とし、ブロックあたりの平均行数を計算します。
ブロックあたりの平均行数= FLOOR(利用可能領域 / 平均的行サイズ)= FLOOR(1762 / 36)= 48(行)
5555....必必必必要要要要ななななブブブブロロロロッッッックククク数数数数ととととババババイイイイトトトト数数数数のののの計計計計算算算算
次の公式を用いて、必要なブロック数、及びバイト数を算出できます。必要なブロック数は、表に含まれる行数をブロックあたりに格納できる平均行数で割ることで求められます。必要なブロック数にブロック・サイズをかけたものが、必要なバイト数となります。
必必必必要要要要ななななブブブブロロロロッッッックククク数数数数==== CEIL((((表表表表にににに含含含含ままままれれれれるるるる行行行行数数数数 / / / / ブブブブロロロロッッッッククククああああたたたたりりりりのののの平平平平均均均均行行行行数数数数))))
必必必必要要要要ななななババババイイイイトトトト数数数数==== 必必必必要要要要ななななブブブブロロロロッッッックククク数数数数 * * * * ブブブブロロロロッッッックククク・・・・ササササイイイイズズズズ
例 表が 20,000 行含むと仮定します。ステップ 4より、ブロックあたりの平均行数 = 50 として必要なブロック数、及びバイト数を計算します。
必要なブロック数= CEIL(表に含まれる行数 / ブロックあたりの平均行数)= CEIL(20000 / 48) = 417
必要なバイト数= 必要なブロック数 * ブロック・サイズ= 417 * 2048 = 854016 (Byte) = 0.81 (MB)
9
索索索索引引引引ササササイイイイズズズズのののの見見見見積積積積ももももりりりりOracleでは、索引も表と同様にセグメントとして扱われます。つまり、索引を作成すると、索引のための領域が必要になります。そのため、索引を定義する場合は、索引に必要な領域を考慮に入れなければなりません。
索引ブロックの構成は、基本的には本書 3ページの図 1:データブロック形式と同じです。しかし、索引ブロックにはリーフ・ブロック、ブランチ・ブロックがあり、それぞれ構造が異なります。このため索引サイズの見積は、表サイズの見積よりも複雑で困難なものとなります。本書では索引ブロック構造の詳細には触れません。本書で説明する見積方法は、簡略化したブロック構造をもとにしています。また、すべての索引ブロック構造が等しいと仮定しています。あくまでも、見積結果は目安と考え、10~20%は余裕を持った領域を割り当てるようにしてください。
索引サイズの見積もり方法は、表の見積もりと類似しています。見積もりに必要な情報を以下に示します。l 索引の行数(NULL値は含まない)l 索引列の平均的な長さとデータ型l データ・ブロック・サイズl PCTFREE、INITRANSの値l V$TYPE_SIZEから検索する定数
以下の手順に従って、索引に必要となる領域の大きさを見積もります。1. データ・ブロック当たりのブロック・ヘッダー・サイズを計算します。2. データ・ブロック当たりの利用可能な索引データ領域を計算します。3. 索引あたりに利用される領域サイズを計算します。4. ブロックあたりの平均索引エントリ数の計算5. 索引に必要なブロック数とバイト数を計算します。
1111....ブブブブロロロロッッッックククク・ヘッダー・サイズの計算・ヘッダー・サイズの計算・ヘッダー・サイズの計算・ヘッダー・サイズの計算
索引ブロック構造を簡略化したものを図 3 に示します。固定部と可変部からなるブロック・ヘッダ以降の領域中、PCTFREEの値によって決定される利用可能領域に索引エントリが格納されます。
索索索索引引引引行行行行エエエエンンンントトトトリリリリ
固固固固定定定定長長長長ヘヘヘヘッッッッダダダダ ((((111111113333ババババイイイイトトトト))))
利利利利用用用用可可可可能能能能領領領領域域域域
可可可可変変変変長長長長トトトトラララランンンンザザザザククククシシシショョョョンンンン・・・・ヘヘヘヘッッッッダダダダ((((22224444ババババイイイイトトトト / / / / INITRANS値値値値 ))))
ブブブブロロロロッッッックククク・・・・ヘヘヘヘッッッッダダダダ
図図図図3333::::索索索索引引引引ブブブブロロロロッッッックククク
この計算方法は、索引を構成する列の平均的長さに依存します。そのため、索引列の実際のデータ長が比較的一定である場合、この見積もり計算式は、より正確なものになります。
10
次の公式により、索引データ・ブロック・ヘッダーに必要な領域を計算します。ブロック・ヘッダは固定部と可変部を加えることで求められます。
ブブブブロロロロッッッックククク・・・・ヘヘヘヘッッッッダダダダーーーー==== 固固固固定定定定長長長長ヘヘヘヘッッッッダダダダーーーー ++++ 可可可可変変変変長長長長トトトトラララランンンンザザザザククククシシシショョョョンンンン・・・・ヘヘヘヘッッッッダダダダーーーー
固固固固定定定定長長長長ヘヘヘヘッッッッダダダダーーーー :113バイト可可可可変変変変長長長長トトトトラララランンンンザザザザククククシシシショョョョンンンン・・・・ヘヘヘヘッッッッダダダダーーーー
:24 * INITRANS
例 INITRANS = 2 と仮定します。ブロック・ヘッダ= 固定長ヘッダ + 可変長トランザクション・ヘッダ= 113 + 24 * 2 = 161 (Byte)
2222....ブブブブロロロロッッッッククククああああたたたたりりりりのののの利利利利用用用用可可可可能能能能ななななデデデデーーーータタタタ領領領領域域域域のののの計計計計算算算算
次の公式を用いて、索引に割り当てることができるデータ領域を計算します。PCTFREEはブロック・ヘッダ以降の領域に対する割合なので、ブロック・サイズからブロック・ヘッダを引いた領域に(1 - (PCTFREE / 100))をかけたものが利用可能領域サイズとして算出されます。
利利利利用用用用可可可可能能能能デデデデーーーータタタタ領領領領域域域域==== ((((ブブブブロロロロッッッックククク・サイズ・サイズ・サイズ・サイズ ---- ブブブブロロロロッッッックククク・・・・ヘヘヘヘッッッッダダダダ))))****((((1 ----((((PCTFREE / 100))))))))
例 ステップ 1より、ブロック・ヘッダ = 161、また PCTFREE = 10、ブロック・サイズ = 2048 と仮定して、データ・ブロックあたりの利用可能領域サイズを計算します。
利用可能データ領域= (ブロック・サイズ - ブロック・ヘッダ) * (1 - (PCTFREE / 100))= (2048 - 161) * (1 - 10 / 100) = 1887 * 0.9 = 1698.3 = 1699 (Byte)
3333....全全全全体体体体のののの索索索索引引引引値値値値ササササイイイイズズズズのののの計計計計算算算算
データブロックに格納される、索引エントリ構造を図 4に示します。各エントリには固定長のエントリ・ヘッダと ROWIDデータ領域があり、それぞれにオーバーヘッドを含む各索引列データ領域が続いて存在します。
索索索索 引引引引エエエエンンンントトトトリリリリ・・・・ヘヘヘヘッッッッダダダダ ババババイイイイトトトト長長長長をををを含含含含むむむむ 索索索索引引引引列列列列 ササササイイイイズズズズのののの和和和和
ROWID
オオオオ ーーーー ババババーーーー ヘヘヘヘッッッッドドドド
列列列列 デデデデ ーーーー タタタタ
図図図図 4444::::索索索索引引引引エエエエンンンントトトトリリリリ構構構構成成成成
INITRANSの値は表のそれと違い、最小値とデフォルト値は 1ではなく 2
です。
11
平均索引サイズを計算する前に、バイト長を加えた、索引列のサイズを計算する必要があります。バイト長を含む索引列のデータ領域サイズは、索引列のデータ領域にオーバーヘッドを加えることで算出できます。
ババババイイイイトトトト長長長長をををを含含含含むむむむ索索索索引引引引列列列列ササササイイイイズズズズ==== column size ++++ overhead
column size :索引列のデータ領域表の領域サイズの計算方法ステップ3を参考にしてください。
overhead:各列に割り当てられるオーバーヘッドcolumn sizeが 127Byte以下の時:1column sizeが 127Byte以上の時:2
次の公式を用いて索引行サイズを計算します。索引行サイズは固定長の行ヘッダにバイト長を含む列データ領域サイズの和を加えて算出します。
索索索索引引引引行行行行ササササイイイイズズズズ==== 行行行行ヘヘヘヘッッッッダダダダーーーー((((3 * UB1))))++++ ババババイイイイトトトト長長長長をををを含含含含むむむむ列列列列デデデデーーーータタタタ領領領領域域域域ササササイイイイズズズズのののの和和和和
UB1:V$TYPE_SIZEを検索することで得られる定数
例 索引が CHAR(15)、NUMBER(10) の 2 列で構成されていると仮定します。CHAR(15)バイト長を含む索引列サイズ= column size + overhead= 15 + 1 = 16 (Byte)
NUMBER(10)バイト長を含む索引列サイズ= column size + overhead= 6 + 1 = 7 (Byte)
例 以上の索引列データ領域サイズの和を用いて、索引行サイズを計算します。索引行サイズ= 行ヘッダー(3 * UB1) + バイト長を加えた索引列データ領域サイズの和= 3 * 1 + (16 + 7) = 26 (Byte)
これで、次の計算式を用いて行あたりに使用される領域サイズを計算できます。
索索索索引引引引行行行行ああああたたたたりりりりにににに使使使使用用用用さささされれれれるるるる領領領領域域域域ササササイイイイズズズズ==== MAX((((UB1*3 ++++ UB4 ++++ SB2, 索索索索引引引引行行行行ササササイイイイズズズズ))))++++ SB2
ここで、
MAX((((A, B)))) :Aか Bの大きい方の値を採用します。UB1、、、、UB4、、、、SB2 :V$TYPE_SIZEを検索することで得られる定数。
12
例 既に計算した値より、索引行サイズ = 26 と仮定すると、索引行あたりに使用される領域サイズは次のように計算されます。
索引行あたりに使用される領域サイズ= MAX(UB1*3 + UB4 + SB2, 索引行サイズ)+ SB2= MAX(1*3 + 4 + 2, 26)+ 2= MAX(9, 26)+ 2 = 28(Byte)
次の公式を用いて索引エントリ・サイズを計算します。索引エントリ・サイズは固定長索引エントリ・ヘッダと ROWIDデータ領域、長さバイトにバイト長を含む索引列データ領域サイズの和を加えて算出します。
全全全全体体体体のののの索索索索引引引引値値値値ササササイイイイズズズズ==== エエエエンンンントトトトリリリリ・ヘッダー・ヘッダー・ヘッダー・ヘッダー ++++ ROWIDのののの長長長長ささささ++++ F ++++ V++++ 索索索索引引引引行行行行ああああたたたたりりりりにににに使使使使用用用用さささされれれれるるるる領領領領域域域域ササササイイイイズズズズ
ここで、
エエエエンンンントトトトリリリリ・ヘッダー・ヘッダー・ヘッダー・ヘッダー :2バイトROWIDのののの長長長長ささささ :6バイトF :長さバイト
= 127 バイト以下のデータを格納するための列数 *1
V :長さバイト= 128 バイト以上のデータを格納するための列数 *2
例 既に計算した値より、索引行あたりに使用される領域サイズ = 30 と仮定すると、全体の索引値サイズは次のように計算されます。
全体の索引値サイズ= エントリ・ヘッダー + ROWIDの長さ+ F + V + 索引行あたりに使用される領域サイズ= 2 + 6 + (2 * 1 + 0 * 2) + 28 = 38 (Byte)
4444....ブブブブロロロロッッッッククククああああたたたたりりりりのののの平平平平均均均均索索索索引引引引エエエエンンンントトトトリリリリ数数数数のののの計計計計算算算算
次の公式を用いてブロックあたりの平均索引エントリ数を算出します。ブロックあたりの平均索引エントリ数は、利用可能領域を平均的索引エントリ・サイズで割ることで計算できます。
ブブブブロロロロッッッッククククああああたたたたりりりりのののの平平平平均均均均索索索索引引引引エエエエンンンントトトトリリリリ数数数数==== FLOOR (利利利利用用用用可可可可能能能能領領領領域域域域 / 全全全全体体体体のののの索索索索引引引引値値値値ササササイイイイズズズズ)
FLOOR:計算結果が整数になるように切り捨てます。
例 ステップ 2より、利用可能データ領域サイズ = 1699、ステップ 3より、全体の索引値サイズ = 40 として平均行数を計算します。
ブロックあたりの平均索引エントリ数= FLOOR (利用可能領域 / 平均的索引エントリ・サイズ)= FLOOR (1699 / 38) = 44
一意でない索引の場合は、ROWID が別の列と見なされて、長さバイトが 1必要になります。
13
5555....必必必必要要要要ななななブブブブロロロロッッッックククク数数数数ととととババババイイイイトトトト数数数数のののの計計計計算算算算
次の公式を用いて、必要なブロック数、及びバイト数を算出できます。必要なブロック数は、表に含まれる nullでない索引の行数を 1.05 で乗してから、ブロックあたりに格納できる平均索引エントリ数で割ることで求められます。必要なブロック数にブロック・サイズをかけたものが、必要なバイト数となります。
必必必必要要要要ななななブブブブロロロロッッッックククク数数数数==== CEIL((((1.05 * 1.05 * 1.05 * 1.05 * null ででででなななないいいい索索索索引引引引のののの行行行行数数数数 / / / / ブブブブロロロロッッッッククククああああたたたたりりりりのののの平平平平均均均均索索索索引引引引エエエエンンンントトトトリリリリ数数数数))))
必必必必要要要要ななななババババイイイイトトトト数数数数==== 必必必必要要要要ななななブブブブロロロロッッッックククク数数数数 * * * * ブブブブロロロロッッッックククク・・・・ササササイイイイズズズズ
例 ステップ4より、ブロックあたりの平均索引エントリ数 = 42 とします。また、索引付きの表の内、索引を構成する列の値が null でない行が 20,000 行あると仮定します。
必要なブロック数 =CEIL (1.05 * nullでない索引の行数 / ブロックあたりの平均索引エントリ数)= CEIL (1.05 * 20000 / 44) = 478
必要なバイト数= 必要なブロック数 * ブロック・サイズ= 478 * 2048 = 978944 (Byte) = 0.93 (MB)
ロードする表に対して、索引を作る時、索引をソートするために一時セグメントが作成されます。索引のソートに必要な領域は一定ではありませんが、索引サイズの 110%にまでなる可能性があります。
関関関関連連連連事事事事項項項項::::ビビビビッッッットトトトママママッッッッププププ索索索索引引引引ササササイイイイズズズズのののの推推推推測測測測
ビットマップ索引のサイズを厳密に測定、または、見積もることはできません。しかし、表のB*ツリー索引のサイズに対して、相対的にビットマップ索引サイズを推測することはできます。ここではその推測方法についの説明は省略しますが、『Oracle8 Server チューニング』 第 10 章「データ・アクセス方法」 -ビット・マップ索引の使用方法- に推測方法例がありますので、参照してください。
乗数 1.05 は索引のブランチ・ブロックで必要な領域を追加するためのものです。
NOSORT オプションをCREATE INDEX コマンドで指定すると、一時領域は必要ありません。ただし、クラスタ索引を作り時には、このオプションを指定できません。
14
記記記記憶憶憶憶領領領領域域域域パパパパララララメメメメーーーータタタタのののの設設設設定定定定とととと注注注注意意意意事事事事項項項項
記憶領域(STORAGE)パラメータは、表および索引等のスキーマ・オブジェクト、および表領域の記憶特性を指定するもので、表領域に指定された値は、その表領域に割り当てられたセグメントに対する STORAGE パラメータのデフォルト値になります。また STORAGE パラメータは、データベースのデータへのアクセス時間とデータベース内での領域利用の効率性の両方に影響します。
ここでは次に示す、一般的な記憶領域パラメータの値の選び方と、その上で考慮すべき注意事項について説明します。l INITIALl NEXTl MAXEXTENTSl MINEXTENTSl PCTINCREASE
またここで説明する注意事項は次の通りです。l パラレル・ロードと INITIAL の値l データ領域見積もりの際の平均行長誤差l エクステントについて
記記記記憶憶憶憶領領領領域域域域パパパパララララメメメメーーーータタタターーーーのののの設設設設定定定定
各記憶領域パラメータについての説明と、一般的値を示します。
INITIAL推奨値 :必要なバイト数デフォルト :5データ・ブロック設定可能値 :OS依存
セグメントに割り当てられる最初のエクステントのサイズをバイト単位で指定します。Kまたは Mを使用して、KBまたは MB単位でもサイズを指定できます。ALTER TABLEの storage句で INITIALを指定してその値の変更することはできません。指定した値が 5データ・ブロック未満のとき、データ・ブロックの倍数のサイズに切り上げられ、5データ・ブロック以上の時は 5データ・ブロックの倍数のサイズに切り上げられます。
パフォーマンスを低下させる可能性がある動的拡張を避けるには、オブジェクトに含まれるデータがすべてこのエクステントに収まるのが理想的です。そのため、パラレル・ロードなど特殊な機能を使用する時以外は、計算によって求めたデータ領域に必要なバイト数を指定するのが一般的です。しかし、初期データ量は少ないが時間とともに急激にデータが増えてしまうようなシステムでは、初めから巨大なエクステントを確保する必要はありません。また、全表走査以外の検索、つまりインデックス走査では表のエクステントがフラグメントしていても、それほどパフォーマンスに影響を与えません。これらのように、必ずしもこの推奨値が理想的でない場合もあります。
15
NEXT推奨値 :INITIALの値の 10%程度デフォルト :5データ・ブロック設定可能値 :OS依存
INITIAL で指定したエクステントがいっぱいになった場合に割り当てられるエクステントのサイズをバイト単位で指定します。Kまたは Mを使用して、KBまたは MB単位でもサイズを指定できます。INITIALの一般値に対しての NEXTの推奨値を示しました。ALTER TABLESPACEの storage句で NEXT値を変更することは可能ですが、その値は次の増分エクステントから適用され、既に割り当てられたエクステントに変更は起きません。指定した値が 5データ・ブロック未満のとき、データ・ブロックの倍数のサイズに切り上げられ、5データ・ブロック以上の時は断片化を最小限にする値に切り上げられます。
MAXEXTENTS推奨値 :UNLIMITEDまたは最大エクステント数より少し小さめデフォルト :OS依存設定可能値 :1 - OS依存
最大エクステント数データ・ブロックのサイズ 最大エクステント数
2048バイト 121
4096バイト 249
8192バイト 505
セグメントに割り当てられるエクステントの総数を指定します。Oracle7.3 からは、UNLIMITEDを指定できます。UNLIMITEDと指定することにより最大エクステント数は 2Gとなり、ほぼエクステントの割り当て制限がなくなります。それ以前の Oracle では最大エクステント数より少し小さな値を指定しましょう。表または索引が MAXEXTENTSを上回った場合でも、表や索引を動的に変更し、最適なサイズの NEXTエクステントを割り当てる機会を残しておくためです。
例 EXAMPLE 表が最大エクステント数より小さい MAXEXTENTS(100)に達したが、表領域にはまだ空があるとします。
ALTER TABLE EXAMPLE STORAGE(MAXEXTENTS 110, NEXT 5M);
MINEXTENTS推奨値 :デフォルトの値デフォルト :1設定可能値 :1 - OS依存
セグメント作成時に割り当てられるエクステントの総数を指定します。特殊な場合以外は、デフォルト値のままにしましょう。
PCTINCREASE推奨値 :0デフォルト :50設定可能値 :0 - OS依存
3 番目以降の各増分エクステントがその直前のエクステントに対して増加する割合(%)を指定します。算出された各エクステントのサイズは、データ・ブロック・サイズの倍数に切り上げられます。表のサイズが分かっている場合は 0を指定しましょう。
ロールバック・セグメントの UNLIMITED 指定は、正式サポートの対象外となります。
セグメントにエクステントの最大数が割り当てられた後も、さらに領域が必要になった場合は、そのオブジェクトの再編成を行わなければなりません。
16
例 「表領域の見積もり」の例で算出した表データ・ブロック・サイズ:2048(Byte)必要なブロック数:426必要なバイト数が 872448 (Byte)
を作成するための CREATE TABLE 文例を示します。必要なバイト数を 10%多めに見積もります。872448 * 1.1 = 959693 (Byte) ≒ 1 (MB)
CREATE TABLE example( name CHAR(15), today DATE, id NUMBER(10))STORAGE( INITIAL 1M, NEXT 100K, MAXEXTENTS UNLIMITED, MINEXTENTS 1, PCTINCREASE 0);
注注注注意意意意事事事事項項項項
記憶領域パラメータ設定の際に役立つ注意事項を説明します。
パパパパララララレレレレルルルル・・・・ロロロローーーードドドドとととと INITIAL のののの値値値値
テキスト・ファイルのデータをデータベースの表に取り入れるためのユーティリティとして、SQL*Loaderがあります。その機能の一つにパラレルロードがあります。パラレルロードは、データファイルを複数に分けることで、複数ファイルに対して同時に、そして高速なデータ・ローディングを可能にします。パラレルロードを行う場合、INITIALの値を小さくしてください。パラレルロードの際、それぞれのローディングで新たにエクステントを確保することから、最初に作成されるエクステントが使用されず、INITIAL で確保する領域が無駄になるからです。
例 データのパラレルロードは次のように行います。%sqlldr DATA=example1.dat DIRECT=true PARALELL=TRUE FILE=/dev/D1%sqlldr DATA=example2.dat DIRECT=true PARALELL=TRUE FILE=/dev/D2.....%sqlldr DATA=example10.dat DIRECT=true PARALELL=TRUE FILE=/dev/D10
例 example 表に必要な領域が約 1000MB のとき、10 個のデータファイルを用いてパラレルロードを行う時の INITIAL および NEXT の設定例です。
CREATE TABLE example( name CHAR(15), today DATE, id NUMBER(10))STORAGE( INITIAL 64K, NEXT 100MB, MAXEXTENTS UNLIMITED, MINEXTENTS 1, PCTINCREASE 0)PARALELL (DEGREE 10) ;
17
デデデデーーーータタタタ領領領領域域域域見見見見積積積積ももももりりりりのののの際際際際のののの平平平平均均均均行行行行長長長長誤誤誤誤差差差差
可可可可変変変変長長長長デデデデーーーータタタタ型型型型ににににつつつついいいいてててて VARCHAR2型の列データ領域は、定義された長さではなく、格納されたデータが占有する長さになります。例えば、VARCHAR2(100)と定義された列に格納されたデータが‘ABC’であれば、列長は 100 ではなく 3 バイトです。このように、VARCHAR2型を含む平均行長の見積もりの際は、定義された長さと実際に格納されたデータの長さによって生じる誤差に注意しなくてはいけません。特に定義された VARCHAR2型の列長が長い時、誤差は顕著になるでしょう。
NUMBER 型の列データについても VARCHAR2 型の場合と同様です。定義された長さより、実際に格納される数値データの長さに注意して見積もりを行うべきです。
NULL 列列列列ののののオオオオーーーーババババーーーーヘヘヘヘッッッッドドドドににににつつつついいいいてててて NULL値を含む列のオーバーヘッドのサイズには注意が必要です。オーバーヘッドのサイズは 1列に対して 1バイトですが、表の最終列まで連続する NULL列のオーバーヘッドは 0 だからです。例えば次に定義する表 NULLTESTがあります。
create table nulltest (col1 char(10) not null,col2 char(10) not null,col3 char(10),col4 char(10),col5 char(10));
CHAR型は固定長データ型なので行ヘッダー、オーバーヘッドを含む平均的行サイズは次のように計算できます。
平均的行サイズ = 3 + 1 + 10 + 1 + 10 + 1 + 10 + 1 + 10 + 1 + 10 = 58 byte
実際に次の SQL文を実行し平均行長を求めてみます。
SQL> insert into nulltest values('test','test','test','test','test');1 行が作成されました。SQL> insert into nulltest values('test','test','test','test','test');1 行が作成されました。SQL> commit;コミットが完了しました。SQL> analyze table nulltest compute statistics for table;表が分析されました。SQL> select avg_row_len from user_tables where table_name = 'NULLTEST';AVG_ROW_LEN----------- 58
計算で求めた値と一致していることを確認できます。
次に第 5 列は常に NULLだと仮定します。このとき平均的行サイズは第 5列のサイズを 0として次のように計算できます。
平均的行サイズ = 3 + 1 + 10 + 1 + 10 + 1 + 10 + 1 + 10 + 1 + 0 = 48 byte
18
しかし実際に次の SQL 文を実行して平均行長を求めると、
SQL> truncate table nulltest;表が切り捨てられました。SQL> insert into nulltest(col1, col2, col3, col4)values('test','test','test','test');1 行が作成されました。SQL> insert into nulltest(col1, col2, col3, col4)values('test','test','test','test');1 行が作成されました。SQL> commit;コミットが完了しました。SQL> analyze table nulltest compute statistics for table;表が分析されました。SQL> select avg_row_len from user_tables where table_name = 'NULLTEST';AVG_ROW_LEN----------- 47
となり、計算値より 1 バイト少ない 47byte となります。これは最終行の第 5 列が NULLのためオーバーヘッドが 0byteとなるからです。同様に第 3列、第 4列、第 5列が NULLであるとき、平均的行サイズの計算値は、
平均的行サイズ = 3 + 1 + 10 + 1 + 10 + 1 + 0 + 1 + 0 + 1 + 0 = 28 byte
ではなく、3列分のオーバーヘッドの少ない、
平均的行サイズ = 3 + 1 + 10 + 1 + 10 + 0 + 0 + 0 + 0 + 0 + 0 = 25 byte
となります。実際に次の SQL分を実行し確認してみます。
SQL> truncate table nulltest;表が切り捨てられました。SQL> insert into nulltest(col1, col2) values('test','test');1 行が作成されました。SQL> insert into nulltest(col1, col2) values('test','test');1 行が作成されました。SQL> commit;コミットが完了しました。SQL> analyze table nulltest compute statistics for table;表が分析されました。SQL> select avg_row_len from user_tables where table_name = 'NULLTEST';AVG_ROW_LEN----------- 25
次に第 3 列と第 5 列が NULL である場合を考えます。最終列の第 5 列が NULLのとき、そのオーバーヘッドは 0byteでした。では同じ NULL列でも連続していない場合のオーバーヘッドはどうなるでしょうか。このときの平均行長を次のSQL文を実行して求めます。
19
SQL> truncate table nulltest;表が切り捨てられました。SQL> insert into nulltest(col1, col2, col4) values('test','test','test');1 行が作成されました。SQL> insert into nulltest(col1, col2, col4) values('test','test','test');1 行が作成されました。SQL> commit;コミットが完了しました。SQL> analyze table nulltest compute statistics for table;表が分析されました。SQL> select avg_row_len from user_tables where table_name = 'NULLTEST';AVG_ROW_LEN----------- 37
これは、第 3列のオーバーヘッドを 0でなく、1byteとした次の計算結果と一致します。
平均的行サイズ = 3 + 1 + 10 + 1 + 10 + 1 + 0 + 1 + 10 + 0 + 0 = 37 byte
つまり、NULLでない列に挟まれた NULL列は 1byteのオーバーヘッドをもつが、最終列まで連続する NULL列にはオーバーヘッドがありません。存在する複数列の内の一部の列しか使用しないような特殊な表を見積もるときは、使用しないNULL 列のオーバーヘッドの大きさに注意して領域の見積もりを実行してください。
エエエエククククスススステテテテンンンントトトトににににつつつついいいいてててて
データ・ベース・オブジェクトが作成されたとき、また、既存の領域(セグメント)が満杯になると、新しいエクステントが割り当てられます。割り当てられたエクステントの解放は、DELETEによっては行われません。エクステントが解放されるのは DROPもしくは TRUNCATEだけです。
複複複複数数数数デデデデーーーータタタタフフフファァァァイイイイルルルルへへへへののののエエエエククククスススステテテテンンンントトトト割割割割りりりり当当当当てててて エクステントの割り当ては Oracle によって自動的に行われます。一つの表領域に複数のデータファイルがある場合も同様で、割り当て先のデータファイルはOracle により自動的に選択されます。この時、一つのエクステントが複数のデータファイルをまたがって割り当てられることはありません。すなわち、データファイルに空領域が残っていても、そのサイズが一つのエクステントのサイズより小さければ、使用されません。例えば、あるデータファイルの空領域サイズが900K バイトあり、もう一つのデータファイルには 800K バイトの空領域があるとします。このとき、次に割り当てられるエクステントのサイズが 1Mバイトであったら、この 2つの空領域は合計サイズ 1.7Mバイトにもかかわらず使用されないのです。エクステントのサイズが大きい時、データファイル中で、未使用となる空領域のサイズも大きくなる可能性があります。
ロールバック・セグメントの記憶領域パラメーターに OPTIMALを指定すると、エクステントの解放が、Oracleにより動的に行われます。
20
明明明明示示示示的的的的ななななエエエエククククスススステテテテンンンントトトト割割割割りりりり当当当当てててて エクステントの割り当ては通常 Oracle によって自動的に行われますが、次の例のように新しいエクステントを明示的に割り当てることができます。明示的に割り当てることで、空領域を有効に使うことができます。また複数データファイルを使用している時は I/Oのバランスを調節することもできます。
例 example 表にサイズ 500K バイトの新しいエクステントを example02.ora といううデータファイル中に割り当てます。
SQL> alter table example allocate extent 2 (size 500k datafile 'C:¥ORAWIN95¥DATABASE¥example02.ora');
表が変更されました。
フフフフララララググググメメメメンンンンテテテテーーーーシシシショョョョンンンン エクステントは連続するデータベース・ブロックの集まりです。すなわち、エクステントを割り当てるのに必要な空領域は同じ表領域内で連続していなくてはいけません。例えば、一つの表領域内に 500Kバイトと 600Kバイトの空領域があったとしても、それらが連続していなければ、1Mバイトのエクステントを割り当てることはできません。このような状態が表領域のフラグメンテーションです。IMPORT/EXPORT ユーティリティを使用すれば表領域のフラグメンテーションを解消することができます。
21
おおおおわわわわりりりりにににに
この資料では、表と索引という特定のオブジェクトの領域を概算する際に役立つ公式について解説しました。また、その計算結果を目安として、オブジェクトを作成する時のパラメータの選び方と考慮すべき注意事項についても説明しました。サイズの見積もりは有効ですが、計算結果は近似値であることを注意して、この資料をデータベース設計に役立ててください。