Archives October 2023

ROLL_INVALID_MISMATCH UNSHARED CURSORS ISSUE ORACLE

I recently came into an issue related to high version counts for a particular query where the reason is ROLL_INVALID_MISMATCH. Customer was frequently gathering statistics for the objects in the database making the old statistics to invalidate with a new child cursor.

Oracle invalidate the statistics for the objects in the database periodically from 10g to avoid unexpected surprises of CPU spikes due to hard parse of the new statistics which need to be used for the sql statements as part of optimizer execution plan generation.

Oracle has introduced automatic control over invalidation of the cursors for freshly created statistics with no_invalidate => DBMS_STATS.AUTO_INVALIDATE of DBMS_STATS package from 10g onwards. Until the threshold value for _optimizer_invalidation_period parameter is met, the old cursors are reused for the object statistics.

kish@x3z6zx9<^>col INVALIDATION_MODE for a30
kish@x3z6zx9<^>SELECT DBMS_STATS.get_prefs(pname=>'NO_INVALIDATE') Invalidation_mode FROM dual;

INVALIDATION_MODE
------------------------------
DBMS_STATS.AUTO_INVALIDATE

A sample shell script to simulate the ROLL_INVALID_MISMATCH issue. This script will generate a pool of child cursors over time and populate the shared pool.

[oracle@x3dbzx36 ~]$ cat test.sql
#!/bin/bash -x

export ORACLE_SID=x3x6zx6
export ORACLE_HOME=/apps01/base/product/11.2.0/dbhome

c=0
while [ $c -lt 1000 ];
do
$ORACLE_HOME/bin/sqlplus -S '/ as sysdba' <<EOF
spool ri.txt
set lines 200 pages 1000
set timing on
set echo on
ALTER system set "_optimizer_invalidation_period"=10;
!sleep 15
select to_char(last_analyzed,'DD-MM-YY HH24:MI:SS') last_analyzed from dba_tables where table_name='YTBL';
select count(*) from ytbl;
col child_number for 99999
col parse_calls for 99999
col executions for 9999999
col first_load_time for a20
col last_load_time for a20
SELECT      child_number,parse_calls,executions,first_load_time,last_load_time,last_active_time
FROM v\$sql WHERE sql_id='8bsh7ckvjnx9x';
!sleep 15
SELECT ROLL_INVALID_MISMATCH from v\$sql_shared_cursor WHERE sql_id='8bsh7ckvjnx9x';
insert /*+append parallel(8)*/ into ytbl
select dbms_random.string('a','10'),
           yid.nextval,
           decode(round(dbms_random.value(0,10)),0,'Chennai',1,'Canberra',2,'Berlin',3,'London',4,'Paris',5,'Washington',6,'Lisbon',7,'Madrid',8,'Mumbai',9,'Moscow',10,'Rome'),
       floor(dbms_random.value(1,1000000))
from (select level from dual connect by level <= 1),
(select level from dual connect by level <= 1),
(select level from dual connect by level <= 1);
commit;
EXEC dbms_stats.gather_table_stats('SYS','YTBL');
spool off
exit;
EOF
c=`expr $c + 1`
done

There are almost 1602 cursors which are created as child for parent cursor

kish@x3z6zx9<^>col RIM for a30
kish@x3z6zx9<^>col COUNT for 999999999
kish@x3z6zx9<^>SELECT rpad('ROLL_INVALID_MISMATCH : ',33)|| ROLL_INVALID_MISMATCH as RIM ,count(*) count FROM v$sql_shared_cursor GROUP BY ROLL_INVALID_MISMATCH;

RIM                                 COUNT
------------------------------ ----------
ROLL_INVALID_MISMATCH :              1602
   Y

ROLL_INVALID_MISMATCH :              3834
   N

The output shows two parse calls for every 1 minute as the value for _optimizer_invalidation_period is 10 but the first cursor load time is same from parent cursor 0.

CHILD_NUMBER PARSE_CALLS EXECUTIONS FIRST_LOAD_TIME      LAST_LOAD_TIME       LAST_ACTI
------------ ----------- ---------- -------------------- -------------------- ---------
           0          37         37 2023-10-31/10:56:41  2023-10-31/10:56:41  31-OCT-23
           1           2          2 2023-10-31/10:56:41  2023-10-31/16:19:28  31-OCT-23
           2           2          2 2023-10-31/10:56:41  2023-10-31/16:20:30  31-OCT-23
           3           2          2 2023-10-31/10:56:41  2023-10-31/16:21:32  31-OCT-23
           4           2          2 2023-10-31/10:56:41  2023-10-31/16:22:34  31-OCT-23
           5           2          2 2023-10-31/10:56:41  2023-10-31/16:23:37  31-OCT-23
           6           2          2 2023-10-31/10:56:41  2023-10-31/16:24:39  31-OCT-23
           7           2          2 2023-10-31/10:56:41  2023-10-31/16:25:41  31-OCT-23
           8           2          2 2023-10-31/10:56:41  2023-10-31/16:26:44  31-OCT-23
           9           2          2 2023-10-31/10:56:41  2023-10-31/16:27:48  31-OCT-23
          10           2          2 2023-10-31/10:56:41  2023-10-31/16:28:51  31-OCT-23
          11           2          2 2023-10-31/10:56:41  2023-10-31/16:29:54  31-OCT-23

Solution:

  • Make sure that the statistics are gathered in equal interval and not too frequently for the objects.
  • Set _optimizer_invalidation_period parameter to a value which suits the data load period of the database.
  • Another workaround can be setting _cursor_obsolete_threshold to lower value to forcefully obsolete the child cursors in the database after every new child spawn.
kish@x3z6zx9<^>set lines 200 pages 1000
col "Hidden_parameter" for a40
col "It's Value" for a20
col Desc for a40
select x.ksppinm as Hidden_parameter,
         y.ksppstvl "It's Value",
                   x.ksppdesc "Desc"
     from
  x$ksppi x
  inner join x$ksppcv y on (x.indx = y.indx)
and
  x.ksppinm like '%_cursor_obsolete_threshold%'
order by x.ksppinm;kish@x3z6zx9<^>kish@x3z6zx9<^>kish@x3z6zx9<^>kish@x3z6zx9<^>  2    3    4    5    6    7    8    9

HIDDEN_PARAMETER                         It's Value           Desc
---------------------------------------- -------------------- ----------------------------------------
_cursor_obsolete_threshold               1024                 Number of cursors per parent before obso
                                                              letion.
--Default value of _cursor_obsolete_threshold per versions
11.2.0.3 :=100
11.2.0.4 :=1024
12.1.0.1 :=1024
12.1.0.2 :=1024
12.2.0.1 :=8192
18c :=8192
19c :=8192
21c :=8192

Setting this parameter to lower value may be obsoleted from shared pool which is the remaining 1024 – 200 = 824 cursors which were child versions of the parent stats version for ytbl.

kish@x3z6zx9<^>ALTER system set "_cursor_obsolete_threshold"=200 scope=spfile;

System altered.

What Is This PARSE ERROR: ospid=31513, error=936 for statement:?

For every 100 parse errors in the database, an entry is recorded in the alertlog with “PARSE ERROR: ospid=<nnnnn>, error=<nnn> for statement: ” format.

Simulate the error by forcing syntax error with 10000 loops. For every 100 errors consolidated, 10000 / 100 = 100 entries are recorded in alertlog.

[oracle@xhydra trace]$ cat ~/select.sh
#!/bin/bash -x

export ORACLE_SID=sqldb
export ORACLE_HOME=/u01/app/oracle/product/19.0.0/dbhome_1

c=0
while [ $c -lt 10000 ];
do
$ORACLE_HOME/bin/sqlplus -S '/ as sysdba' <<EOF
whenever sqlerror continue;
select count(*)* from dspm;
exit;
EOF
c=`expr $c + 1`
done

The entry contains the error message which can point to cause of the issue including the sql text with sql id.

It also provide the application information with the username and action etc..

[oracle@xhydra trace]$ tail -100f alert_sqldb.log |grep -A5 'PARSE ERROR'
PARSE ERROR: ospid=30863, error=936 for statement:
2023-10-30T21:28:31.006154+05:30
select count(*)* from dspm
Additional information: hd=0x79bfa4f8 phd=0x79bfa920 flg=0x28 cisid=0 sid=0 ciuid=0 uid=0 sqlid=bg9pxaf3r8akn
...Current username=SYS
...Application: sqlplus@xhydra (TNS V1-V3) Action:
--
PARSE ERROR: ospid=31513, error=936 for statement:
2023-10-30T21:30:40.623706+05:30
select count(*)* from dspm
Additional information: hd=0x79bfa4f8 phd=0x79bfa920 flg=0x28 cisid=0 sid=0 ciuid=0 uid=0 sqlid=bg9pxaf3r8akn
...Current username=SYS
...Application: sqlplus@xhydra (TNS V1-V3) Action:
--
PARSE ERROR: ospid=32079, error=936 for statement:
2023-10-30T21:32:28.160547+05:30
select count(*)* from dspm
Additional information: hd=0x79bfa4f8 phd=0x79bfa920 flg=0x28 cisid=0 sid=0 ciuid=0 uid=0 sqlid=bg9pxaf3r8akn
...Current username=SYS
...Application: sqlplus@xhydra (TNS V1-V3) Action:
--
PARSE ERROR: ospid=32663, error=936 for statement:
2023-10-30T21:34:18.773368+05:30
select count(*)* from dspm
Additional information: hd=0x79bfa4f8 phd=0x79bfa920 flg=0x28 cisid=0 sid=0 ciuid=0 uid=0 sqlid=bg9pxaf3r8akn
...Current username=SYS
...Application: sqlplus@xhydra (TNS V1-V3) Action:
--
PARSE ERROR: ospid=33248, error=936 for statement:
2023-10-30T21:36:08.751102+05:30
select count(*)* from dspm
Additional information: hd=0x79bfa4f8 phd=0x79bfa920 flg=0x28 cisid=0 sid=0 ciuid=0 uid=0 sqlid=bg9pxaf3r8akn
...Current username=SYS
...Application: sqlplus@xhydra (TNS V1-V3) Action:
--
PARSE ERROR: ospid=33754, error=936 for statement:
2023-10-30T21:37:59.365650+05:30
select count(*)* from dspm
Additional information: hd=0x79bfa4f8 phd=0x79bfa920 flg=0x28 cisid=0 sid=0 ciuid=0 uid=0 sqlid=bg9pxaf3r8akn
...Current username=SYS
...Application: sqlplus@xhydra (TNS V1-V3) Action:
--
PARSE ERROR: ospid=34305, error=936 for statement:
2023-10-30T21:39:44.152553+05:30
select count(*)* from dspm
Additional information: hd=0x79bfa4f8 phd=0x79bfa920 flg=0x28 cisid=0 sid=0 ciuid=0 uid=0 sqlid=bg9pxaf3r8akn
...Current username=SYS
...Application: sqlplus@xhydra (TNS V1-V3) Action:
--
PARSE ERROR: ospid=34877, error=936 for statement:
2023-10-30T21:41:28.786950+05:30
select count(*)* from dspm
Additional information: hd=0x79bfa4f8 phd=0x79bfa920 flg=0x28 cisid=0 sid=0 ciuid=0 uid=0 sqlid=bg9pxaf3r8akn
...Current username=SYS
...Application: sqlplus@xhydra (TNS V1-V3) Action:
--
PARSE ERROR: ospid=35437, error=936 for statement:
2023-10-30T21:43:12.664262+05:30
select count(*)* from dspm
Additional information: hd=0x79bfa4f8 phd=0x79bfa920 flg=0x28 cisid=0 sid=0 ciuid=0 uid=0 sqlid=bg9pxaf3r8akn
...Current username=SYS
...Application: sqlplus@xhydra (TNS V1-V3) Action:

In AWR report, we notice high “connection management call elapsed time” and also “failed parse elapsed time” with less significant value. Whenever, parse errors happen in the database, then these symptoms always show in AWR report.

There are also high parse count failures out of total parse count which is not good.

Also, if the parse failures are significant, then instance efficiency ratio drop for Execute to parse and Parse CPU

Solution:

  1. There is no action that can be taken from DBA rather to inform application team to fix the code with correct syntax or permissions on the object depending on the type of error.
[oracle@xhydra trace]$ oerr ora 936
00936, 00000, "missing expression"
// *Cause:
// *Action:

2. Error stack should help

<error barrier> at 0x7ffee3f36a30 placed dbkda.c@296
ORA-00936: missing expression
<error barrier> at 0x7ffee3f39af0 placed prsde.c@1119
----- SQL Statement (None) -----
Current SQL information unavailable - no cursor.

----- Call Stack Trace -----
calling              call     entry                argument values in hex
location             type     point                (? means dubious value)
-------------------- -------- -------------------- ----------------------------
ksedst1()+95         call     kgdsdst()            7FFEE3F35E90 000000002
                                                   7FFEE3F301C0 ? 7FFEE3F302D8 ?
                                                   000000000 000000082 ?
ksedst()+58          call     ksedst1()            000000000 000000001
                                                   7FFEE3F301C0 ? 7FFEE3F302D8 ?
                                                   000000000 ? 000000082 ?
dbkedDefDump()+2308  call     ksedst()             000000000 000000001 ?
0                                                  7FFEE3F301C0 ? 7FFEE3F302D8 ?
                                                   000000000 ? 000000082 ?
ksedmp()+577         call     dbkedDefDump()       00000000C 000000000
                                                   7FFEE3F301C0 ? 7FFEE3F302D8 ?
                                                   000000000 ? 000000082 ?
dbkdaKsdActDriver()  call     ksedmp()             00000000C 000000000 ?
+2484                                              7FFEE3F301C0 ? 7FFEE3F302D8 ?
                                                   000000000 ? 000000082 ?
dbgdaExecuteAction(  call     dbkdaKsdActDriver()  7F67548AF6D0 7FFEE3F38320
)+354                                              7FFEE3F301C0 ? 7FFEE3F302D8 ?
                                                   000000000 ? 000000082 ?
dbgdaRunAction()+76  call     dbgdaExecuteAction(  7F67548AF6D0 0140B5E00
2                             )                    04EC1CBB0 7FFEE3F38320
                                                   000000001 000000082 ?
dbgdRunActions()+83  call     dbgdaRunAction()     7F67548AF6D0 7FFEE3F385A0
                                                   7F67548AF6D0 000000000
                                                   7FFEE3F385A8 000000082 ?
dbgdProcessEventAct  call     dbgdRunActions()     7F67548AF6D0 ? 7FFEE3F385A0 ?

========== FRAME [17] (qcpiapr()+1615 -> kgesecl0()) ==========
defined by frame pointers 0x7ffee3f39410  and 0x7ffee3f39230
CALL TYPE: call   ERROR SIGNALED: yes   COMPONENT: (null)

There is a hidden parameter “_kks_parse_error_warning” which has a default value of 100 threshold for which the number of times that the warning message should print in alertlog. If this value is increased, then oracle does not print the message too frequently. But, this may also hide parse failures which is very important for the DBA to troubleshoot any performance problems of parsing issues.

SQL> set lines 200 pages 1000
col “Hidden_parameter” for a40
col “It’s Value” for a20
col Desc for a40
select x.ksppinm as Hidden_parameter,
y.ksppstvl “It’s Value”,
x.ksppdesc “Desc”
from
x$ksppi x
inner join x$ksppcv y on (x.indx = y.indx)
and
x.ksppinm like ‘%kks%’
order by x.ksppinm;SQL> SQL> SQL> SQL> 2 3 4 5 6 7 8 9

HIDDEN_PARAMETER It’s Value Desc
—————————————- ——————– —————————————-
_kks_cached_parse_errors 0 KKS cached parse errors
_kks_obsolete_dump_threshold 1 Number of parent cursor obsoletions befo
re dumping cursor

_kks_parse_error_warning 100 Parse error warning

The failed parse time can be queried from time model statistics tables.

SQL> SELECT stat_name,value from v$sys_time_model where stat_name like '%fail%';

STAT_NAME                                                             VALUE
---------------------------------------------------------------- ----------
failed parse elapsed time                                          89025886
failed parse (out of shared memory) elapsed time                          0

SQL> SELECT stat_name,sum(value) from dba_hist_sys_time_model where stat_name like '%fail%' group by stat_name;

STAT_NAME                                                        SUM(VALUE)
---------------------------------------------------------------- ----------
failed parse (out of shared memory) elapsed time                          0
failed parse elapsed time                                            646813

Alternatively, 10035 trace can also help to identify the parse failures.

SQL> ALTER system set events '10035 trace name context forever,level 12';

System altered.

Summary:

  • Although these parse errors looks harmless, these errors can be ignored if it is less in numbers
  • If the parse errors are significant, then this indicates a potential performance problem of unnecessary parsing which lead to shared pool processing
  • These sessions can be killed after confirmation from application team because of useless parses
SQL QUERY TO FIND USERS AND OBJECTS WHICH GENERATE MORE ARCHIVES ORACLE

set lines 200 pages 1000
col OBJECT_NAME for a30
col OWNER for a10
def arccol="do.OWNER,dhse.OBJ#,do.OBJECT_NAME,to_char(al.COMPLETION_TIME,'DD-MM-YY HH24:MI') ARCTIME,(sum(BLOCKS*BLOCK_SIZE)/1073741824) ARCSIZE_GB"
def arccol2="count(*) ARCOUNT,((sum(BLOCKS*BLOCK_SIZE)/1073741824)/(select value/1073741824 from v$parameter where name='db_recovery_file_dest_size')) ARCPCT"
def arcview="v$archived_log al"
def arcgrp="group by do.OWNER,dhse.OBJ#,do.OBJECT_NAME,to_char(al.COMPLETION_TIME,'DD-MM-YY HH24:MI')"
def arcord="order by ARCOUNT desc"
def snap="inner join dba_hist_snapshot dhss on to_char(al.COMPLETION_TIME,'DD-MM-YY HH24') = to_char(dhss.BEGIN_INTERVAL_TIME,'DD-MM-YY HH24')"
def seg="inner join dba_hist_seg_stat dhse on dhse.SNAP_ID = dhss.SNAP_ID"
def obj="inner join dba_objects do on do.OBJECT_ID = dhse.OBJ#"
SELECT &arccol,&arccol2 from
           &arcview
           &snap
           &seg
           &obj
           &arcgrp
           &arcord
/

OWNER            OBJ# OBJECT_NAME                    ARCTIME        ARCSIZE_GB    ARCOUNT     ARCPCT
---------- ---------- ------------------------------ -------------- ---------- ---------- ----------
SYS             11358 WRH$_CON_SYSMETRIC_SUMMARY     20-10-23 12:20  .06503582          2 .005230653
SYS             73576 WRH$_SYSSTAT                   20-10-23 12:20  .06503582          2 .005230653
SYS                37 I_OBJ2                         24-10-23 11:25 .197018623          2  .01584567
SYS                65 I_OBJ#_INTCOL#                 24-10-23 11:25 .197018623          2  .01584567
SYS                68 HIST_HEAD$                     24-10-23 11:25 .197018623          2  .01584567
SYS                18 OBJ$                           27-10-23 18:14 .161505699          2 .012989462
SLOW SQL QUERY DUE TO FIXED BASELINE ORACLE

There was a customer who had a performance issue for a batch query which was executing as per expected timelines earlier and now it take more than half of previous time.

After investigating the problem, the query picked up the fixed baseline plan which was not suitable for all data sets as the query had bind variables in it which fetched variable results.

Enable auto capture baselines for all the sql. Warning! this may capture millions of baseline if multiple queries are executed in database which may exhaust sysaux space.

This is just a sample test case query for understanding purpose.

Execute the query for the first time with out creating any index on the where clause.

The query execute with a full table scan and also the execution plan is captured for the query due to auto capture baseline.

SQL> ALTER system set optimizer_capture_sql_plan_baselines=TRUE;

System altered.

SQL> set autot traceonly
SQL> SELECT name,type from dspm where type='PROCEDURE' and owner='MDSYS';

45 rows selected.


Execution Plan
----------------------------------------------------------
Plan hash value: 3837617297

--------------------------------------------------------------------------
| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |      |  2515 | 75450 |  1570   (1)| 00:00:01 |
|*  1 |  TABLE ACCESS FULL| DSPM |  2515 | 75450 |  1570   (1)| 00:00:01 |
--------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   1 - filter("TYPE"='PROCEDURE' AND "OWNER"='MDSYS')

Note
-----
   - SQL plan baseline "SQL_PLAN_74gw55r480awsb495c64e" used for this statement

Check if the plan is accepted as a benchmark plan. The plan is accepted but not fixed.

SQL> col SQL_HANDLE for a20
SQL> col PLAN_NAME for a20
SQL> SELECT sql_handle, sql_text, plan_name, enabled,accepted,fixed FROM dba_sql_plan_baselines WHERE plan_name='SQL_PLAN_74gw55r480awsb495c64e';

SQL_HANDLE           SQL_TEXT             PLAN_NAME            ENA ACC FIX
-------------------- -------------------- -------------------- --- --- ---
SQL_723f852dc8802b98 SELECT name,type fro SQL_PLAN_74gw55r480a YES YES NO
                     m dspm where type='P wsb495c64e
                     ROCEDURE' and owner=
                     'MDSYS'

Accidentally, the full table scan plan is fixed considering that the plan performs well at the present.

SQL> var v_5cygq95qjwmzr_ft number
SQL> EXEC :v_5cygq95qjwmzr_ft := DBMS_SPM.ALTER_SQL_PLAN_BASELINE ( sql_handle => 'SQL_723f852dc8802b98', plan_name => 'SQL_PLAN_74gw55r480awsb495c64e', attribute_name => 'FIXED', attribute_value => 'YES' );

PL/SQL procedure successfully completed.

Now, application team expects a better performance for the query and creates index on one specific column ‘type’. Again the same fixed plan is used, even though a better index plan is available.

SQL> CREATE index dtype on dspm(type);

Index created.

SQL> set autot traceonly
SQL> SELECT name,type from dspm where type='PROCEDURE' and owner='MDSYS';

45 rows selected.


Execution Plan
----------------------------------------------------------
Plan hash value: 3837617297

--------------------------------------------------------------------------
| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |      |  2515 | 75450 |  1570   (1)| 00:00:01 |
|*  1 |  TABLE ACCESS FULL| DSPM |  2515 | 75450 |  1570   (1)| 00:00:01 |
--------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   1 - filter("TYPE"='PROCEDURE' AND "OWNER"='MDSYS')

Note
-----
   - SQL plan baseline "SQL_PLAN_74gw55r480awsb495c64e" used for this statement

Again, application team creates another index on ‘owner’ column. This time again the fixed full table scan is used due to baseline.

SQL> CREATE index downer on dspm(owner);

Index created.

SQL> set autot traceonly
SQL> SELECT name,type from dspm where type='PROCEDURE' and owner='MDSYS';

45 rows selected.


Execution Plan
----------------------------------------------------------
Plan hash value: 3837617297

--------------------------------------------------------------------------
| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |      |  2515 | 75450 |  1570   (1)| 00:00:01 |
|*  1 |  TABLE ACCESS FULL| DSPM |  2515 | 75450 |  1570   (1)| 00:00:01 |
--------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   1 - filter("TYPE"='PROCEDURE' AND "OWNER"='MDSYS')

Note
-----
   - SQL plan baseline "SQL_PLAN_74gw55r480awsb495c64e" used for this statement

So, the above test case is just for learning purpose.

In reality, the same case may be suitable, where sql tuning advisor would have recommended to accept full table scan baseline but not to fix it. DBA might have faced performance issue during the time with a worse plan than full table scan plan and he might have fixed the fts plan considering it fast.

Consider that the DBA left the job and another new DBA comes in. After some days, there may be change on the size of data to be retrieved like more rows for the sql. At that time, optimizer still use the fts plan because of fixed baseline and another performance issue arise as a consequence of previous fix.

Summary:

  • Always make sure of the existing sql profiles and baselines for the sql
  • Make sure of the status of those baselines if they are enabled or accepted or fixed or all of them together
  • If so, drop the unnecessary bad baselines created on older plans which may not be suitable currently

First identify the number of baselines available for the sql id.

SQL> set lines 200 pages 1000
SQL> col PLAN_NAME for a20
SQL> col SQL_TEXT for a20
SQL> SELECT SQL_TEXT,SIGNATURE,SQL_HANDLE,PLAN_NAME,ENABLED,ACCEPTED,FIXED,ELAPSED_TIME from dba_sql_plan_baselines WHERE SQL_TEXT like '%SELECT name,type from dspm where type%';

SQL_TEXT              SIGNATURE SQL_HANDLE                     PLAN_NAME            ENA ACC FIX ELAPSED_TIME
-------------------- ---------- ------------------------------ -------------------- --- --- --- ------------
SELECT name,type fro 8.2324E+18 SQL_723f852dc8802b98           SQL_PLAN_74gw55r480a YES YES YES            0
m dspm where type='P                                           wsb495c64e
ROCEDURE' and owner=
'MDSYS'

One baseline is available for the SQL and it is fixed for the query. This is the reason why a fixed plan is used irrespective of other good plans.

Check the contents of the baseline for the plan.

SQL> SELECT * from table(DBMS_XPLAN.DISPLAY_SQL_PLAN_BASELINE(PLAN_NAME => 'SQL_PLAN_74gw55r480awsb495c64e'));

PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

--------------------------------------------------------------------------------
SQL handle: SQL_723f852dc8802b98
SQL text: SELECT name,type from dspm where type='PROCEDURE' and owner='MDSYS'
--------------------------------------------------------------------------------

--------------------------------------------------------------------------------
Plan name: SQL_PLAN_74gw55r480awsb495c64e         Plan id: 3029714510
Enabled: YES     Fixed: YES     Accepted: YES     Origin: AUTO-CAPTURE
Plan rows: From dictionary
--------------------------------------------------------------------------------

Plan hash value: 3837617297

--------------------------------------------------------------------------
| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |      |  2515 | 75450 |  1570   (1)| 00:00:01 |
|*  1 |  TABLE ACCESS FULL| DSPM |  2515 | 75450 |  1570   (1)| 00:00:01 |
--------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   1 - filter("TYPE"='PROCEDURE' AND "OWNER"='MDSYS')

25 rows selected.

Drop the baseline containing the worst plan and purge the sql_id from the shared pool.

SQL> DECLARE
varint INTEGER;
BEGIN
varint := DBMS_SPM.drop_sql_plan_baseline(plan_name => 'SQL_PLAN_74gw55r480awsb495c64e');
END;
/    2    3    4    5    6

PL/SQL procedure successfully completed.

SQL> SELECT address,hash_value from v$sql where sql_id='3bjw18gb6jthj';

ADDRESS          HASH_VALUE
---------------- ----------
0000000076701840 3597198865

SQL> EXEC dbms_shared_pool.purge('0000000076701840,3597198865','C');

PL/SQL procedure successfully completed.

SQL> SELECT address,hash_value from v$sql where sql_id='3bjw18gb6jthj';

no rows selected

After the baseline with worst plan is dropped, good plan is used.

SQL> set autot traceonly
SQL> SELECT name,type from dspm where type='PROCEDURE' and owner='MDSYS';

45 rows selected.


Execution Plan
----------------------------------------------------------
Plan hash value: 2382681726

---------------------------------------------------------------------------------------------
| Id  | Operation                           | Name  | Rows  | Bytes | Cost (%CPU)| Time     |
---------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT                    |       |  2515 | 75450 |   405   (0)| 00:00:01 |
|*  1 |  TABLE ACCESS BY INDEX ROWID BATCHED| DSPM  |  2515 | 75450 |   405   (0)| 00:00:01 |
|*  2 |   INDEX RANGE SCAN                  | DTYPE | 15536 |       |    44   (0)| 00:00:01 |
---------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   1 - filter("OWNER"='MDSYS')
   2 - access("TYPE"='PROCEDURE')

Note
-----
   - SQL plan baseline "SQL_PLAN_74gw55r480aws87226bf8" used for this statement

Summary:

  • It is always good to verify that if there are any fixed baseline plans for a query during performance issue and also examine the history
  • Do not fix the baseline plan unless until the data for the objects are used only for archival purpose which means that the table data is stable for long time and there is no data load or growth.
  • Fix the baseline only if the data is constant.
  • If the data is dynamic, then consider only accepting the good plan.
SQL ID IS NOT CAPTURED IN V$SQL OR V$SQLAREA

I was trying to identify SQL ID for a microsecond query from v$sql, v$session, v$sqlarea etc.. But none of them retained the information of the sql because of ultra fast execution of the sql.

There may be other parsing reasons of the sql when specifying the sql text in WHERE clause. If the sql text is provided in WHERE clause with either upper or lower case or with additional spaces, then the sql may not be properly retrieved due to syntax variations. But here, this is not the case.

v$SQL displays the sql query details at the end of query execution generally as per oracle doc.

But if the query executes in fraction of milliseconds, then the details are not visible in v$sql or v$sqlarea.

So, alternatively v$open_cursor captures the query details immediately after query execution and it disappears too in a while. None of the AWR tables shows the details about this fast query.

SQL> SELECT sql_id,sql_text FROM v$open_cursor WHERE sql_id='5cygq95qjwmzr';

SQL_ID        SQL_TEXT
------------- --------------------
5cygq95qjwmzr SELECT name,type fro
              m dspm where type='P
              ROCEDURE' and owner=

SQL> SELECT sql_id from v$session where sql_id IS NOT NULL;

SQL_ID
-------------
30fux3fx84xuu

SQL> SELECT sql_text from v$sql where sql_id='30fux3fx84xuu';

SQL_TEXT
--------------------------------------------------------------------------------
SELECT sql_id from v$session where sql_id IS NOT NULL

SQL> SELECT sql_id FROM v$active_session_history WHERE sql_id='5cygq95qjwmzr';

no rows selected
SQL>  SELECT sql_id from dba_hist_sqlstat WHERE PLAN_HASH_VALUE=3837617297;

no rows selected

SQL> SELECT sql_id from dba_hist_active_sess_history where SQL_PLAN_HASH_VALUE=3837617297;

no rows selected

The sql details were kept in v$sqlstats even though the query completed faster.

SQL> col SQL_TEXT for a20
SQL> SELECT sql_id,sql_text FROM v$sqlstats WHERE sql_text like '%SELECT name,type from dspm where type=%';

SQL_ID        SQL_TEXT
------------- --------------------
5cygq95qjwmzr SELECT name,type fro
              m dspm where type='P
              ROCEDURE' and owner=
              'MDSYS'

Also, another way to identify the sql id is to use 10046 trace if nothing works.

PARSING IN CURSOR #139655058600344 len=67 dep=0 uid=0 oct=3 lid=0 tim=3227964751 hv=1830703095 ad='7f481648' sqlid='5cygq95qjwmzr'
SELECT name,type from dspm where type='PROCEDURE' and owner='MDSYS'
END OF STMT
HOW TO PRINT Nth LINE FROM A FILE IN SHELL SCRIPT

I was asked this question in an interview for testing pattern matching skills in shell script. Though, the question looked easy but still it was really difficult to think of logic immediately and it took some time. Also the difficult question was “How to filter the 10 row without using head or tail”

Create a sample file, populate with numbers and cat the contents

[oracle@hydrupgrd ~]$ touch abc.txt
[oracle@hydrupgrd ~]$ echo -ne "1\n2\n3\n4\n5\n6\n" > abc.txt
[oracle@hydrupgrd ~]$ cat abc.txt
1
2
3
4
5
6

head and tail are the easiest combination to filter the Nth row in the file
[oracle@hydrupgrd ~]$ cat abc.txt|head -3|tail -1
3

Another method is to use AWK to filter the exact line

[oracle@hydrupgrd ~]$ cat abc.txt |awk 'NR==3'
3

SED can also be used to filter complex logics.

[oracle@hydrupgrd ~]$ cat abc.txt |sed -n '3p'
3
MEMORY, SGA,PGA,AMM,ASMM,MMM IN ORACLE

Before configuration of SGA or PGA or Memory in the database, it is very important to configure the kernel parameters optimally to hold the database memory from OS.

[oracle@xhydra ~]$ cat /etc/sysctl.conf |egrep 'fs.|net.|kernel.'|grep -v '#'
fs.file-max = 6815744
kernel.sem = 250 32000 100 128
kernel.shmmni = 4096
kernel.shmall = 1073741824
kernel.shmmax = 4398046511104
kernel.panic_on_oops = 1
net.core.rmem_default = 262144
net.core.rmem_max = 4194304
net.core.wmem_default = 262144
net.core.wmem_max = 1048576
net.ipv4.conf.all.rp_filter = 2
net.ipv4.conf.default.rp_filter = 2
fs.aio-max-nr = 1048576
net.ipv4.ip_local_port_range = 9000 65500

kernel.shmall and kernel.shmmax are crucial for SGA allocation

Learning 1:

How to calculate the sga and pga size as per the current workload in the database ?

Formula is to to find the difference between total sga allocated and the current sga. This is the target value for sga(sga_target) as per usage and not the max value (sga_max_size)

SQL> WITH sga as (SELECT sum(value) tot_sga from v$sga),sga_d_c as (SELECT current_size cur_sga from v$sga_dynamic_free_memory)
SELECT (TOT_SGA - CUR_SGA)/1048576 sga_target_mb FROM sga,sga_d_c;

SGA_TARGET_MB
-------------
          260

Similarly, calculate the pga target with the formula,

Maximum value out of max value allocated for pga in the instance currently and the value of pga_aggregate_target parameter.

SQL> WITH max_pga as (SELECT value/1048576 MB from v$pgastat where name='maximum PGA allocated'), pga_agg_target as (SELECT value/1048576 PMB from v$parameter where name='pga_aggregate_target')
  2   SELECT MB,PMB,greatest(MB,PMB) PGA_AGGREGATE_TARGET FROM max_pga,pga_agg_target;

        MB        PMB PGA_AGGREGATE_TARGET
---------- ---------- --------------------
348.155273         52           348.155273

Now let us combine both the values in a single query to get sga and pga target values respectively.

SQL> WITH sga as (SELECT sum(value) tot_sga from v$sga),sga_d_c as (SELECT current_size cur_sga from v$sga_dynamic_free_memory),max_pga as (SELECT value/1048576 MB from v$pgastat where name='maximum PGA allocated'), pga_agg_target as (SELECT value/1048576 PMB from v$parameter where name='pga_aggregate_target')
    SELECT (TOT_SGA - CUR_SGA)/1048576 sga_target_mb,MB,PMB,greatest(MB,PMB) pga_aggregate_target_mb FROM sga,sga_d_c,max_pga,pga_agg_target;

SGA_TARGET_MB         MB        PMB PGA_AGGREGATE_TARGET_MB
------------- ---------- ---------- -----------------------
          260 348.155273         52              348.155273

To enable AMM, we need to find out the optimal value for memory_target parameter. For setting memory_target, the value of memory_max_target parameter should be figured out. This query can give the target size for every memory component as per current usage.

SQL> WITH sga as (SELECT sum(value) tot_sga from v$sga),sga_d_c as (SELECT current_size cur_sga from v$sga_dynamic_free_memory),max_pga as (SELECT value/1048576 MB from v$pgastat where name='maximum PGA allocated'), pga_agg_target as (SELECT value/1048576 PMB from v$parameter where name='pga_aggregate_target')
  2  SELECT (TOT_SGA - CUR_SGA)/1048576 sga_target_mb,MB,PMB,greatest(MB,PMB) pga_aggregate_target_mb,((TOT_SGA - CUR_SGA)/1048576 + greatest(MB,PMB)) memory_max_target_mb FROM sga,sga_d_c,max_pga,pga_agg_target;

SGA_TARGET_MB         MB        PMB PGA_AGGREGATE_TARGET_MB MEMORY_MAX_TARGET_MB
------------- ---------- ---------- ----------------------- --------------------
          260 348.155273         52              348.155273           608.155273

To derive the outliers, minimum and maximum value from the historical statistics based on time, deeper analysis is required to know the peak time of the database.


set lines 200 pages 1000
col startup_time for a20
WITH sga as (SELECT sum(s.value) tot_sga from dba_hist_sga s group by s.snap_id),sga_d_c as (SELECT d.current_size cur_sga from dba_hist_mem_dynamic_comp d),
max_pga as (SELECT p.value/1048576 MB from dba_hist_pgastat p where p.name='maximum PGA allocated'), 
pga_agg_target as (SELECT pr.value/1048576 PMB from dba_hist_parameter pr where pr.parameter_name='pga_aggregate_target')
    SELECT startup_time,
	      (TOT_SGA - CUR_SGA)/1048576 sga_target_mb,
		  MB,
		  PMB,
		  greatest(MB,PMB) pga_aggregate_target_mb 
	FROM sga,
	     sga_d_c,
	     max_pga,
	     pga_agg_target,
	     dba_hist_snapshot;

STARTUP_TIME         SGA_TARGET_MB         MB        PMB PGA_AGGREGATE_TARGET_MB
-------------------- ------------- ---------- ---------- -----------------------
20-OCT-23 12.20.32.0    1999.99861 297.851563        368                     368
00 PM

20-OCT-23 12.20.32.0    1999.99861 297.851563        368                     368
00 PM

20-OCT-23 12.20.32.0    1999.99861 297.851563        368                     368
00 PM

Statistics can also unleash the hidden trends in the size of the memory areas allocation dynamically over the historical period.

SQL> set lines 200 pages 1000
col startup_time for a20
WITH sga as (SELECT sum(s.value) tot_sga from dba_hist_sga s group by s.snap_id),sga_d_c as (SELECT d.current_size cur_sga from dba_hist_mem_dynamic_comp d),
max_pga as (SELECT p.value/1048576 MB from dba_hist_pgastat p where p.name='maximum PGA allocated'),
pga_agg_target as (SELECT pr.value/1048576 PMB from dba_hist_parameter pr where pr.parameter_name='pga_aggregate_target')
    SELECT
              avg((TOT_SGA - CUR_SGA)/1048576) ASTMB,
                  avg(MB) AMPMB,
                  avg(PMB) APATMB,
                  avg(greatest(MB,PMB)) APATNMB,
                  median((TOT_SGA - CUR_SGA)/1048576) MSTMB,
                  median(MB) MMPMB,
                  median(PMB) MPATMB,
                  median(greatest(MB,PMB)) MPATNMB,
                  stats_mode((TOT_SGA - CUR_SGA)/1048576) SMSTMB,
                  stats_mode(MB) SMMPMB,
                  stats_mode(PMB) SMPATMB,
                  stats_mode(greatest(MB,PMB)) SMPATNMB
        FROM sga,
             sga_d_c,
                 max_pga,
                 pga_agg_target;SQL> SQL>   2    3    4    5    6    7    8    9   10   11   12   13   14   15   16   17   18   19   20

     ASTMB      AMPMB     APATMB    APATNMB      MSTMB      MMPMB     MPATMB    MPATNMB     SMSTMB     SMMPMB    SMPATMB   SMPATNMB
---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ----------
1832.31505 339.319824       99.5 350.250244 1999.99629 315.630859         10 319.322266 1999.99629 297.851563         10 428.166016

The above output shows that the frequently used values are,

sga_target= 2GB and pga_aggregate_target=10 and max pga allocated = 298 MB and max pga value for pga_aggregate_target=428MB

SQL> ALTER system set SGA_TARGET=260M scope=spfile;

System altered.


SQL> alter system set memory_max_target=608M scope=spfile;

System altered.
SQL> startup force;
ORACLE instance started.

Total System Global Area  637534208 bytes
Fixed Size                  2927624 bytes
Variable Size             478151672 bytes
Database Buffers          150994944 bytes
Redo Buffers                5459968 bytes
Database mounted.
Database opened.

SQL> show parameter memory%_target

NAME                                 TYPE        VALUE
------------------------------------ ----------- ------------------------------
memory_max_target                    big integer 608M
memory_target                        big integer 0

SQL> show parameter pga%_target

NAME                                 TYPE        VALUE
------------------------------------ ----------- ------------------------------
pga_aggregate_target                 big integer 52M
SQL> show parameter sga%_target

NAME                                 TYPE        VALUE
------------------------------------ ----------- ------------------------------
sga_target                           big integer 260M

SQL> alter system set memory_target=608M;

System altered.

Learning 2:

SQL> show parameter shared_pool

NAME                                 TYPE        VALUE
------------------------------------ ----------- ------------------------------
shared_pool_reserved_size            big integer 25M
shared_pool_size                     big integer 500M
SQL> show parameter large_pool

NAME                                 TYPE        VALUE
------------------------------------ ----------- ------------------------------
large_pool_size                      big integer 76M
SQL> show parameter db_cache

NAME                                 TYPE        VALUE
------------------------------------ ----------- ------------------------------
db_cache_advice                      string      ON
db_cache_size                        big integer 600M

SQL> show parameter sga_target

NAME                                 TYPE        VALUE
------------------------------------ ----------- ------------------------------
sga_target                           big integer 0

SQL> alter system set sga_target=1800m;

System altered.

SQL> startup mount;
ORA-00093: _shared_pool_reserved_min_alloc must be between 4000 and 0
ORA-01078: failure in processing system parameters

Configure AMM (memory_target and memory_max_target ):

To configure AMM, configure memory_target and memory_max_target to a non-zero value. memory_max_target is a static parameter which determines the maximum size of memory that can be allocated and used in the database. It has default value of 0.

memory_target is the minimum size usable for both SGA and PGA combined and this parameter cannot be set unless memory_max_target is set. This parameter is dynamic, can be modified during run time and does not need a restart of database. Value of memory_target should be less than or equal to memory_max_target.

SQL> alter system set memory_target=608M;
alter system set memory_target=608M
*
ERROR at line 1:
ORA-02097: parameter cannot be modified because specified value is invalid
ORA-00837: Specified value of MEMORY_TARGET greater than MEMORY_MAX_TARGET
  • Calculate the min size of SGA and PGA with the current and historical trends with the help of queries provided above.
  • Calculate memory_target which is the minimum value for AMM by adding both min SGA and PGA calculated based on the historical usage and this is not a prediction for future usage. If more memory is available from OS, then more memory can be dedicated to instance than the calculated value. But, be cautious about resource wastage.
  • Before memory_target parameter is set, memory_max_target should be set as a hard limit for memory_target.
  • Set sga_target and pga_aggregate_target to 0. If these values are set to a non-zero value, then those values are considered as soft limit for sga and pga respectively. Oracle uses sga and pga combined together to less than or equal to memory_target as per the requirement.

SQL> show parameter memory_tar

NAME                                 TYPE        VALUE
------------------------------------ ----------- ------------------------------
memory_target                        big integer 0
SQL> show parameter memory_max

NAME                                 TYPE        VALUE
------------------------------------ ----------- ------------------------------
memory_max_target                    big integer 0

Configure ASMM(sga_target and pga_aggregate_target):

If currently in MMM, then,

  • Set sga_target to non-zero value based on scripts provided to calculate sga. Before that, sga_max_size should be specified as hard limit. sga_target should be less than or equal to sga_max_size.
  • Components inside SGA like db_cache_size, large_pool_size, shared_pool_reserved_size and shared_pool_size can or cannot be left as such as per current value. If they are left to their default values, then those values are considered as minimum starting limit for those pools. If they are resized to zero, then ASMM automatically grow or shrink the pools dynamically as per requirement. Setting these pool values to 0 can give more benefit for auto sga tuning.
  • pga_aggregate_target can also be calculated as per the formula and script provided above.

If currently in AMM, then,

  • Set memory_target to 0.
  • sga_target is automatically sized based on current value.
  • Components inside SGA like db_cache_size, large_pool_size, shared_pool_reserved_size and shared_pool_size can or cannot be left as such as per current value. If they are left to their default values, then those values are considered as minimum starting limit for those pools. If they are resized to zero, then ASMM automatically grow or shrink the pools dynamically as per requirement. Setting these pool values to 0 can give more benefit for auto sga tuning.
  • pga_aggregate_target can also be calculated as per the formula and script provided above.

ORA-14107: partition specification is required for a partitioned object – ORA-03205: partition name is required when partitioned type is specified – ORA-03200: the segment type specification is invalid

DBMS_SPACE.SPACE_USAGE package is used to detect fragmentation at table, partition level etc..

It is straightforward for table fragmentation to be detected using this package but for partition level, there should be confusion on syntax level without specifying the partitions.

ORA-14107 is triggered, if the table is partitioned and the partition name should be specified and if not, then this error is expected.

SQL> set serveroutput on
declare
v_unformatted_blocks number;
v_unformatted_bytes number;
v_fs1_blocks number;
v_fs1_bytes number;
v_fs2_blocks number;
v_fs2_bytes number;
v_fs3_blocks number;
v_fs3_bytes number;
v_fs4_blocks number;
v_fs4_bytes number;
v_full_blocks number;
v_full_bytes number;
begin
dbms_space.space_usage ('&SCHEMA_NAME', '&TABLE_NAME', 'TABLE', v_unformatted_blocks,
v_unformatted_bytes, v_fs1_blocks, v_fs1_bytes, v_fs2_blocks, v_fs2_bytes,
v_fs3_blocks, v_fs3_bytes, v_fs4_blocks, v_fs4_bytes, v_full_blocks, v_full_bytes);
dbms_output.put_line('Unformatted Blocks = '||v_unformatted_blocks);
dbms_output.put_line('FS1 Blocks = '||v_fs1_blocks);
dbms_output.put_line('FS2 Blocks = '||v_fs2_blocks);
dbms_output.put_line('FS3 Blocks = '||v_fs3_blocks);
dbms_output.put_line('FS4 Blocks = '||v_fs4_blocks);
dbms_output.put_line('Full Blocks = '||v_full_blocks);
end;
/SQL>   2    3    4    5    6    7    8    9   10   11   12   13   14   15   16   17   18   19   20   21   22   23   24   25
Enter value for schema_name: C##HYDRA
Enter value for table_name: RP
old  15: dbms_space.space_usage ('&SCHEMA_NAME', '&TABLE_NAME', 'TABLE', v_unformatted_blocks,
new  15: dbms_space.space_usage ('C##HYDRA', 'RP', 'TABLE', v_unformatted_blocks,
declare
*
ERROR at line 1:
ORA-14107: partition specification is required for a partitioned object
ORA-06512: at "SYS.DBMS_SPACE", line 214
ORA-06512: at line 15

If the segment type is not correctly specified, then ORA-03200 is thrown.

SQL> set serveroutput on
declare
v_unformatted_blocks number;
v_unformatted_bytes number;
v_fs1_blocks number;
v_fs1_bytes number;
v_fs2_blocks number;
v_fs2_bytes number;
v_fs3_blocks number;
v_fs3_bytes number;
v_fs4_blocks number;
v_fs4_bytes number;
v_full_blocks number;
v_full_bytes number;
begin
dbms_space.space_usage ('&SCHEMA_NAME', '&TABLE_NAME', 'PARTITION', v_unformatted_blocks,
v_unformatted_bytes, v_fs1_blocks, v_fs1_bytes, v_fs2_blocks, v_fs2_bytes,
v_fs3_blocks, v_fs3_bytes, v_fs4_blocks, v_fs4_bytes, v_full_blocks, v_full_bytes);
dbms_output.put_line('Unformatted Blocks = '||v_unformatted_blocks);
dbms_output.put_line('FS1 Blocks = '||v_fs1_blocks);
dbms_output.put_line('FS2 Blocks = '||v_fs2_blocks);
dbms_output.put_line('FS3 Blocks = '||v_fs3_blocks);
dbms_output.put_line('FS4 Blocks = '||v_fs4_blocks);
dbms_output.put_line('Full Blocks = '||v_full_blocks);
end;
/SQL>   2    3    4    5    6    7    8    9   10   11   12   13   14   15   16   17   18   19   20   21   22   23   24   25
Enter value for schema_name: C##HYDRA
Enter value for table_name: RP
old  15: dbms_space.space_usage ('&SCHEMA_NAME', '&TABLE_NAME', 'PARTITION', v_unformatted_blocks,
new  15: dbms_space.space_usage ('C##HYDRA', 'RP', 'PARTITION', v_unformatted_blocks,
declare
*
ERROR at line 1:
ORA-03200: the segment type specification is invalid
ORA-06512: at "SYS.DBMS_SPACE", line 214
ORA-06512: at line 15

Partition name should be specified at the last argument and if not ORA-03205 is thrown

SQL>
set serveroutput on
declare
v_unformatted_blocks number;
v_unformatted_bytes number;
v_fs1_blocks number;
v_fs1_bytes number;
v_fs2_blocks number;
v_fs2_bytes number;
v_fs3_blocks number;
v_fs3_bytes number;
v_fs4_blocks number;
v_fs4_bytes number;
v_full_blocks number;
v_full_bytes number;
begin
dbms_space.space_usage ('&SCHEMA_NAME', '&TABLE_NAME', 'TABLE PARTITION', v_unformatted_blocks,
v_unformatted_bytes, v_fs1_blocks, v_fs1_bytes, v_fs2_blocks, v_fs2_bytes,
SQL> v_fs3_blocks, v_fs3_bytes, v_fs4_blocks, v_fs4_bytes, v_full_blocks, v_full_bytes);
dbms_output.put_line('Unformatted Blocks = '||v_unformatted_blocks);
dbms_output.put_line('FS1 Blocks = '||v_fs1_blocks);
dbms_output.put_line('FS2 Blocks = '||v_fs2_blocks);
dbms_output.put_line('FS3 Blocks = '||v_fs3_blocks);
dbms_output.put_line('FS4 Blocks = '||v_fs4_blocks);
SQL>   2    3    4    5    6    7    8    9   10   11   12   13   14   15   16   17   18   19   20   21   22   23  dbms_output.put_line('Full Blocks = '||v_full_blocks);
end;
/ 24   25
Enter value for schema_name: C##HYDRA
Enter value for table_name: RP
old  15: dbms_space.space_usage ('&SCHEMA_NAME', '&TABLE_NAME', 'TABLE PARTITION', v_unformatted_blocks,
new  15: dbms_space.space_usage ('C##HYDRA', 'RP', 'TABLE PARTITION', v_unformatted_blocks,
declare
*
ERROR at line 1:
ORA-03205: partition name is required when partitioned type is specified
ORA-06512: at "SYS.DBMS_SPACE", line 214
ORA-06512: at line 15

Check the available segment types in dba_segments.

SQL> select distinct segment_type from dba_segments;

SEGMENT_TYPE
------------------
LOBINDEX
INDEX PARTITION
TABLE SUBPARTITION
ROLLBACK
TABLE PARTITION
NESTED TABLE
LOB PARTITION
LOBSEGMENT
INDEX
TABLE
TYPE2 UNDO
CLUSTER

12 rows selected.

Describe the procedure dbms_space for more information and clarity on the options available

SQL> desc dbms_space
FUNCTION ASA_RECOMMENDATIONS RETURNS ASA_RECO_ROW_TB
 Argument Name                  Type                    In/Out Default?
 ------------------------------ ----------------------- ------ --------
 ALL_RUNS                       VARCHAR2                IN     DEFAULT
 SHOW_MANUAL                    VARCHAR2                IN     DEFAULT
 SHOW_FINDINGS                  VARCHAR2                IN     DEFAULT
PROCEDURE AUTO_SPACE_ADVISOR_JOB_PROC
PROCEDURE CREATE_INDEX_COST
 Argument Name                  Type                    In/Out Default?
 ------------------------------ ----------------------- ------ --------
 DDL                            VARCHAR2                IN
 USED_BYTES                     NUMBER                  OUT
 ALLOC_BYTES                    NUMBER                  OUT
 PLAN_TABLE                     VARCHAR2                IN     DEFAULT
PROCEDURE CREATE_TABLE_COST
 Argument Name                  Type                    In/Out Default?
 ------------------------------ ----------------------- ------ --------
 TABLESPACE_NAME                VARCHAR2                IN
 AVG_ROW_SIZE                   NUMBER                  IN
 ROW_COUNT                      NUMBER                  IN
 PCT_FREE                       NUMBER                  IN
 USED_BYTES                     NUMBER                  OUT
 ALLOC_BYTES                    NUMBER                  OUT
PROCEDURE CREATE_TABLE_COST
 Argument Name                  Type                    In/Out Default?
 ------------------------------ ----------------------- ------ --------
 TABLESPACE_NAME                VARCHAR2                IN
 COLINFOS                       CREATE_TABLE_COST_COLUMNS IN
 ROW_COUNT                      NUMBER                  IN
 PCT_FREE                       NUMBER                  IN
 USED_BYTES                     NUMBER                  OUT
 ALLOC_BYTES                    NUMBER                  OUT
FUNCTION DBFS_DF RETURNS NUMBER
 Argument Name                  Type                    In/Out Default?
 ------------------------------ ----------------------- ------ --------
 USERID                         NUMBER                  IN
 NTBS                           NUMBER                  IN
 INTS_LIST                      TABLESPACE_LIST         IN
PROCEDURE FREE_BLOCKS
 Argument Name                  Type                    In/Out Default?
 ------------------------------ ----------------------- ------ --------
 SEGMENT_OWNER                  VARCHAR2                IN
 SEGMENT_NAME                   VARCHAR2                IN
 SEGMENT_TYPE                   VARCHAR2                IN
 FREELIST_GROUP_ID              NUMBER                  IN
 FREE_BLKS                      NUMBER                  OUT
 SCAN_LIMIT                     NUMBER                  IN     DEFAULT
 PARTITION_NAME                 VARCHAR2                IN     DEFAULT
PROCEDURE ISDATAFILEDROPPABLE_NAME
 Argument Name                  Type                    In/Out Default?
 ------------------------------ ----------------------- ------ --------
 FILENAME                       VARCHAR2                IN
 VALUE                          NUMBER                  OUT
FUNCTION OBJECT_DEPENDENT_SEGMENTS RETURNS DEPENDENT_SEGMENTS_TABLE
 Argument Name                  Type                    In/Out Default?
 ------------------------------ ----------------------- ------ --------
 OBJOWNER                       VARCHAR2                IN
 OBJNAME                        VARCHAR2                IN
 PARTNAME                       VARCHAR2                IN
 OBJTYPE                        NUMBER                  IN
FUNCTION OBJECT_GROWTH_TREND RETURNS OBJECT_GROWTH_TREND_TABLE
 Argument Name                  Type                    In/Out Default?
 ------------------------------ ----------------------- ------ --------
 OBJECT_OWNER                   VARCHAR2                IN
 OBJECT_NAME                    VARCHAR2                IN
 OBJECT_TYPE                    VARCHAR2                IN
 PARTITION_NAME                 VARCHAR2                IN     DEFAULT
 START_TIME                     TIMESTAMP               IN     DEFAULT
 END_TIME                       TIMESTAMP               IN     DEFAULT
 INTERVAL                       INTERVAL DAY TO SECOND  IN     DEFAULT
 SKIP_INTERPOLATED              VARCHAR2                IN     DEFAULT
 TIMEOUT_SECONDS                NUMBER                  IN     DEFAULT
 SINGLE_DATAPOINT_FLAG          VARCHAR2                IN     DEFAULT
FUNCTION OBJECT_GROWTH_TREND_CUR RETURNS REF CURSOR
 Argument Name                  Type                    In/Out Default?
 ------------------------------ ----------------------- ------ --------
 OBJECT_OWNER                   VARCHAR2                IN
 OBJECT_NAME                    VARCHAR2                IN
 OBJECT_TYPE                    VARCHAR2                IN
 PARTITION_NAME                 VARCHAR2                IN     DEFAULT
 START_TIME                     TIMESTAMP               IN     DEFAULT
 END_TIME                       TIMESTAMP               IN     DEFAULT
 INTERVAL                       INTERVAL DAY TO SECOND  IN     DEFAULT
 SKIP_INTERPOLATED              VARCHAR2                IN     DEFAULT
 TIMEOUT_SECONDS                NUMBER                  IN     DEFAULT
FUNCTION OBJECT_GROWTH_TREND_CURTAB RETURNS OBJECT_GROWTH_TREND_TABLE
FUNCTION OBJECT_GROWTH_TREND_I_TO_S RETURNS NUMBER
 Argument Name                  Type                    In/Out Default?
 ------------------------------ ----------------------- ------ --------
 INTERV                         INTERVAL DAY TO SECOND  IN
FUNCTION OBJECT_GROWTH_TREND_SWRF RETURNS OBJECT_GROWTH_SWRF_TABLE
 Argument Name                  Type                    In/Out Default?
 ------------------------------ ----------------------- ------ --------
 OBJECT_OWNER                   VARCHAR2                IN
 OBJECT_NAME                    VARCHAR2                IN
 OBJECT_TYPE                    VARCHAR2                IN
 PARTITION_NAME                 VARCHAR2                IN     DEFAULT
FUNCTION OBJECT_GROWTH_TREND_S_TO_I RETURNS INTERVAL DAY TO SECOND
 Argument Name                  Type                    In/Out Default?
 ------------------------------ ----------------------- ------ --------
 SECSIN                         NUMBER                  IN
PROCEDURE OBJECT_SPACE_USAGE
 Argument Name                  Type                    In/Out Default?
 ------------------------------ ----------------------- ------ --------
 OBJECT_OWNER                   VARCHAR2                IN
 OBJECT_NAME                    VARCHAR2                IN
 OBJECT_TYPE                    VARCHAR2                IN
 SAMPLE_CONTROL                 NUMBER                  IN
 SPACE_USED                     NUMBER                  OUT
 SPACE_ALLOCATED                NUMBER                  OUT
 CHAIN_PCENT                    NUMBER                  OUT
 PARTITION_NAME                 VARCHAR2                IN     DEFAULT
 PRESERVE_RESULT                BOOLEAN                 IN     DEFAULT
 TIMEOUT_SECONDS                NUMBER                  IN     DEFAULT
FUNCTION OBJECT_SPACE_USAGE_TBF RETURNS OBJECT_SPACE_USAGE_TABLE
 Argument Name                  Type                    In/Out Default?
 ------------------------------ ----------------------- ------ --------
 OBJECT_OWNER                   VARCHAR2                IN
 OBJECT_NAME                    VARCHAR2                IN
 OBJECT_TYPE                    VARCHAR2                IN
 SAMPLE_CONTROL                 NUMBER                  IN
 PARTITION_NAME                 VARCHAR2                IN     DEFAULT
 PRESERVE_RESULT                VARCHAR2                IN     DEFAULT
 TIMEOUT_SECONDS                NUMBER                  IN     DEFAULT
PROCEDURE PARSE_SPACE_ADV_INFO
 Argument Name                  Type                    In/Out Default?
 ------------------------------ ----------------------- ------ --------
 INFO                           VARCHAR2                IN
 USED_SPACE                     VARCHAR2                OUT
 ALLOCATED_SPACE                VARCHAR2                OUT
 RECLAIMABLE_SPACE              VARCHAR2                OUT
PROCEDURE SPACE_USAGE
 Argument Name                  Type                    In/Out Default?
 ------------------------------ ----------------------- ------ --------
 SEGMENT_OWNER                  VARCHAR2                IN
 SEGMENT_NAME                   VARCHAR2                IN
 SEGMENT_TYPE                   VARCHAR2                IN
 UNFORMATTED_BLOCKS             NUMBER                  OUT
 UNFORMATTED_BYTES              NUMBER                  OUT
 FS1_BLOCKS                     NUMBER                  OUT
 FS1_BYTES                      NUMBER                  OUT
 FS2_BLOCKS                     NUMBER                  OUT
 FS2_BYTES                      NUMBER                  OUT
 FS3_BLOCKS                     NUMBER                  OUT
 FS3_BYTES                      NUMBER                  OUT
 FS4_BLOCKS                     NUMBER                  OUT
 FS4_BYTES                      NUMBER                  OUT
 FULL_BLOCKS                    NUMBER                  OUT
 FULL_BYTES                     NUMBER                  OUT
 PARTITION_NAME                 VARCHAR2                IN     DEFAULT
PROCEDURE SPACE_USAGE
 Argument Name                  Type                    In/Out Default?
 ------------------------------ ----------------------- ------ --------
 SEGMENT_OWNER                  VARCHAR2                IN
 SEGMENT_NAME                   VARCHAR2                IN
 SEGMENT_TYPE                   VARCHAR2                IN
 SEGMENT_SIZE_BLOCKS            NUMBER                  OUT
 SEGMENT_SIZE_BYTES             NUMBER                  OUT
 USED_BLOCKS                    NUMBER                  OUT
 USED_BYTES                     NUMBER                  OUT
 EXPIRED_BLOCKS                 NUMBER                  OUT
 EXPIRED_BYTES                  NUMBER                  OUT
 UNEXPIRED_BLOCKS               NUMBER                  OUT
 UNEXPIRED_BYTES                NUMBER                  OUT
 PARTITION_NAME                 VARCHAR2                IN     DEFAULT
PROCEDURE SPACE_USAGE
 Argument Name                  Type                    In/Out Default?
 ------------------------------ ----------------------- ------ --------
 SEGMENT_OWNER                  VARCHAR2                IN
 SEGMENT_NAME                   VARCHAR2                IN
 SEGMENT_TYPE                   VARCHAR2                IN
 SUOPTION                       NUMBER                  IN
 SEGMENT_SIZE_BLOCKS            NUMBER                  OUT
 SEGMENT_SIZE_BYTES             NUMBER                  OUT
 USED_BLOCKS                    NUMBER                  OUT
 USED_BYTES                     NUMBER                  OUT
 EXPIRED_BLOCKS                 NUMBER                  OUT
 EXPIRED_BYTES                  NUMBER                  OUT
 UNEXPIRED_BLOCKS               NUMBER                  OUT
 UNEXPIRED_BYTES                NUMBER                  OUT
 PARTITION_NAME                 VARCHAR2                IN     DEFAULT
PROCEDURE UNUSED_SPACE
 Argument Name                  Type                    In/Out Default?
 ------------------------------ ----------------------- ------ --------
 SEGMENT_OWNER                  VARCHAR2                IN
 SEGMENT_NAME                   VARCHAR2                IN
 SEGMENT_TYPE                   VARCHAR2                IN
 TOTAL_BLOCKS                   NUMBER                  OUT
 TOTAL_BYTES                    NUMBER                  OUT
 UNUSED_BLOCKS                  NUMBER                  OUT
 UNUSED_BYTES                   NUMBER                  OUT
 LAST_USED_EXTENT_FILE_ID       NUMBER                  OUT
 LAST_USED_EXTENT_BLOCK_ID      NUMBER                  OUT
 LAST_USED_BLOCK                NUMBER                  OUT
 PARTITION_NAME                 VARCHAR2                IN     DEFAULT
FUNCTION VERIFY_SHRINK_CANDIDATE RETURNS BOOLEAN
 Argument Name                  Type                    In/Out Default?
 ------------------------------ ----------------------- ------ --------
 SEGMENT_OWNER                  VARCHAR2                IN
 SEGMENT_NAME                   VARCHAR2                IN
 SEGMENT_TYPE                   VARCHAR2                IN
 SHRINK_TARGET_BYTES            NUMBER                  IN
 PARTITION_NAME                 VARCHAR2                IN     DEFAULT
FUNCTION VERIFY_SHRINK_CANDIDATE_TBF RETURNS VERIFY_SHRINK_TABLE
 Argument Name                  Type                    In/Out Default?
 ------------------------------ ----------------------- ------ --------
 SEGMENT_OWNER                  VARCHAR2                IN
 SEGMENT_NAME                   VARCHAR2                IN
 SEGMENT_TYPE                   VARCHAR2                IN
 SHRINK_TARGET_BYTES            NUMBER                  IN
 PARTITION_NAME                 VARCHAR2                IN     DEFAULT

After specifying the correct argument, procedure is successfully executed.

SQL> set serveroutput on
declare
v_unformatted_blocks number;
v_unformatted_bytes number;
v_fs1_blocks number;
v_fs1_bytes number;
v_fs2_blocks number;
v_fs2_bytes number;
v_fs3_blocks number;
v_fs3_bytes number;
v_fs4_blocks number;
v_fs4_bytes number;
v_full_blocks number;
v_full_bytes number;
begin
dbms_space.space_usage ('&SCHEMA_NAME', '&TABLE_NAME', 'TABLE PARTITION', v_unformatted_blocks,
v_unformatted_bytes, v_fs1_blocks, v_fs1_bytes, v_fs2_blocks, v_fs2_bytes,
v_fs3_blocks, v_fs3_bytes, v_fs4_blocks, v_fs4_bytes, v_full_blocks, v_full_bytes,'R_MAY2022');
dbms_output.put_line('Unformatted Blocks = '||v_unformatted_blocks);
dbms_output.put_line('FS1 Blocks = '||v_fs1_blocks);
dbms_output.put_line('FS2 Blocks = '||v_fs2_blocks);
dbms_output.put_line('FS3 Blocks = '||v_fs3_blocks);
dbms_output.put_line('FS4 Blocks = '||v_fs4_blocks);
dbms_output.put_line('Full Blocks = '||v_full_blocks);
end;
/SQL>   2    3    4    5    6    7    8    9   10   11   12   13   14   15   16   17   18   19   20   21   22   23   24   25
Enter value for schema_name: C##HYDRA
Enter value for table_name: RP
old  15: dbms_space.space_usage ('&SCHEMA_NAME', '&TABLE_NAME', 'TABLE PARTITION', v_unformatted_blocks,
new  15: dbms_space.space_usage ('C##HYDRA', 'RP', 'TABLE PARTITION', v_unformatted_blocks,
Unformatted Blocks = 0
FS1 Blocks = 0
FS2 Blocks = 0
FS3 Blocks = 0
FS4 Blocks = 0
Full Blocks = 0

PL/SQL procedure successfully completed.
PARTITION IN LOB COLUMNS

Can we use partitioning key as LOB column in a partitioned table or during partitioned table creation?

No, LOB columns cannot be used as partitioning key but table containing LOB columns can be partitioned with non-LOB column as partitioning key.

ERROR at line 6:
ORA-14135: a LOB column cannot serve as a partitioning column


SQL> !oerr ora 14135
14135, 00000, "a LOB column cannot serve as a partitioning column"
// *Cause:  An attempt was made to specify a column of type BLOB or CLOB as a
//          partitioning or subpartitioning column.
// *Action: Ensure that no partitioning or subpartitioning column is of type
//          BLOB or CLOB.

All types of partitions are supported for table’s with LOB columns like range, list, hash, composite etc..

ORA-13780: SQL statement does not exist.

The error clearly states that the tuning task is failed because the sql_id is not present in cursor cache.

SQL> DECLARE
   l_sql_tune_task_id VARCHAR2(100);
  2  BEGIN
  3    4     l_sql_tune_task_id := DBMS_SQLTUNE.create_tuning_task (
  5     sql_id => '1n7b9udgaz4bv',
  6     scope => DBMS_SQLTUNE.scope_comprehensive,
  7     time_limit => 3600,
  8     task_name => '1n7b9udgaz4bv_tuning_task11',
   description => 'Tuning task1 for statement 1n7b9udgaz4bv');
   DBMS_OUTPUT.put_line('l_sql_tune_task_id: ' || l_sql_tune_task_id);
END;
  9   10   11   12  /
DECLARE
*
ERROR at line 1:
ORA-13780: SQL statement does not exist.
ORA-06512: at "SYS.DBMS_SYS_ERROR", line 79
ORA-06512: at "SYS.PRVT_SQLADV_INFRA", line 268
ORA-06512: at "SYS.DBMS_SQLTUNE", line 606
ORA-06512: at line 4


SQL> !oerr ora 13780
13780, 00000, "SQL statement does not exist."
// *Cause:  The user attempted to tune a SQL statement that does not exist.
// *Action: Verify the sql_id and the plan hash value of the statement and
//          retry the operation.

Extract the sql_id from AWR history and run the advisor report.

SQL> variable v_sql VARCHAR2(64);
SQL> EXEC :v_sql := DBMS_SQLTUNE.CREATE_TUNING_TASK(begin_snap => 769,  end_snap => 770,  sql_id => '1n7b9udgaz4bv' ,  scope => 'COMPREHENSIVE',  time_limit => 3600,  task_name => '1n7b9udgaz4bv_tuning_task');

PL/SQL procedure successfully completed.

SQL> EXEC DBMS_SQLTUNE.EXECUTE_TUNING_TASK(task_name => '1n7b9udgaz4bv_tuning_task');

PL/SQL procedure successfully completed.

SQL> set long 65536
set longchunksize 65536
set linesize 100
select dbms_sqltune.report_tuning_task('1n7b9udgaz4bv_tuning_task') from dual;SQL> SQL> SQL>

DBMS_SQLTUNE.REPORT_TUNING_TASK('1N7B9UDGAZ4BV_TUNING_TASK')
----------------------------------------------------------------------------------------------------
GENERAL INFORMATION SECTION
-------------------------------------------------------------------------------
Tuning Task Name   : 1n7b9udgaz4bv_tuning_task
Tuning Task Owner  : SYS
Workload Type      : Single SQL Statement
Scope              : COMPREHENSIVE
Time Limit(seconds): 3600
Completion Status  : COMPLETED
Started at         : 10/11/2023 17:13:21
Completed at       : 10/11/2023 17:13:24

-------------------------------------------------------------------------------
Schema Name   : C##HYDRA
Container Name: CDB$ROOT
SQL ID        : 1n7b9udgaz4bv
SQL Text      : Insert into CUSTOMERS(CUSTOMER_ID,CUST_FIRST_NAME,CUST_LAST_NA
                ME,NLS_LANGUAGE,NLS_TERRITORY,CREDIT_LIMIT,CUST_EMAIL,ACCOUNT_
                MGR_ID,CUSTOMER_SINCE,CUSTOMER_CLASS,SUGGESTIONS,DOB,MAILSHOT,
                PARTNER_MAILSHOT,PREFERRED_ADDRESS,PREFERRED_CARD) values (:1
                ,:2 ,:3 ,:4 ,:5 ,:6 ,:7 ,:8 ,:9 ,:10 ,:11 ,:12 ,:13 ,:14 ,:15
                ,:16 )

-------------------------------------------------------------------------------
ERRORS SECTION
-------------------------------------------------------------------------------
- ORA-00904: "PREFERRED_CARD": invalid identifier

-------------------------------------------------------------------------------