Oracle Server - Enterprise Edition - Version: 11.1.0.7 and later [Release: 11.1 and later ]
The purpose of this note is to provide insight on how space allocation ( v$asm_file.space column ) in ASM can be calculated depending on Allocation Unit size, redundancy and striping scheme.
        db_recovery_file_dest_size should be calculated carefully by taking into redundancy, striping and AU boundary as it can cause database hung in a situation when archivelog can not be generated. 
This note will be useful - 
 1. Calculate the exact size of a file in ASM environment. 
 2. Calculate v$recovery_file_dest.space_used for flashback logs and archived log files.
注意事项:
        This script is provided for educational purposes only and not supported by Oracle Support Services. It has been tested internally, however, and works as documented. We do not guarantee that it will work for you, so be sure to test it in your environment before relying on it. 
       Proofread this script before using it! Due to the differences in the way text editors, e-mail packages and operating systems handle text formatting (spaces, tabs and carriage returns), this script may not be in an executable state when you first receive it. Check over the script to ensure that errors of this type are corrected. 
ASM space allocation consideration 
       1.    The space of each ASM file is allocated in Allocation Unit boundary - default 1M but can be specified at the creation of a diskgroup with an attribute. 
      2. Each file on ASM is created with a corresponding template either explictly or implictly depending on file type. 
 - Check v$asm_template 
 - Attribute can be altered. 
 SQL> alter diskgroup <diskgroup_name> alter template <template_name> attributes ( coarse ) ; 
3.  v$asm_file.bytes is calculated from v$asm_file.blocks * v$asm_file.block_size . 
 4.  v$asm_file.block_size varies to the file type - online redo - 512 bytes, control file - 16K etc . 
 5. v$asm_file.space is calculated by taking into account of AU boundary, redundancy and striping width. See Useful SQL statement - SQL1. 
 -  For FINE striping scheme with 128K, striping width is 8 AU (Allocation Units. ) 
 - 1st 128K needs 1AU space allocation and 2nd 128K needs another 1AU, subsequently 1M with 128K striping width needs 8AU space allocation. 
 6. Big space gap between v$asm_file.bytes and v$asm_file.space can be seen if an ASM file is created with a combination of FINE striping and normal or high redundancy. 
 7. In Oracle instance side, v$recovery_file_dest.space_used only takes into account of AU boundary of v$asm_file.bytes, doesn't take into striping and redundancy. 
 - See Useful SQL satement - SQL2. 
 - This is mainly because v$asm_file.space does not mean all space in these extent is full. 
 - v$recovery_file_dest.space_used = sum(ceil (( v$asm_file.bytes + 1) / AU ) * AU ) 
 8. But recovery destination cleanup mechanism will kick in by the usage of based on v$asm_file.space. 
Useful SQL statement 
SQL1: How v$asm_file.space is calculated from v$asm_file.bytes depending on striping and redundancy scheme of a diskgroup. 
- Please note that space allocation on ASM diskgroup is based on v$asm_file.space, not from v$asm_file.bytes.
------------------------- 
 set linesize 140 
 col g_n format 999 
 col f_n format 9999 
 col bytes format 999,999,999,999 
 col space format 999,999,999,999 
 col a_i format 999 
 col blocks format 999,999 
 col block_size format 999,999 
 col ftype format a16 
 col dir format a3 
 col s_created format a10 
 col full_alias_path format a40 
 col striped format a6 
 col rdun format a6 
 col au format 99999999 
 col calculated format 999,999,999,999 
 select x.gnum g_n, 
 x.filnum f_n, 
 substr(x.full_alias_path,1, 40) full_alias_path, 
 f.striped, 
 f.redundancy rdun, 
 f.bytes, 
 f.space, 
 case when calculated / x.au > 60 then calculated + 3 * x.au -- Over 60 direct extents consideration 
 else calculated 
 end calculated 
 from ( SELECT gnum,filnum,au, concat('+'||gname, sys_connect_by_path(aname, '/')) full_alias_path 
 from ( SELECT g.name gname, 
 g.allocation_unit_size au, 
 a.parent_index pindex, 
 a.name aname, 
 a.reference_index rindex, 
 a.group_number gnum, 
 a.file_number filnum 
 FROM v$asm_alias a, v$asm_diskgroup g 
 WHERE a.group_number = g.group_number) 
 START WITH (mod(pindex, power(2, 24))) = 0 CONNECT BY PRIOR rindex = pindex) x, 
 (select f.group_number gnum, 
 f.file_number filnum, 
 f.type ftype , 
 f.bytes, 
 f.space, 
 f.blocks, 
 f.block_size, 
 f.striped, 
 f.redundancy, 
 case f.striped when 'FINE' 
 then ceil(((f.blocks * f.block_size + 1) / g.allocation_unit_size) / 8) 
 * decode(f.redundancy, 'HIGH', 3 , 'MIRROR', 2, 'UNPROT', 1 ) * 8 * g.allocation_unit_size 
 else ceil((f.blocks * f.block_size + 1) / g.allocation_unit_size) 
 * decode(f.redundancy, 'HIGH', 3 , 'MIRROR', 2, 'UNPROT', 1 ) * g.allocation_unit_size 
 end calculated 
 from v$asm_file f , v$asm_diskgroup g 
 where f.group_number = g.group_number 
 order by f.group_number,file_number) f 
 where x.filnum != 4294967295 
 and x.gnum=f.gnum and x.filnum=f.filnum 
 / 
 ------------------------- 
SQL2. How v$recovery_file_dest.space_used is calculated from v$asm_file.bytes. 
 ------------------------- 
 set linesize 140 
 col g_n format 999 
 col f_n format 9999 
 col bytes format 999,999,999,999 
 col space format 999,999,999,999 
 col a_i format 999 
 col blocks format 999,999 
 col block_size format 999,999 
 col ftype format a16 
 col dir format a3 
 col s_created format a10 
 col full_alias_path format a40 
 col striped format a6 
 col redundancy format a10 
 col au format 99999999 
 col size_au format 999,999,999,999 
 break on report 
 compute sum of size_au on report 
 select x.gnum g_n, 
 x.filnum f_n, 
 substr(x.full_alias_path,1, 40) full_alias_path, 
 f.ftype, 
 f.bytes, 
 ceil((f.bytes + 1 ) / x.au ) * x.au size_au, -- take into account only AU boundary of actual bytes 
 f.space, 
 f.striped, 
 f.redundancy 
 from (select gname, gnum,filnum, au, concat('+'||gname, sys_connect_by_path(aname, '/')) full_alias_path 
 from ( select g.name gname, 
 g.allocation_unit_size au, 
 a.parent_index pindex, 
 a.name aname, 
 a.reference_index rindex, 
 a.group_number gnum, 
 a.file_number filnum 
 from v$asm_alias a, v$asm_diskgroup g 
 where a.group_number = g.group_number) 
 start with (mod(pindex, power(2, 24))) = 0 connect by prior rindex = pindex 
 ) x, 
 (select f.group_number gnum, 
 f.file_number filnum, 
 f.type ftype , 
 f.bytes, 
 f.space, 
 f.redundancy, 
 f.striped 
 from v$asm_file f 
 order by f.group_number,file_number 
 ) f 
 where x.filnum != 4294967295 
 and x.gname = '&DB_RECOVERY_FILE_DEST' -- Put the diskgroup name seen in db_recovery_file_dest 
 and x.gnum=f.gnum 
 and x.filnum=f.filnum 
 / 
 --------------------------------- 
SQL3. v$asm_template - striping and redundancy information for ASM files. 
 --------------------------- 
 set linesize 140 
 col g_n format 99 
 col e_n format 999 
 col name format a20 
 select group_number g_n, 
 entry_number e_n, 
 name, 
 redundancy, 
 stripe, 
 system 
 from v$asm_template 
 order by g_n, e_n 
 / 
 --------------------------- 
SQL4. SQL for querying v$recovery_file_dest 
--------------------------------- 
 set linesize 140 
 col name format a20 
 col space_limit format 999,999,999,999 
 col space_used format 999,999,999,999 
 col space_reclaimable format 999,999,999,999 
 col number_of_files format 999,999,999,999 
 select name, 
 space_limit, 
 space_used, 
 space_reclaimable, 
 number_of_files 
 from v$recovery_file_dest 
 /
From Oracle
-------------------------------------------------------------------------------------------------------










