Skip to Main Content

Breadcrumb

Question and Answer

Chris Saxon

Thanks for the question, Jose Laurindo.

Asked: February 26, 2016 - 1:25 pm UTC

Last updated: March 02, 2016 - 12:23 am UTC

Version: 11.2.0.4

Viewed 100+ times

You Asked

Hi - I need to find the used space (used for data) inside each data block in a heap table, for management reasons and (mainly) for self-education, too.
As we know, DBMS_SPACE shows the quantity of completely free blocks but what I need/want is to find, for all data blocks in a given segment , to know how many bytes are occupied with data and how many usable bytes are yet to be used in the block. The difficulties here are : the header/control part of a block is variable, the block size is variable, and each row length (of course) varies, too.
My main line of thought was to use DBMS_ROWID to find the block for each line, but I was unable to continue frm there.

Regards,

J. Laurindo Chiappa

and Connor said...

To look inside a single block or range of blocks, you can use a command to dump the datablocks to a trace file.

It's not documented, but if you google for "alter system dump datafile" you will find lots of examples.

Rating

  (2 ratings)

Is this answer out of date? If it is, please let us know via a Comment

Comments

Another point

Jose Laurindo Chiappa, February 29, 2016 - 4:59 pm UTC

Yes, a block dump would give the complete and exact answer about a block content, txs for the confirmation.
I was thinking more in the line of means - let's say, a very big table suffered deletion in a so singular pattern that the data blocks are not completely free, a few rows yet exists in each datablock (and thus this blocks do not appears in DBMS_SPACE reports), this table will be archived (ie, no more data will be entered) and we want/need to release this space to re-use elsewhere this space.
My line of thinking was, for each "suspect" table :

- calculate (by hand) the ** mean ** row length rigth now, OR (with some clever manipulation finding blocks for each row of data) find the exact number of rows in each block
- find the total block size
- find the expected number of lines to be contained in a block (creating a "copy" of the suspect table structure and doing a lot of inserts only)
- check in the real suspect table if the mean number of lines present right now per block is very less than the expected number (analyzing the table and looking at the xx_TABLES columns) : if so, this table is a real candidate for any kind of shrink/move/rebuild, the space to be gained after that probably is significative.

It makes some sense ?

[]s

J. Laurindo Chiappa

OBS : in another point , I don't know if the % of data block occupation (given in DBMS_SPACE.FREE_SPACE via FS1/FS2/FS3/FS4, as https://asktom.oracle.com/pls/asktom/f?p=100:11:::::P11_QUESTION_ID:231414051079 ) could be used to find segments with a lot of semi-occupied data blocks and thus to-shrink candidates if we know that no more data will be entered....
Chris Saxon
February 29, 2016 - 11:55 pm UTC

Check out DBMS_ROWID if you want to drill into that.

eg

SQL> create table t1 as select * from dba_objects;

Table created.

SQL>
SQL> delete from t1
  2  where object_id between 40000 and 50000
  3  or mod(object_id,5) = 0;

27350 rows deleted.

SQL>
SQL> commit;

Commit complete.

SQL>
SQL> select rows_per_block, count(*)
  2  from (
  3    select
  4      dbms_rowid.ROWID_RELATIVE_FNO(rowid) f,
  5      dbms_rowid.ROWID_BLOCK_NUMBER(rowid) b,
  6      count(*) rows_per_block
  7    from t1
  8    group by
  9      dbms_rowid.ROWID_RELATIVE_FNO(rowid),
 10      dbms_rowid.ROWID_BLOCK_NUMBER(rowid)
 11  )
 12  group by rows_per_block
 13  order by 1;

ROWS_PER_BLOCK   COUNT(*)
-------------- ----------
            16          1
            30          1
            38          1
            41          1
            42          4
            43          2
            44         18
            45        163
            46        389
            47        291
            48        146
            49         85
            50         80
            51         87
            52         81
            53         47
            54         23
            55         14
            56          4
            57          4
            58          7
            59          1
            61          1

23 rows selected.


Thanks!

Jose Laurindo Chiappa, March 01, 2016 - 5:01 pm UTC

Many thanks - this kind of usage for DBMS_ROWID was exactly what I was thinking, thanks...
Chris Saxon
March 02, 2016 - 12:23 am UTC

Glad we could help

More to Explore

DBMS_SPACE

More on PL/SQL routine DBMS_SPACE here