数据库空间估算
空間估算的準確與否決定了 ??
? ? ? ? 1。系統(tǒng)對資源的需求--投資問題 ??
? ? ? ? 2。數(shù)據(jù)分布是否合理--數(shù)據(jù)結(jié)構(gòu)設(shè)計問題 ??
? ? ? ? 3。應(yīng)用設(shè)計,特別是數(shù)據(jù)存取方面的設(shè)計--系統(tǒng)運行性能問題等。 ??
同時,由于ORACLE數(shù)據(jù)類型的多樣,數(shù)據(jù)模型的復(fù)雜,空間估算也代表了相當大的工作量。 ??
通常的空間估算包括了對TABLE,INDEX,CLUSTER,ROLLBACK ? SEGMENT,TEMPORARY ? SEGMENT以及REDO ? LOG方面等的計算。在本文中重點給出了對TABLE,INDEX的估算。 ??
應(yīng)該強調(diào)的是估算工作主要針對數(shù)據(jù)庫中比較大的表,以及在應(yīng)用中變化量較大的表。 ??
在進行空間估算之前,有必要再回顧以下認識: ??
1。對于數(shù)據(jù)塊的認識: ??
? ? ? ? 。數(shù)據(jù)塊的大小有DB_BLOCK_SIZE決定,并且只有通過重建數(shù)據(jù)庫來得到調(diào)整??臻g計算的根據(jù)來自于數(shù)據(jù)塊。 ??
? ? ? ? 。數(shù)據(jù)塊由數(shù)據(jù)塊頭,數(shù)據(jù)區(qū)組成。數(shù)據(jù)區(qū)的使用由PCTFREE,PCTUSED控制。當INSERT發(fā)生時, ??
? ? ? ? PCTFREE決定了該塊所能容納的最多的數(shù)據(jù),即,剩余空間占數(shù)據(jù)塊實際空間的百分比不小于PCTFREE。 ??
? ? ? ? 空間估算中PCTFREE是很一個很重要的參數(shù)。 ??
2。對于在表上進行的事務(wù)(TRANSACTION)類型要有一個清晰的認識,因為這會幫助如何更好的確定PCTFREE ? & ? PCTUSED。 ??
例如: ??
? ? ? ? 如果PCTFREE的值太大,記錄又可能很長,這會引起行鏈接(ROW-CHAINING),同時空間利用率也不高; ? ? ? 如果PCTFREE的值太小,會影響塊數(shù)據(jù)記錄的增長,容易引起行遷移(ROW-MIGURATING); ??
? ? ? ? 如果PCTUSED的值太大,空間上似乎沒什么問題,但數(shù)據(jù)塊的操作上又有潛在的性能問題,因為數(shù)據(jù)塊需要在 ??
? ? ? ? ? ? ? ? FREELIST上反復(fù)搬動; ??
? ? ? ? 如果PCTUSED的值太小,則又出現(xiàn)了空間利用率不高的問題。 ??
3。PCTFREE ? & ? PCTUSED表示的是DB_BLOCK_SIZE減去數(shù)據(jù)塊頭后的百分比值。 ??
4。ORACLE采用的是延遲寫(DELAYED ? CLEANOUT)方式來完成事務(wù)處理,所以由DELETE及UPDATE等操作釋放的空間并不會 ??
馬上被利用。這一點在數(shù)據(jù)變化頻繁時需要加以考慮。 ??
5。記錄結(jié)尾空值(TRAILING ? NULLS)不占存儲空間,但如果出現(xiàn)在記錄中間,則會占用1 ? byte。所以O(shè)RACLE建議盡可能 ??
將經(jīng)常出現(xiàn)空值的列放在結(jié)構(gòu)定義的尾部。 ??
6。CHAR,DATE是定長數(shù)據(jù)類型,NUMBER,VARCHAR2,LONG,LONG ? RAW等是變長數(shù)據(jù)類型。其中DATE的長度固定為7 ? BYTES, ??
包括世紀,年,月,日,時,分,秒。 ??
方法一: ??
對表的空間估算 ??
根據(jù)以下步驟確定表對空間占用的情況。要注意的是這里給出的是該表初始建立時所占的空間。 ??
一。數(shù)據(jù)塊頭的大小 ??
? ? block ? header ? = ? fixed ? header ? + ? variable ? transaction ? header ? + ? table ? directory ? + ? row ? directory ??
? ? ? ? ? where: ??
? ? ? ? ? ? ? ? fixed ? header ? = ? 57 ? bytes ? ??
? ? ? ? ? ? ? ? variable ? transaction ? header ? = ? 23 ? * ? i ? ? (i ? 代表 ? INITRANS的值,這是個動態(tài)值,最大不超過MAXTRANS) ??
? ? ? ? ? ? ? ? table ? directory ? = ? 4 ? * ? n ? ? ? ? (對于非CLUSTERED表來講n=1) ??
? ? ? ? ? ? ? ? row ? directory ? = ? 2 ? * ? x ? ? ? ? (x=該數(shù)據(jù)塊中的記錄數(shù)) ??
說明: ??
1。VARIABLE ? TRANSACTION ? HEADER代表的是發(fā)生在此數(shù)據(jù)塊上的事務(wù)所占用的空間。每個事務(wù)占用23 ? BYTES, ??
一般情況下(INITRANS=1),塊頭部會保留23 ? BYTES,更多的事務(wù)要占用空間會利用PCTFREE所保留的空間。所以 ??
隨著事務(wù)的增加,數(shù)據(jù)塊頭會向下“長”也是這個道理。 ??
2。隨著塊中記錄數(shù)量的增加,ROW ? DIRECTORY的值也會增加,這樣也會增加塊頭部的大小。并且,即使后來刪除了 ??
這些記錄,塊頭也不會“回縮”。 ??
有了這些概念,如上述公式,假定INITRANS=1,數(shù)據(jù)塊頭的大小為: ??
? ? block ? header ? = ? 57 ? + ? 23 ? + ? 4 ? + ? 2x ? = ? (84 ? + ? 2x) ? bytes ??
二。塊中可用的空間為: ??
? ? available ? data ? space ? = ? (block ? size ? - ? total ? block ? header) ? - ??
? ? ? ? ? ? ? ? ? ((block ? size ? - ? total ? block ? header) ? * ? (PCTFREE/100)) ??
假定BLOCK ? SIZE=2K,PCTFREE=10,即: ??
? ? available ? data ? space ? = ? (2048 ? - ? (84 ? + ? 2x)) ? - ? ((2048 ? - ? (84 ? + ? 2x)) ? * ? (10/100)) ??
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? = ? (1964 ? - ? 2x) ? - ? ((2048 ? - ? 84 ? - ? 2x) ? * ? (10/100)) ??
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? = ? (1964 ? - ? 2x) ? - ? (1964 ? - ? 2x) ? * ? 0.1 ??
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? = ? (1964 ? - ? 2x ? - ? 196 ? + ? 0.2x) ? bytes ??
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? = ? (1768 ? - ? 1.8x) ? bytes ??
三。計算每條記錄的長度: ??
這取決于三個方面, ??
? ? ? ? 1。表中定義的列的個數(shù) ??
? ? ? ? 2。每列的類型 ??
? ? ? ? 3。變長列的平均長度(根據(jù)與實際數(shù)據(jù)庫類似的測試數(shù)據(jù)庫) ??
? ? SELECT ? AVG(NVL(VSIZE(col1), ? 1)) ? + ??
? ? ? ? ? ? ? ? ? AVG(NVL(VSIZE(col2), ? 1)) ? + ??
? ? ? ? ? ? ? ? ? ... ? + ??
? ? ? ? ? ? ? ? ? AVG(NVL(VSIZE(coln), ? 1)) ? ? "SPACE ? OF ? AVERAGE ? ROW " ??
? ? ? ? ? ? ? ? ? FROM ? table_name; ??
注:記錄結(jié)尾的列如果不空,上述公式有效;如果結(jié)尾的列為空,該列長被計為0。 ??
舉例來講,我們創(chuàng)建了TEST表, ??
? ? CREATE ? TABLE ? test ? ( ? A ? CHAR(10), ? ? B ? DATE, ? ? C ? NUMBER(10, ? 2)); ??
我們可以通過 ??
? ? SELECT ? AVG(NVL(VSIZE(A), ? 1)) ? + ??
? ? ? ? ? ? ? ? ? AVG(NVL(VSIZE(B), ? 1)) ? + ??
? ? ? ? ? ? ? ? ? AVG(NVL(VSIZE(C), ? 1)) ? ? ? "SPACE ? OF ? AVERAGE ? ROW " ??
? ? ? ? ? ? ? ? ? FROM ? test; ??
來估算每條記錄的大小。 ??
如果測試數(shù)據(jù)庫不存在,則需要分別考慮各列的情況。 ??
? ? ? 1。對于定長列,每條記錄的該列值也是定長; ??
? ? ? 2。對于變長列,首先要估計該列的平均值,然后再決定該值需要多大空間。 ??
就TEST表來講,A列與B列均為定長列,所以他們分別需要10及7 ? BYTES來存儲。對于C列, ??
假設(shè)平均該值有8位長度,由于是數(shù)字類型,所以存儲長度為: ??
? ? average ? length ? column ? C ? = ? (average_precision/2 ? + ? 1) ? bytes ??
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? = ? (8/2 ? + ? 1) ? bytes ??
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? = ? 5 ? bytes ??
這樣, ? ? average ? row ? (for ? columns)= ? (A ? + ? B ? + ? C) ??
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? = ? (10 ? + ? 7 ? + ? 5) ? bytes ??
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? = ? 22 ? bytes ??
四。記錄平均存儲空間為: ??
? ? ? average ? row ? size ? = ? row ? header ? + ? F ? + ? V ? + ? D ? ? ??
? ? ? ? ? ? 其中: ??
? ? ? ? ? ? ? ? ? row ? header ? = ? 3 ? bytes ? (非CLUSTER表) ??
? ? ? ? ? ? ? ? ? F ? ? ? ? ? ? ? ? ? ? = ? 列長的總和(1 ? byte表示長度的列,CHAR, ? NUMBER, ? DATE, ? and ? ROWID ? types) ??
? ? ? ? ? ? ? ? ? V ? ? ? ? ? ? ? ? ? ? = ? 列長的總和(3 ? bytes表示長度的列,CHAR, ? LONG, ? RAW, ? LONG ? RAW ? datatypes) ??
? ? ? ? ? ? ? ? ? D ? ? ? ? ? ? ? ? ? ? = ? average ? row ? (for ? columns,from ? above) ??
說明: ??
1。由于每列數(shù)據(jù)在存儲時需要額外的位來表示其長度,通常,如果該列值> 250,需要3 ? bytes表示, ??
如果 <250,需要1 ? byte表示, ??
2。對于NON-CLUSTERED表,average ? row ? size最小值為9,所以如果上述值小于9,則要用9 ? bytes計算。 ??
再看TEST表, ??
? ? ? average ? row ? size ? ? ? = ? row ? header ? + ? F ? + ? V ? + ? D ? ? ??
? ? ? ? ? ? ? ? ? ? ? = ? 3+(1*3)+(3*0)+22 ??
? ? ? ? ? ? ? ? ? ? ? = ? 28 ? bytes ??
五。平均每塊中的記錄數(shù)為, ??
? ? average ? number ? of ? rows ? per ? block ? = ? floor(available ? data ? space ? / ? average ? row ? size) ??
? ? ? ? ? ? ? x ? ? ? = ? floor((1768-1.8x)/28) ??
? ? ? ? ? ? ? 28x ? ? ? ? =1768-1.8x ??
? ? ? ? ? ? ? x ? ? ? = ? 59 ? (近似值) ??
根據(jù)記錄量的大小,例如TEST表中有10000條記錄,可以算得該表需要的數(shù)據(jù)塊數(shù)量: ??
? ? number ? of ? blocks ??
? ? for ? the ? table ? ? ? ? ? = ? number ? of ? rows ? / ? average ? number ? of ? rows ? per ? block ??
? ? ? ? ? ? ? ? ? ? ? = ? 10000/59 ??
? ? ? ? ? ? ? ? ? ? ? = ? 169 ? blocks ? (近似值) ??
從而得到該表可能占據(jù)的存儲空間為169*db_block_size.
對索引空間的估算 ??
一。數(shù)據(jù)塊頭的大小 ??
? ? block ? header ? size ? = ? fixed ? header ? + ? variable ? transaction ? header ??
? ? ? ? ? 其中: ??
? ? ? ? ? ? ? ? fixed ? header ? = ? 113 ? bytes ??
? ? ? ? ? ? ? ? variable ? transaction ? header ? = ? 23*i ? ? ? ? (i=INITRANS) ??
假定INITRANS=2, ??
? ? block ? header ? size ? = ? 113 ? + ? (23 ? * ? 2) ? bytes ??
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? = ? 159 ? bytes ??
二。數(shù)據(jù)塊中可供INDEX使用的空間為: ??
? ? available ? data ? space ? = ? (block ? size ? - ? block ? header ? size) ? - ??
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ((block ? size ? - ? block ? header ? size) ? * ? (PCTFREE/100)) ??
假定PCTFREE=10,DB_BLOCK_SIZE=2K ??
? ? available ? data ? space ? = ? (2048 ? bytes ? - ? 159 ? bytes) ? - ??
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ((2048 ? bytes ? - ? 159 ? bytes) ? * ? (10/100)) ??
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? = ? 1889 ? bytes ? - ? 188.9 ? bytes ??
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? = ? 1700.1 ? bytes ??
三。INDEX ? entry的長度 ??
與表的計算方法類似,估算出被索引的列的平均長度之和,利用下面公式得到每一條INDEX ? ENTRY的長度。 ??
? ? bytes ? per ? entry ? = ? entry ? header ? + ? ROWID ? length ? + ? F ? + ? V ? + ? D ??
? ? ? ? ? 其中: ??
? ? ? ? ? ? ? ? entry ? header ? = ? 1 ? byte ??
? ? ? ? ? ? ? ? ROWID ? length ? = ? 6 ? bytes ??
? ? ? ? ? ? ? ? ? F ? ? ? ? ? ? ? ? ? ? = ? 列長的總和(1 ? byte表示長度的列,CHAR, ? NUMBER, ? DATE, ? and ? ROWID ? types) ??
? ? ? ? ? ? ? ? ? V ? ? ? ? ? ? ? ? ? ? = ? 列長的總和(3 ? bytes表示長度的列,CHAR, ? RAW ? datatypes) ??
? ? ? ? ? ? ? ? ? D ? ? ? ? ? ? ? ? ? ? = ? 被索引列長之和 ? ? (from ? above) ??
如果我們在TEST表上建立了在A,B,C三列上的一個索引,則D=22,于是 ??
? ? bytes ? per ? entry ? = ? 1 ? + ? 6 ? + ? (3 ? * ? 1) ? + ? (3 ? * ? 0) ? + ? 22 ? bytes ??
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? = ? 32 ? bytes ??
四。于是,該索引所需要的數(shù)據(jù)塊數(shù)量為: ??
? ? number ? of ? blocks ??
? ? for ? index ? ? ? ? ? ? ? ? = ? 1.1 ? * ? ((number ? of ? not ? null ? rows ? * ? avg. ? entry ? size) ? / ??
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ((floor ? (avail. ? data ? space ? / ? avg. ? entry ? size)) ? * ??
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? (avg. ? entry ? size)) ??
注:這里帶入了系數(shù)1.1主要考慮到INDEX的建立需要分支(BRANCH ? ENTRY ? BLOCKS) ??
? ? number ? of ? blocks ??
? ? for ? index ? ? ? ? ? ? ? ? = ? 1.1 ? * ? ((10000 ? * ? 32 ? bytes) ? / ? ((floor ? (1700/32 ? bytes)) ? * ??
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? (32 ? bytes)) ??
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? = ? 208 ? blocks ??
從而得到該表可能占據(jù)的存儲空間為208*db_block_size. ??
方法二: ??
利用ANALYZE進行空間估算 ??
如果可以建立一個模擬環(huán)境(模擬數(shù)據(jù)或者實際數(shù)據(jù)),也可以利用ANALYZE命令來進行空間估算。 ??
具體方法為: ??
一。ANALYZE ? TABLE ? testtable ? COMPUTE ? STATISTICS ??
在DBA_TABLES中有下面的列 ??
========================================= ??
? AVG_SPACE ? ? ? ? 表中平均剩余空間 ??
? AVG_ROW_LEN ? ? ? ? 平均一條記錄的長度 ??
? OWNER ? ? ? ? ? 表的所有者 ??
? TABLE_NAME ? ? ? ? 表名 ??
? NUM_ROWS ? ? ? ? 表中記錄數(shù) ??
========================================= ??
則: ??
表的大小(估計值) ? ? ? = ? ? ? ? ? DB_BLOCK_SIZE* ? ? ? ? ? ? ? ? ? ? ceil(實際表中記錄數(shù)/floor((DB_BLOCK_SIZE-AVG_SPACE)/AVG_ROW_LEN)) ??
二。ANALYZE ? INDEX ? testindex ? COMPUTE ? STATISTICS ??
在DBA_INDEXES中有下面的列 ??
========================================= ??
? OWNER ? ? ? ? ? 索引的所有者 ??
? INDEX_NAME ? ? ? ? 索引名 ??
? TABLE_OWNER ? ? ? ? 索引的基表所有者 ??
? TABLE_NAME ? ? ? ? 索引的基表 ??
? LEAF_BLOCKS ? ? ? ? 索引中葉子塊數(shù) ??
? BLEVEL ? ? ? ? ? ? ? ? B-Tree ? level: ? B-tree的深度, ??
? ? ? ? ? ? ? 如果為0表示根與葉子在同一個LEVEL上. ??
========================================= ??
則: ??
索引的大小(估計值) ? = ? LEAF_BLOCKS*ceil(實際表中記錄數(shù)/NUM_ROWS); ??
如果BLEVEL <> 0,還需要考慮再加上一個系數(shù),用來包含用作分支(BRANCH)塊的空間。 ??
此外,在INDEX_STATS視圖中包含了更詳細的有關(guān)索引空間及結(jié)構(gòu)上的分配情況,這需要事先進行 ??
ANALYZE ? INDEX ? testindex ? VALIDATE ? STRUCTURE的動作。有興趣可以詳細參見該視圖的定義。?
總結(jié)
- 上一篇: oracle数据库空间估算
- 下一篇: GoldenGate SQL error