Oracle Scratchpad

September 11, 2016

Space Usage

Filed under: fragmentation,Infrastructure,Oracle,Troubleshooting — Jonathan Lewis @ 6:09 pm BST Sep 11,2016

Here’s a simple script that I’ve used for many years to check space usage inside segments.  The comment about freelist groups may be out of date  – I’ve not had to worry about that for a very long time. There is a separate script for securefile lobs.


rem
rem     Script:         dbms_space_use.sql
rem     Author:         Jonathan Lewis
rem     Dated:          Nov 2002
rem     Purpose:        
rem
rem     Last tested 
rem             12.1.0.2
rem             11.2.0.4
rem     Not tested
rem             11.1.0.7
rem             10.2.0.5
rem              9.2.0.8
rem     Not relevant
rem              8.1.7.4
rem
rem     Notes:
rem     For accuracy in free space you (once) needed to set the
rem     scan limit; and for those rare objects cases where you 
rem     had defined multiple freelist groups you still have to
rem     work through each free list group in turn
rem
rem     For the ASSM calls:
rem             FS1     => 0% - 25% free space
rem             FS2     => 25% - 50% free space
rem             FS3     => 50% - 75% free space
rem             FS4     => 75% - 100% free space
rem             Bytes = blocks * block size
rem
rem     Expected errors:
rem             ORA-10614: Operation not allowed on this segment
rem                     (MSSM segment, ASSM call)
rem             ORA-10618: Operation not allowed on this segment
rem                     (ASSM segment, MSSM call)
rem             ORA-03200: the segment type specification is invalid
rem                     (e.g. for LOBINDEX or LOBSEGMENT)
rem                     11g - "LOB" is legal for LOB segments
rem                         - use "INDEX" for the LOBINDEX
rem
rem     For indexes
rem             Blocks are FULL or FS2 (re-usable)
rem
rem     Special case: LOB segments.
rem     The number of blocks reported by FS1 etc. is actually the
rem     number of CHUNKS in use (and they're full or empty). So 
rem     if your CHUNK size is not the same as your block size the
rem     total "blocks" used doesn't match the number of blocks 
rem     below the HWM.
rem
rem     The package dbms_space is created by dbmsspu.sql
rem     and the body is in prvtspcu.plb
rem
rem     11.2 overloads dbms_space.space_usage for securefile lobs
rem     See dbms_space_use_sf.sql
rem
rem     When supplying details about partitions the segment type
rem     can consist of two words (e.g. LOB PARTITION), these 
rem     must be surrounded by quotes to survive the script.
rem
rem     You might want to set up two versions of this code with
rem     all references to partitions removed from one of them
rem     or you have to keep pressing return to bypass the 
rem     requests for substitution variables
rem

define m_seg_owner      = &1
define m_seg_name       = &2
define m_seg_type       = '&3'
define m_part_name      = &4

define m_segment_owner  = &m_seg_owner
define m_segment_name   = &m_seg_name
define m_segment_type   = '&m_seg_type'
define m_partition_name = &m_part_name

set linesize 156
set pagesize 60
set trimspool on
set tab off
spool dbms_space_use

prompt  ===================
prompt  Freelist management
prompt  ===================

declare
        wrong_ssm       exception;
        pragma exception_init(wrong_ssm, -10618);

        m_free  number(10);
begin
        dbms_space.free_blocks(
                segment_owner           => upper('&m_segment_owner'),
                segment_name            => upper('&m_segment_name'),
                segment_type            => upper('&m_segment_type'),
                partition_name          => upper('&m_partition_name'),
--              scan_limit              => 50,
                freelist_group_id       => 0,
                free_blks               => m_free
        );
        dbms_output.put_line('Free blocks below HWM: ' || m_free);
exception
        when wrong_ssm then
                dbms_output.put_line('Segment not freelist managed');
end;
/


prompt  ====
prompt  ASSM
prompt  ====

declare
        wrong_ssm       exception;
        pragma exception_init(wrong_ssm, -10614);

        m_unformatted_blocks    number;
        m_unformatted_bytes     number;
        m_fs1_blocks            number;
        m_fs1_bytes             number;
        m_fs2_blocks            number;  
        m_fs2_bytes             number;

        m_fs3_blocks            number;
        m_fs3_bytes             number;
        m_fs4_blocks            number; 
        m_fs4_bytes             number;
        m_full_blocks           number;
        m_full_bytes            number;

begin
        dbms_space.SPACE_USAGE(
                segment_owner           => upper('&m_segment_owner'),
                segment_name            => upper('&m_segment_name'),
                segment_type            => upper('&m_segment_type'),
                unformatted_blocks      => m_unformatted_blocks,
                unformatted_bytes       => m_unformatted_bytes, 
                fs1_blocks              => m_fs1_blocks , 
                fs1_bytes               => m_fs1_bytes,
                fs2_blocks              => m_fs2_blocks,  
                fs2_bytes               => m_fs2_bytes,
                fs3_blocks              => m_fs3_blocks,  
                fs3_bytes               => m_fs3_bytes,
                fs4_blocks              => m_fs4_blocks,  
                fs4_bytes               => m_fs4_bytes,
                full_blocks             => m_full_blocks, 
                full_bytes              => m_full_bytes,
                partition_name          => upper('&m_partition_name')
        );


        dbms_output.new_line;
        dbms_output.put_line('Unformatted                   : ' || to_char(m_unformatted_blocks,'999,999,990') || ' / ' || to_char(m_unformatted_bytes,'999,999,999,990'));
        dbms_output.put_line('Freespace 1 (  0 -  25% free) : ' || to_char(m_fs1_blocks,'999,999,990') || ' / ' || to_char(m_fs1_bytes,'999,999,999,990'));
        dbms_output.put_line('Freespace 2 ( 25 -  50% free) : ' || to_char(m_fs2_blocks,'999,999,990') || ' / ' || to_char(m_fs2_bytes,'999,999,999,990'));
        dbms_output.put_line('Freespace 3 ( 50 -  75% free) : ' || to_char(m_fs3_blocks,'999,999,990') || ' / ' || to_char(m_fs3_bytes,'999,999,999,990'));
        dbms_output.put_line('Freespace 4 ( 75 - 100% free) : ' || to_char(m_fs4_blocks,'999,999,990') || ' / ' || to_char(m_fs4_bytes,'999,999,999,990'));
        dbms_output.put_line('Full                          : ' || to_char(m_full_blocks,'999,999,990') || ' / ' || to_char(m_full_bytes,'999,999,999,990'));

exception
        when wrong_ssm then
                dbms_output.put_line('Segment not ASSM');
end;
/


prompt  =======
prompt  Generic
prompt  =======

declare
        m_total_blocks                  number;
        m_total_bytes                   number;
        m_unused_blocks                 number;
        m_unused_bytes                  number;
        m_last_used_extent_file_id      number;
        m_last_used_extent_block_id     number;
        m_last_used_block               number;
begin
        dbms_space.unused_space(
                segment_owner           => upper('&m_segment_owner'),
                segment_name            => upper('&m_segment_name'),
                segment_type            => upper('&m_segment_type'),
                total_blocks            => m_total_blocks,
                total_bytes             => m_total_bytes, 
                unused_blocks           => m_unused_blocks,  
                unused_bytes            => m_unused_bytes,
                last_used_extent_file_id        => m_last_used_extent_file_id, 
                last_used_extent_block_id       => m_last_used_extent_block_id,
                last_used_block         => m_last_used_block,
                partition_name          => upper('&m_partition_name')
        );

        dbms_output.put_line('Segment Total blocks: '  || to_char(m_total_blocks,'999,999,990'));
        dbms_output.put_line('Object Unused blocks: '  || to_char(m_unused_blocks,'999,999,990'));

end;
/

undefine 1
undefine 2
undefine 3
undefine 4

undefine m_seg_owner
undefine m_seg_name
undefine m_seg_type
undefine m_part_name

undefine m_segment_owner
undefine m_segment_name
undefine m_segment_type
undefine m_partition_name

spool off

Here’s a sample of output (from a segment using ASSM):


===================
Freelist management
===================
Segment not freelist managed

PL/SQL procedure successfully completed.

====
ASSM
====

Unformatted                   :  132,385 / ############
Freespace 1 (  0 -  25% free) :        0 /            0
Freespace 2 ( 25 -  50% free) :        0 /            0
Freespace 3 ( 50 -  75% free) :        0 /            0
Freespace 4 ( 75 - 100% free) :        0 /            0
Full                          :   12,327 /  100,982,784

PL/SQL procedure successfully completed.

=======
Generic
=======
Segment Total blocks: 145920
Object Unused blocks: 0

PL/SQL procedure successfully completed.

(I’ve increased the length of the byte-count output since I produced that report ;)

8 Comments »

  1. […] to ensure that the last extent in the segment had just a few blocks left – and I used my “dbms_space_use.sql” script to check this, getting the following […]

    Pingback by Basicfile LOBs 6 | Oracle Scratchpad — September 11, 2016 @ 7:48 pm BST Sep 11,2016 | Reply

  2. […] script hacked together a couple of years ago from a clone of a script I’d been using for checking space usage in the older types of segments. Oracle Corp. […]

    Pingback by Securefile space | Oracle Scratchpad — September 13, 2016 @ 7:30 am BST Sep 13,2016 | Reply

  3. Hi Jonathan, Did you run the test in non-RAC database?

    Comment by dbabible — September 21, 2016 @ 3:33 am BST Sep 21,2016 | Reply

    • dbabible,

      Yes, I don’t think I’ve ever run it on a RAC system – but I don’t think that would make any difference to the way it works.

      Comment by Jonathan Lewis — September 22, 2016 @ 9:14 pm BST Sep 22,2016 | Reply

  4. […] used less than 300 bytes in the block. But I’ve got a little procedure (I published this version of it some time ago) to check for free and used space – and this is what it said about the […]

    Pingback by 255 Again! | Oracle Scratchpad — May 24, 2017 @ 11:21 am BST May 24,2017 | Reply

  5. […] The number of rows per block after this insert is 24, with 1038 bytes free space left (808 due to the pctfree = 10, then the bit that was too small to take a 25th row before breaching the pctfree barrier). This means we should report 1M/24 = 41,666 full blocks and one block with some free space. So we query the table using the dbms_space package: […]

    Pingback by ASSM argh! | Oracle Scratchpad — January 9, 2018 @ 5:53 pm GMT Jan 9,2018 | Reply

  6. […] of one of the securefile options here, and the generic ASSM code that we need is part of the script here. Our estimate (excluding the 1% metadata) should be a reasonable match for the “Full […]

    Pingback by LOB space | Oracle Scratchpad — July 20, 2022 @ 5:07 pm BST Jul 20,2022 | Reply

  7. […] final call in the script is to a stripped down version of some code I published a few years back; the relevance of the numbers when applied to indexes is desribed in this blog […]

    Pingback by Shrinking indexes | Oracle Scratchpad — September 2, 2022 @ 7:22 pm BST Sep 2,2022 | Reply


RSS feed for comments on this post. TrackBack URI

Comments and related questions are welcome.

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Website Powered by WordPress.com.