/* * table_size_info.rw * * DESCRIPTION: * Report to view table size information. It selects all table/index info * from the system catelogs. Then, based on the last time the structure was * modified, it will calculate the amount of pages the table will take if * remodified with the parameters used the last time (like MINPAGES & * FILLFACTOR). * * CREATION: * Mark Kale * * MODIFICATIONS: * Init Date Comments * ---- ---- -------- * mdk 092496 Added total size of db * mdk 092496 Got rid of length and key_length columns, added Kb Waste * */ .name table_size_info .shortremark DBA: Table Size & Re-Modification Information .lm 0 .rm 80 .pl 66 .noformfeeds .setup set autocommit on; /* for interactive use */ set lockmode session where readlock = nolock; .query select db = dbmsinfo ('database'), t.table_name, t.storage_structure, t.is_compressed, t.table_type, t.num_rows, t.row_width, t.number_pages, t.overflow_pages, data_fill = float8 (float8(t.table_dfillpct) / 100), leaf_fill = float8 (float8(t.table_lfillpct) / 100), index_fill = float8 (float8(t.table_ifillpct) / 100), minpages = t.table_minpages, maxpages = t.table_maxpages, c.column_name, c.column_nulls, c.column_datatype, col_len = c.column_length from iitables t, iicolumns c where t.table_owner = dbmsinfo ('dba') /* DBA tables */ and t.storage_structure != 'HEAP' /* have no keys */ and t.table_type in ('T', 'I') /* also get indexes */ and t.table_name = c.table_name and t.table_owner = c.table_owner and c.key_sequence > 0 /* only count keys */ union select db = dbmsinfo ('database'), t.table_name, t.storage_structure, t.is_compressed, t.table_type, t.num_rows, t.row_width, t.number_pages, t.overflow_pages, data_fill = (t.table_dfillpct / 100), leaf_fill = (t.table_lfillpct / 100), index_fill = (t.table_ifillpct / 100), minpages = t.table_minpages, maxpages = t.table_maxpages, column_name = '', column_nulls = 'N', column_datatype = '', col_len = 0 from iitables t where t.table_owner = dbmsinfo ('dba') /* DBA tables */ and t.storage_structure = 'HEAP' and t.table_type = 'T' .sort number_pages :desc, table_name, column_name .position table_name (0), storage_structure (24), number_pages (30), overflow_pages (46), num_rows (54) .declare key_len = integer, /* key length */ rows_per_page = integer, /* number of tuples per data page */ page_break = integer, x = integer, free = integer, keys_per_lpage = integer, /* number of keys per leaf page */ keys_per_ipage = integer, /* number of keys per index page */ max_keys = integer, leaf_pages = integer, data_pages = integer, remainder = integer, sprig_pages = integer, index_pages = integer, required_pages = integer, csum = integer with value "0", nsum = integer with value "0", rsum = integer with value "0", waste = float /* Need a separate header for REPORT since we want the report description only * on the first page. */ .header report .left .pr "DB: ", uppercase (db) (c0) .center .pr "Table Size Information" .right .pr "As of: ", date('today') (d"03-feb-01") .nl .right .pr "Page : ", page_number .center .pr "TABLE_SIZE_INFO.RW" .nl 2 .tab 5 .pln "This report shows all DBA-owned tables, there current size as reported by" .tab 5 .pln "the system catelogs, and the amount of space the table would require if" .tab 5 .pln "re-modified with the same parameters as it was before. A %Waste is also" .tab 5 .pln "given which shows the relative waste. If OVFLW is indicated, it means the" .tab 5 .pln "table/index is actually 'fuller' than it would be if re-modified. For" .tab 5 .pln "compressed tables, the compression ratio is shown." .nl 2 .ul .tab table_name .pr "Table" .tab storage_structure .pr "Type" .right number_pages .pr "# Pages" .right 45 .pr "Req Pgs" .right overflow_pages .pr "# Ovflw" .right num_rows .pr "# Rows" .right 73 .pr "Waste(Kb)" .tab 74 .pr "%Waste" .nl .noul .let page_break = 1 .header page .left .pr "DB: ", uppercase (db) (c0) .center .pr "Table Size Information" .right .pr "As of: ", date('today') (d"03-feb-01") .nl .right .pr "Page : ", page_number .nl 2 .ul .tab table_name .pr "Table" .tab storage_structure .pr "Type" .right number_pages .pr "# Pages" .right 45 .pr "Req Pgs" .right overflow_pages .pr "# Ovflw" .right num_rows .pr "# Rows" .right 72 .pr "Waste(MB)" .tab 74 .pr "%Waste" .nl .noul .let page_break = 1 .header table_name .let key_len = 0 .detail /* figure out the real key_length */ .let key_len = key_len + col_len .if column_datatype = 'VARCHAR' .then .let key_len = key_len + 2 .elseif column_datatype = 'DATE' .then .let key_len = 12 .elseif column_datatype = 'MONEY' .then .let key_len = 10 .endif .if column_nulls = 'Y' .then .let key_len = key_len + 1 .endif .footer table_name .tab table_name .pr table_name (c24) .if is_compressed = 'Y' .then .tab (storage_structure) .tab -1 .pr "C" /* for compressed */ .endif .tab storage_structure .pr storage_structure (c5) .if number_pages < 1000000 .then .right number_pages .pr number_pages ("zzz,zzn") .else .right number_pages .pr number_pages ("zzzzzzn") .endif .if storage_structure = 'HASH' or storage_structure = 'ISAM' .then .if overflow_pages < 1000000 .then .right overflow_pages .pr overflow_pages ("zzz,zzn") .else .right overflow_pages .pr overflow_pages ("zzzzzzn") .endif .endif .if num_rows < 10000000 .then .right num_rows .pr num_rows ("z,zzz,zzn") .else .right num_rows .pr num_rows ("zzzzzzzzn") .endif .if storage_structure = 'HASH' .then .let rows_per_page = (data_fill * 2008) / (row_width + 2) .if rows_per_page < 1 .then .let rows_per_page = 1 .endif .let required_pages = (num_rows / rows_per_page) .if required_pages < minpages .then .let required_pages = minpages .elseif required_pages > maxpages and maxpages > 0 .then .let required_pages = maxpages .endif .elseif storage_structure = 'HEAP' .then .let rows_per_page = 2008 / (row_width + 2) .if rows_per_page < 1 .then .let rows_per_page = 1 .endif .let required_pages = (num_rows / rows_per_page) .elseif storage_structure = 'BTREE' .then .let rows_per_page = (data_fill * 2010) / (row_width + 2) .if rows_per_page < 1 .then .let rows_per_page = 1 .endif .let free = 2008 - (rows_per_page * (row_width + 2)) .if (free > (2048 - (data_fill * 2048))) and (row_width <= free) .then .let rows_per_page = rows_per_page + 1 .endif .if rows_per_page > 512 .then .let rows_per_page = 512 .endif /* For BTREE secondary indexes, all data is at leaf level */ .if table_type = 'I' .then .let key_len = row_width .endif .let max_keys = (1964 / (key_len + 6)) - 2 .let keys_per_lpage = max_keys * leaf_fill .let keys_per_ipage = max_keys * index_fill .if keys_per_lpage < 2 .then .let keys_per_lpage = 2 .endif .if keys_per_ipage < 2 .then .let keys_per_ipage = 2 .endif .let leaf_pages = (num_rows / keys_per_lpage) .let data_pages = leaf_pages * int4(float8(keys_per_lpage) / rows_per_page + .9999) .let remainder = num_rows - (leaf_pages * keys_per_lpage) .if remainder > 0 .then .let leaf_pages = leaf_pages + 1 .let data_pages = data_pages + int4(float8(remainder) / rows_per_page + .9999) .endif .if table_type = 'I' .then .let data_pages = 0 .endif .if leaf_pages <= keys_per_ipage .then .let sprig_pages = 0 .else .let sprig_pages = (float8(leaf_pages) / keys_per_ipage + .9999) .endif /* figure number of non-index pages, an iterative calulation which * is fudged here. Will have a separate calculation for each level * of non-sprig index pages. */ .let index_pages = 0 .if sprig_pages > keys_per_ipage .then .let x = sprig_pages / keys_per_ipage .let index_pages = x .if x > keys_per_ipage .then .let x = x / keys_per_ipage .let index_pages = index_pages + x .if x > keys_per_ipage .then .let x = x / keys_per_ipage .let index_pages = index_pages + x .if x > keys_per_ipage .then .let x = x / keys_per_ipage .let index_pages = index_pages + x .if x > keys_per_ipage .then .let x = x / keys_per_ipage .let index_pages = index_pages + x .endif .endif .endif .endif .endif /* have non-sprig pages */ .let required_pages = data_pages + leaf_pages + sprig_pages + index_pages + 2 .elseif storage_structure = 'ISAM' .then .let rows_per_page = (data_fill * 2008) / (row_width + 2) .if rows_per_page < 1 .then .let rows_per_page = 1 .endif .let free = 2008 - (rows_per_page * (row_width + 2)) .if (free > (2048 - (data_fill * 2048))) and (row_width <= free) .then .let rows_per_page = rows_per_page + 1 .endif .if rows_per_page > 512 .then .let rows_per_page = 512 .endif .let data_pages = num_rows / rows_per_page .let keys_per_ipage = 2008 / (key_len + 2) .let index_pages = data_pages / keys_per_ipage .let required_pages = index_pages + data_pages .if required_pages >= 2 .then .let required_pages = required_pages + 2 .else .let required_pages = 2 .endif .endif .if required_pages <= 0 .then .let required_pages = 1 .endif .if required_pages < 1000000 .then .right 45 .pr required_pages ("zzz,zzn") .else .right 45 .pr required_pages ("zzzzzzn") .endif /* haven't figured out compression */ .if is_compressed = 'N' .then .if (number_pages-required_pages) > 0 .then .right 72 .pr ((number_pages-required_pages))*2 ("zzz,zzz") .endif .tab 74 .let waste = (float8(number_pages - required_pages) * 100 / required_pages) .if waste < 0 .then .pr "OvrFul" .else .pr waste (f6.1) .endif .let nsum = nsum + number_pages .let rsum = rsum + required_pages .else /* print compression ratio */ .tab 74 .let waste = required_pages / number_pages .pr waste (i4), ':1' .let csum = csum + number_pages .endif .nl /* * DEBUG code * .pln "tot = ", required_pages (i6), " data= ", data_pages (i6), " leaf= ", leaf_pages (i6), " sprig= ", sprig_pages (i6), " idx = ", index_pages (i6) .pln "lpage = ", keys_per_lpage (i3), " ipage= ", keys_per_ipage (i3), "rows/p= ", rows_per_page (i3) */ .footer report .need 5 .nl 2 .pln "Database is: ", ((nsum+csum) * 2 / 1024) ("zzz,zzz,zzn"), "Mb" .pln "It requires: ", ((rsum+csum) * 2 / 1024) ("zzz,zzz,zzn"), "Mb" .pln "We can save: ", (((nsum+csum) - (rsum+csum)) * 2 / 1024) ("zzz,zzz,zzn"), "Mb" Mark Kale mdkale@aol.com Caribou Lake Software, Inc. www.CaribouLake.com
© William Yuan 2000
Email William