| Oracle FAQ | Your Portal to the Oracle Knowledge Grid | |
Home -> Community -> Mailing Lists -> Oracle-L -> RE: Who and What is using the shared pool.
This message is in MIME format. Since your mail reader does not understand
this format, some or all of this message may not be legible.
------_=_NextPart_001_01C00DE3.CFD168DE
Content-Type: text/plain;
charset="iso-8859-1"
Lisa,
I am baffled. I do not have access to 8.x at the moment. Is there anyone out there who can help Lisa?
Phil West - Impex IT ltd
Unix Sys Admin and Oracle Financials DBA Services
all opinions are worth [at most] what you paid for them
-----Original Message-----
From: Koivu, Lisa [mailto:lkoivu_at_qode.com]
Sent: 24 August 2000 16:52
To: Multiple recipients of list ORACLE-L
Subject: RE: Who and What is using the shared pool.
Hi Phil,
8.1.5 on HP/UX 11.0. Check it out below. I figured I would have to look at executions to determine if something that is constantly being reloaded really needs to be pinned. Seems to me if it's being executed a lot, and reloaded a lot, it should be pinned - and if it's being reloaded a lot but not executed more than once per load, it's not worth the effort.
Thanks in advance for any comments.
Lisa
SQL> select startup_time from v$instance;
STARTUP_T
2 , type 3 , to_char(sharable_mem/1024,'9,999.9') "SPACE(K)" 4 , loads 5 , executions execs 6 , kept
OBJECT TYPE SPACE(K) LOADSEXECS KEP
---------------------------------------- --------------- -------- --------- --------- --- QODE_LOAD.F_VALIDATE_ISBN FUNCTION 1.9 31 0 NO QODE_BC.PKG_GN_SPECIAL_OFFERS PACKAGE BODY 12.3 29 0 NO QODE_APP.CLEANUP_PARTNERNAME_STG2 PROCEDURE 2.8 25 0 NO QODE_APP.PKG_GENERATE_KEYWORD PACKAGE BODY 3.1 21 0 NO QODE_APP.PKG_UTIL PACKAGE 28.0 17 0 NO QODE_APP.PKG_CLEANUP PACKAGE BODY 9.3 17 0 NO QODE_BC.PKG_GN_SPECIAL_OFFERS PACKAGE 11.3 16 0 NO QODE_BC.CATHIERARCHY PACKAGE 1.7 15 0 NO QODE_BC.RPT_PARTNER_EMAIL PACKAGE 1.7 15 0 NO QODE_BC.PARTNER1 PACKAGE 1.7 15 0 NO QODE_APP.P_GUESTHOME PROCEDURE 73.7 15 0 NO QODE_USER.WEBDBTEST012345678912 PROCEDURE 1.7 15 0 NO QODE_BC.PARTRELATIONSHIP PACKAGE 1.2 15 0 NO QODE_BC.PARTNER_RELATIONSHIP1 PACKAGE 1.7 15 0 NO QODE_BC.CATHIERARCHY2 PACKAGE 1.7 15 0 NO QODE_APP.P_BUYQODER PROCEDURE 38.8 15 0 NO QODE_LOAD.PKG_LOAD PACKAGE BODY 1.4 15 0 NO QODE_APP.P_LOGIN PROCEDURE 75.2 15 0 NO QODE_BC.PARTNER9 PACKAGE 1.6 15 0 NO QODE_APP.PKG_SPECIALOFFERS_OBJ PACKAGE 35.6 14 0 NO QODE_APP.P_SIGN_UP_ERROR_VALIDATE PROCEDURE 17.6 13 0 NO QODE_BC.PARTNER9 PACKAGE BODY 1.4 13 0 NO QODE_LOAD.PKG_PRODUCT_CATEGORY PACKAGE BODY 2.6 13 0 NO QODE_APP.PKG_LIST_MAINT PACKAGE 21.8 13 0 NO QODE_BC.CATEGORY PACKAGE BODY 1.7 130 NO
-----Original Message-----
From: Philip West [mailto:P.West_at_g-icap.com]
Sent: Thursday, August 24, 2000 7:27 AM
To: Multiple recipients of list ORACLE-L
Subject: RE: Who and What is using the shared pool.
If your database has been up and running for a while I am VERY suprised that executions are 0 across the board. This is the way that I would always check for pinning candidates. Maybe someone else on the list could shed light. WHat versions are you running.
Phil West - Impex IT ltd
Unix Sys Admin and Oracle Financials DBA Services
all opinions are worth [at most] what you paid for them
-----Original Message-----
From: Koivu, Lisa [mailto:lkoivu_at_qode.com]
Sent: 23 August 2000 21:58
To: Multiple recipients of list ORACLE-L
Subject: RE: Who and What is using the shared pool.
Thanks Philip for sending this to the list.
However now I see that executions in v$db_object_cache is 0 everywhere. Is there an easy way to join to v$sqlarea to v$db_object_cache? I guess I was hoping to see if any heavily-used objects were being reloaded frequently and are candidates for pinning.
Anyone?? Thanks
Lisa
Ft. Lauderdale, FL, USA
*O*fficially *C*rabby and *P*eeved
-----Original Message-----
From: Philip West [ mailto:P.West_at_g-icap.com <mailto:P.West_at_g-icap.com> ]
Sent: Monday, August 21, 2000 1:33 PM
To: Multiple recipients of list ORACLE-L
Subject: RE: Who and What is using the shared pool.
Always keep to the shallow end of the shared pool. There are things swimming around in the depths that you do not want to meet!
Or, the problem is most likely shared pool fragmentation rather than the sizing per se. Fragmentation is a 'feature'. This is a big subject, which I would recommend you read up on (good papers on metalink on this subject. You do not tell us your db version. Ways to improve the situation include reserving a portion of the pool for larger objects. pinning critical or frequently reloaded objects into the pool. and, yes, increasing the size of the pool if necessary.
Look at v$sgastat to see what is where in your sga.
Try these (from the $AD_TOP/sql directory if you run Applications)
select owner || '.' || name OBJECT
, type
, to_char(sharable_mem/1024,'9,999.9') "SPACE(K)"
, loads
, executions execs
, kept
from v$db_object_cache
where type in ('FUNCTION','PACKAGE','PACKAGE BODY','PROCEDURE')
and owner not in ('SYS')
order by owner, name
/
select to_char(sum(sharable_mem)/1024,'9,999,999.9') "TOTAL SPACE (K)"
from v$db_object_cache
where type in ('FUNCTION','PACKAGE','PACKAGE BODY','PROCEDURE')
and owner not in ('SYS')
/
also look here:
Bookmark Fixed font Go to End
Doc ID: Note:61623.1
Type: BULLETIN
Status: PUBLISHED
Content Type: TEXT/PLAIN
Creation Date: 12-SEP-1997
Last Revision Date: 23-MAY-2000
Language: USAENG
PURPOSE
This document discusses some of the common issues associated with the
shared
pool in Oracle7 and describes how to diagnose and respond to these issues.
RELATED DOCUMENTS
[NOTE:1012049.6] TUNING LIBRARY CACHE LATCH CONTENTION
With Release 7.2 and 7.3, changes have been made to reduce usage of shared
memory as well as per-user (UGA) memory. Also, memory is not being
allocated
in large contiguous chunks, resulting in better shared-pool utilization and
reduction in fragmentation.
Before this error is signalled, all objects in the shared pool that are not currently in use will be flushed from the shared pool, and their memory will
be
freed and merged. This error only occurs when there is still not a large
enough contiguous piece of free memory after this happens. There may be
very
large amounts of total free memory in the shared pool, but just not enough
contiguous memory.
ii) INIT.ORA PARAMETER
An init.ora parameter can be set so that whenever an ORA-04031 error is
signalled a dump will occur into a trace file. By looking for these trace
files, the DBA can determine that these errors are occurring. This is
useful
when applications do not always report errors signalled by oracle, or if
users
do not report the errors to the DBAs. The parameter is the following:
event = "4031 trace name errorstack"
If you are using 7.0.16 or higher you can use the following:
event = "4031 trace name errorstack level 4"
This will cause a dump of the Oracle state objects to occur when this error
is
signalled. By looking in the dump for 'load=X' and then looking up a few
lines
for 'name=' you can often tell whether an object was being loaded into the
shared pool when this error occurred. If an object was being loaded then it
is
likely that this load is the cause of the problem and the object should be
'kept' in the shared pool. The object being loaded is the object printed
after
the 'name='. Do not use the 'level 4' option in versions before 7.0.16
because
a bug existed that often caused the system to crash with this option enabled
due to a latch level violation.
Prior to version 7.3, there were a handful of cases where the RDBMS or
PL/SQL
would attempt to allocate large pieces of contiguous memory. Most of this
has
been fixed for 7.3. This problem was especially acute when running MTS, when
the UGA would be located in the SGA. This should also be fixed in 7.3 and
using
MTS for a high OLTP scenario is recommended. As a result of all these
changes,
the ORA-04031 error should be virtually eliminated. If an ORA-04031 error is
signalled, quite likely the shared pool is over 90% utilized and the
alternative is to increase the shared pool. The only known situation is
PL/SQL
packages (like STANDARD) where the package contains a very large number
(over
400) procedure/function definitions. This still needs to be in contiguous
memory and may request memory chunks as large as 15K. Packages like this
should
be the only ones that should be kept.
iii) X$KSMLRU
There is a fixed table called x$ksmlru that tracks allocations in the
shared pool that cause other objects in the shared pool to be aged out.
This
fixed table can be used to identify what is causing the large allocation.
The columns of this fixed table are the following:
KSMLRCOM - allocation comment that describes the type of allocation.
If this comment is something like 'MPCODE' or 'PLSQL%' then there is a large
PL/SQL object being loaded into the shared pool. This PL/SQL object will
need
to be 'kept' in the shared pool.
If this comment is 'kgltbtab' then the allocation is for a dependency table
in
the library cache. This is only a problem when several hundred users are
logged
on using distinct user ids. The solution in this case is to use fully
qualified
names for all table references.
If you are running MTS and the comment is something like 'Fixed UGA' then
the
problem is that the init.ora parameter 'open_cursors' is set too high.
KSMLRSIZ - amount of contiguous memory being allocated. Values over around
5K
start to be a problem, values over 10K are a serious problem, and values
over
20K are very serious problems. Anything less then 5K should not be a
problem.
KSMLRNUM - number of objects that were flushed from the shared pool in order
allocate the memory.
In release 7.1.3 or later, the following columns also exist:
KSMLRHON - the name of the object being loaded into the shared pool if the object is a PL/SQL object or a cursor.
KSMLROHV - hash value of object being loaded
KSMLRSES - SADDR of the session that loaded the object.
The advantage of X$KSMLRU is that it allows you to identify problems with fragmentation that are effecting performance, but that are not bad enough to
be
causing ORA-04031 errors to be signalled. If a lot of objects are being
periodically flushed from the shared pool then this will cause response time
problems and will likely cause library cache latch contention problems when
the
objects are reloaded into the shared pool. With version 7.2, the library
cache
latch contention should be significantly reduced with the breaking up of the
library cache pin latch into a configurable set of symmetric library cache latches.
One unusual thing about the x$ksmlru fixed table is that the contents of the
fixed table are erased whenever someone selects from the fixed table. This
is
done since the fixed table stores only the largest allocations that have
occurred. The values are reset after being selected so that subsequent
large
allocations can be noted even if they were not quite as large as others that
occurred previously. Because of this resetting, the output of selecting
from
this table should be carefully noted since it cannot be reselected if it is
forgotten. Also you should take care that there are not multiple people on
one
database that select from this table because only one of them will select
the
real data.
To monitor this fixed table just run the following:
select * from x$ksmlru where ksmlrsiz > 5000;
iv) MTS
Oracle users using SQL*Net V2 can connect to the database using dedicated
servers, or multiple clients can use a pool of shared (or MTS) servers. The
biggest memory implication of this mode is that the session memory (also
known
as the UGA) for every session needs to be accessible to every MTS server.
This
implies that the logical UGA comes out of the physical SGA (or the shared
pool) instead of the PGA (process memory).
In versions prior to 7.3, there were a few components in the UGA that would
request large contiguous chunks of memory, contributing to fragmentation of
the shared pool if using MTS. If the system had been up for a while, users
would have failures when attempting to connect or executing sql. Starting
with
7.3, all these allocations have been segmented such that the average size of
memory chunks allocated to the UGA should be about 5K.
B) CORRECTION OF FRAGMENTATION i) KEEPING OBJECTS
The primary source of problems is large PL/SQL objects. The means of
correcting
these errors is to 'keep' large PL/SQL object in the shared pool at startup
time. This will load the objects into the shared pool and will make sure
that
the objects are never aged out of the shared pool. If the objects are never
aged out then there will not be a problem with trying to load them and not
having enough memory.
Objects are 'kept' in the shared pool using the dbms_shared_pool package
that
is defined in the dbmspool.sql file. For example:
execute dbms_shared_pool.keep('SYS.STANDARD');
All large packages that are shipped should be 'kept' if the customer uses
PL/SQL. This includes 'STANDARD', 'DBMS_STANDARD', and 'DIUTIL'. With 7.3,
the
only package left in this list is 'STANDARD'.
All large customer packages should also be marked 'kept'.
To mark all packages in the system 'kept' execute the following:
declare
own varchar2(100);
nam varchar2(100);
cursor pkgs is
select owner, object_name
from dba_objects
where object_type = 'PACKAGE';
The dbms_shared_pool package was introduced in 7.0 and has evolved over the versions. Until 7.1.5, 'keep' could only be used for packages. Starting with
7.1.6, this was extended to standalone procedures, cursors as well as
triggers.
For detailed usage instructions, see the dbmspool.sql file. So, prior to
this
version, if you have large procedures or large anonymous blocks, then these
will need to be put into packages and marked kept. With 7.3, most packages
do
not need to be kept any longer since PL/SQL no longer requires large amounts
of
contiguous memory to load packages/procedures in memory.
You can determine what large stored objects are in the shared pool by
selecting
from the v$db_object_cache fixed view. This will also tell you which
objects
have been marked kept. This can be done with the following query:
select * from v$db_object_cache where sharable_mem > 10000;
Note that this query will not catch PL/SQ: objects that are only rarely used
and therefore the PL/SQL object is not currently loaded in the shared pool.
To determine what large PL/SQL objects are currently loaded in the shared
pool
and are not marked 'kept' and therefore may cause a problem, execute the
following:
select name, sharable_mem
from v$db_object_cache
where sharable_mem > 10000
and (type = 'PACKAGE' or type = 'PACKAGE BODY' or type = 'FUNCTION'
or type = 'PROCEDURE')
and kept = 'NO';
Another approach to the above is to use the dbms_shared_pool.sizes
procedure.
To use this in SQLDBA:
set serveroutput on;
execute dbms_shared_pool.sizes(10);
This should show you the names of all the objects in the shared pool that
take
more that 10K of memory as well as if they are marked kept or not. For SQL
statements, if there are multiple versions of a query (usually a bug if the
count is more than 3), they will also be indicated in parenthesis. Use the
following query to check for problems:
select sql_text, loaded_versions, version_count, sharable_mem from v$sqlarea where loaded_versions > 3 order by sharable_mem;
In Oracle7.3 onwards the best candidates for keeping can be seen by querying
the table X$KSMSP to see if there are any chunks in the shared-pool that
have
the KSMCHSIZ larger than 5K and KSMCHCOM like '%PL/SQL%'. If so then one can
identify the object name and owner of this chunk using the following SQL:
select distinct
decode(kglobtyp,0,'CURSOR',7,'PROCEDURE',8,'FUNCTION',9,'PACKAGE',
11,'PACKAGE BODY',12,'TRIGGER',13,'TYPE',14,'TYPE
BODY','OTHER')
||' - '||kglnaown||'.'||kglnaobj "Eligible PL/SQL objects"
from x$kglob
where kglobhd4 in
(select ksmchpar from x$ksmsp
where ksmchcom='PL/SQL MPCODE' and ksmchsiz>5120)
If you are 'keeping' PL/SQL objects today and migrate to 7.3 or higher there
is
no need to re-assess the list of objects that you are keeping.
ii) USE BIND VARIABLES
One of the best things that can be done to reduce the amount of
fragmentation
is to reduce or eliminate the number of sql statements in the shared pool
that
are duplicates of each other except for a constant that is embedded in the
statement. The statements should be replaced with one statement that uses
a bind variable instead of a constant.
For example:
select * from emp where empno=1; select * from emp where empno=2; select * from emp where empno=3;
Should all be replaced with:
select * from emp where empno=:1;
You can identify statements that potentially fall into this class with a
query
like the following:
select substr(sql_text, 1, 30) sql, count(*) copies
from v$sqlarea
group by substr(sql_text, 1, 30)
having count(*) > 3;
iii) MAX BIND SIZE
It is possible for a SQL statement to not be shared because the max bind
variable lengths of the bind variables in the statement do not match. This
is
automatically taken care of for precompiler programs and forms programs, but
could be a problem for programs that directly use OCI. The bind call in OCI
takes two arguments, one is the max length of the value, and the other is a
pointer to the actual length. If the current length is always passed in as
the
max length instead of the max possible length for the variable, then this
could
cause the SQL statement not to be shared.
To identify statements that might potentially have this problem execute the following statement:
select sql_text, version_count from v$sqlarea where version_count > 5;
Starting with 7.1.6 this should no longer be an issue as the server can
graduate bind buffers even when the user's max bind lengths are jumping up
or
down and continue to share cursors that are built for larger buffer lengths
and flush the smaller sql compilation from the shared pool.
iv) ELIMINATING LARGE ANONYMOUS PL/SQL
Large anonymous PL/SQL blocks should be turned into small anonymous PL/SQL
blocks that call packaged functions. The packages should be 'kept' in
memory.
For version earlier that 7.3, this includes anonymous PL/SQL blocks that are
used for trigger definitions. With 7.3, triggers are compiled and stored to
disk like standalone procedures and should be treated as such. Large
anonymous
blocks can be identified with the following query:
select sql_text from v$sqlarea
where command_type=47 -- command type for anonymous block
and length(sql_text) > 500;
Note that this query will not catch PL/SQL blocks that are only rarely used
and
therefore the PL/SQL block is not currently loaded in the shared pool.
Another option that can be used when an anonymous block cannot be turned
into
a package is to mark the anonymous block with some string so that it can be
identified in v$sqlarea and marked 'kept'.
For example, instead of using:
declare x number; begin x := 5; end;;
you can use:
declare /* KEEP_ME */ x number; begin x := 5; end;
You can then use the following procedure to select these statements out of
the
shared pool and mark them 'kept' using the dbms_shared_pool.keep package.
declare
/* DONT_KEEP_ME */
addr varchar2(10);
hash number;
cursor anon is
select address, hash_value
from v$sqlarea
where command_type = 47 -- command type for anonymous
block
and sql_text like '% KEEP_ME %'
and sql_text not like '%DONT_KEEP_ME%';
begin
v) REDUCING USAGE
Another way to reducing fragmentation is to reduce consumption. This is of
special importance when using MTS, when every user's session memory is in
the
shared pool and the impact is multiplied by the total concurrent users.
Insert, update, delete and anonymous blocks complete the execution in one
round
trip. All the memory that is allocated on the server for the execute comes
from
the PGA and is freed before the call returns to the user. But in the case of
selects, memory required to execute the statement - which could be large if
a
sort was involved - is not freed until the end-of-fetch is reached or the
query
is cancelled. In these situations using the OCI features to do an exact
fetch
and cancel helps free memory back to the pool.
If the application logic has been embedded into server side PL/SQL, a large number of cursors may be getting cached on the server for every user. Though
this results in reduced latch contention and faster response, it does use
more
memory in the UGA. Setting the close_cached_open_cursors init.ora to TRUE
closes the PL/SQL cached cursors on the server, freeing the memory.
2) COMMON FALLACIES There are a number of common fallacies about the shared pool that are often stated as fact.
not
like the free memory reported by operating system statistics. Since the
shared
pool acts as a cache, nothing will ever be aged out of the shared pool until
all
the free memory has been used up. This is entirely normal.
Free memory is more properly thought of as 'wasted memory'. You would
rather
see this value be low than very high. In fact, a high value of free memory
is
sometimes a symptom that a lot of objects have been aged out of the shared
pool
and therefore the system is experiencing fragmentation problems.
B) FLUSH SHARED POOL Some people think that frequently executing 'alter system flush shared_pool'
improves the performance of the system and decreases the amount of
fragmentation. This is incorrect. Executing this statement causes a big
spike
in performance and does nothing to improve fragmentation.
The only time when it might be useful to run this statement is between
shifts of
users so that the objects that are relevant to the last shift of users can
be
flushed out before the next shift of users starts to use the system. This
is
almost never needed though.
3) SIZING OF SHARED POOL
One very difficult judgement that needs to be make in Oracle7 is to
determine
the proper size of the shared pool. The following provides some guidelines
for
this. It should be emphasized that these are just guidelines, there are no
hard and fast rules here and experimentation will be needed to determine a
good
value.
The shared pool size is highly application dependent. To determine the
shared
pool size that will be needed for a production system it is generally
necessary
to first develop the application and run it on a test system and take some
measurements. The test system should be run with a very large value for the
shared pool size to make the measurements meaningful.
select sum(sharable_mem) from v$db_object_cache;
This is especially effective because all large pl/sql object should be
'kept'
in the shared pool at all times.
B) SQL
The amount of memory needed to store SQL statements in the shared pool is
more
difficult to measure because of the needs of dynamic SQL. If an application
has no dynamic SQL then the amount of memory can simply be measured after
the
application has run for a while by just selecting it out of the shared pool
as
follows:
select sum(sharable_mem) from v$sqlarea;
If the application has a moderate or large amount of dynamic SQL like most
applications do, then a certain amount of memory will be needed for the
shared
SQL, plus more for the dynamic SQL, and more so that the dynamic SQL does
not
age the shared SQL out of the shared pool.
The amount of memory for the shared SQL can be approximated by the following:
select sum(sharable_mem) from v$sqlarea where executions > 5;
The remaining memory in v$sqlarea is for dynamic SQL Some shared pool will need to be budgeted for this also, but there are few rules here.
C) PER-USER PER-CURSOR MEMORY You will need to allow around 250 bytes of memory in the shared pool per concurrent user for each open cursor that the user has whether the cursor is
shared or not. During the peak usage time of the production system, you can
measure this as follows:
select sum(250 * users_opening) from v$sqlarea;
In a test system you can measure it by selecting the number of open cursors for a test user and multiplying by the total number of users:
select 250 * value bytes_per_user
from v$sesstat s, v$statname n
where s.statistic# = n.statistic#
and n.name = 'opened cursors current'
and s.sid = 23; -- replace 23 with session id of user being
measured
The per-user per-cursor memory is one of the classes of memory that shows up
as
'library cache' in v$sgastat.
D) MTS If you are using multi-threaded server, then you will need to allow enough memory for all the shared server users to put their session memory in the shared pool. This can be measured for one user with the following query:
select value sess_mem
from v$sesstat s, v$statname n
where s.statistic# = n.statistic#
and n.name = 'session uga memory'
and s.sid = 23; -- replace 23 with session id of user being
measured
A more conservative value to use is the maximum session memory that was ever allocated by the user:
select value sess_max_mem
from v$sesstat s, v$statname n
where s.statistic# = n.statistic#
and n.name = 'session uga memory max'
and s.sid = 23; -- replace 23 with session id of user being
measured
To select this value for all the currently logged on users the following
query
can be used:
select sum(value) all_sess_mem
from v$sesstat s, v$statname n
where s.statistic# = n.statistic#
and n.name = 'session uga memory max';
E) OVERHEAD
You will need to add a minimum of 30% overhead to the values calculated
above
to allow for unexpected and unmeasured usage of the shared pool.
4) FINAL COMMENTS
The most important point that needs to be understood by everyone using
Oracle7
and PL/SQL (prior to release 7.3) is that all large PL/SQL objects must be
made
into packages and those packages must be kept in the shared pool. This point
cannot be over emphasized. Many customers, especially those running a lot
of
users, have had terrible performance problems that were completely cleared
up
by doing this.
APPENDIX I: Reserved Shared Pool
=================================
memory to satisfy a large request for memory. Because the RDBMS will search
for and free currently unused memory, the search for this large piece of
memory
may disrupt the behavior of the share pool, leading to more fragmentation
and
poor performance.
RDBMS 7.1.5 allows DBAs to reserve memory within the shared pool to satisfy
these large allocations during RDBMS operations such as PL/SQL compilation
and
trigger compilation. Smaller objects will not fragment the reserved list,
helping to ensure the reserved list will have large contiguous chunks of
memory.
Once the memory allocated from the reserved list is freed, it returns to the
reserved list.
The size of the reserved list, as well as the minimum size of the objects
that
can be allocated from the reserved list are controlled via init.ora
parameters:
shared_pool_reserved_size and shared_pool_reserved_min_alloc.
1.1 shared_pool_reserved_size
units : bytes default: 0 (no reserved list) minimum: > shared_pool_reserved_min_alloc maximum: 1/2 shared_pool_size
1.2 shared_pool_reserved_min_alloc
units : bytes default: 5000 minimum: 5000 maximum: < shared_pool_reserved_size
The default value for shared_pool_reserved_min_alloc should be adequate for almost all systems.
2. CONTROLLING SPACE RECLAMATION OF THE SHARED POOL
Before the RDBMS signals the ORA-04031 error, it incrementally flushes
unused
objects from the shared pool until there is sufficient memory to satisfy the
allocation request. In most cases, incrementally flushing objects from the
shared pool frees enough memory for the allocation to complete succesfully.
If
the RDBMS signals an ORA-04031 error, it has flushed all objects currently
not
in use on the system without finding a large enough piece of contiguous
memory.
On a busy system, the larger the space allocation, the more likely the RDBMS
will signal the ORA-04031 error. Flushing all objects, however, will impact
other users on the system, possibly causing a degradation in performance.
The aborted_request_threshold procedure allows the DBA to localize the
impact
the ORA-04031 error to the process that couldn't allocate memory. The
procedure
takes a numeric value between 5000 and 2147483647, representing the size, in
bytes, of the threshold.
3. NEW FIXED VIEW V$SHARED_POOL_RESERVED
Name Null? Type ------------------------------- -------- -------------- FREE_SPACE NUMBER AVG_FREE_SIZE NUMBER FREE_COUNT NUMBER MAX_FREE_SIZE NUMBER USED_SPACE NUMBER AVG_USED_SIZE NUMBER USED_COUNT NUMBER MAX_USED_SIZE NUMBER REQUESTS NUMBER REQUEST_MISSES NUMBER LAST_MISS_SIZE NUMBER MAX_MISS_SIZE NUMBER REQUEST_FAILURES NUMBER LAST_FAILURE_SIZE NUMBER ABORTED_REQUEST_THRESHOLD NUMBER ABORTED_REQUESTS NUMBER LAST_ABORTED_SIZE NUMBER
These columns of V$SHARED_POOL_RESERVED are only valid if the parameter shared_pool_reserved_size is set to a valid value.
FREE_SPACE is the total amount of free space on the reserved list.
AVG_FREE_SIZE is the average size of the free memory on the reserved list.
FREE_COUNT is the number of free pieces of memory on the reserved list.
MAX_FREE_SIZE is the size of the largest free piece of memory on the reserved
list.
USED_SPACE is the total amount of used memory on the reserved list.
AVG_USED_SIZE is the average size of the of the used memory on the reserved
list.
USED_COUNT is the number of used pieces of memory on the reserved list.
MAX_USED_SIZE is the size of the largest used piece of memory on the reserved
list.
REQUESTS is the number of times that the reserved list was searched for a
free piece of memory.
REQUEST_MISSES is the number of times the reserved list didn't have a free
piece of memory to satisfy the request, and proceeded to
start
flushing objects from the LRU list.
LAST_MISS_SIZE is the request size of the last REQUEST_MISS.
MAX_MISS_SIZE is the request size of the largest REQUEST_MISS.
The next set of columns contain values which are valid even if shared_pool_reserved_size is not set.
REQUEST_FAILURES is the number of times that no memory was found to satisfy a
request (example: number of times ORA-04031 occurred)
LAST_FAILURE_SIZE is the request size of the last failed request
(example: the request size of last ORA-04031).
ABORTED_REQUEST_THRESHOLD is the minimum size of a request which will signal
an ORA-04031 error without flushing objects. See
the procedure aborted_request_threshold
described
above.
LAST_ABORTED_SIZE is the last size of the request which returned an ORA-04031
error without flushing objects from the LRU list.
4. TUNING HINTS BASED ON V$SHARED_POOL_RESERVED
4.1 Initial Value for shared_pool_reserved_size
4.2 Initial Value for shared_pool_reserved_min_alloc
4.4 Tuning shared_pool_reserved_size
If the DBA has a system with ample free memory to increase his SGA, the goal
is
to have:
REQUEST_MISS = 0 If the DBA is constrained for OS memory, his goal is:
REQUEST_FAILURES = 0 or not increasing LAST_FAILURE_SIZE > shared_pool_reserved_min_alloc AVG_FREE_SIZE > shared_pool_reserved_min_alloc
If neither of these goals are met, increase shared_pool_reserved_size; the
DBA
also needs to increase shared_pool_size by the same amount, since the
reserved
list is taken from the shared pool.
4.5 shared_pool_reserved_size too low
REQUEST_FAILURES > 0 (and increasing)
and at least one of the following is true:
LAST_FAILURE_SIZE > shared_pool_reserved_min_alloc MAX_FREE_SIZE < shared_pool_reserved_min_alloc FREE_MEMORY < shared_pool_reserved_min_alloc
The DBA has two options, depending on his SGA size constraints:
o Increase shared_pool_reserved_size and shared_pool_size, accordingly o Increase shared_pool_reserved_min_alloc (but may need to increase
shared_pool_size)
The first option will increase the amount of memory available on the
reserved
list without impacting users not allocating memory from the reserved list.
The
second options reduces the number of allocations allowed to use memory from
the
reserved list; doing so, however, will increase normal shared pool perhaps
impacting other users on the system.
4.6 shared_pool_reserved_size too high
If:
REQUEST_MISS = 0 or not increasing FREE_MEMORY = > 50% of shared_pool_reserved_size minimum
The DBA has two options:
o Decrease shared_pool_reserved_size o Decrease shared_pool_reserved_min_alloc (if not the default
value)
4.7 shared_pool_size too small
REQUEST_FAILURES > 0 and increasing LAST_FAILURE_SIZE < shared_pool_reserved_min_alloc
Then the DBA has two options if he has enabled the reserved list:
o Decrease shared_pool_reserved_size o Decrease shared_pool_reserved_min_alloc (if set larger than the default)
Otherwise, the DBA the could:
o Increase shared_pool_size
APPENDIX 2: Procedure free_unused_memory
=========================================
This text is also in the specification for this procedure in dbmsutil.sql. It is part of package dbms_session.
Procedure free_unused_memory --
Procedure for users to reclaim unused memory after performing operations requiring large amounts of memory (where large is >100K). Note that this procedure should only be used in cases where memory is at a premium.
Examples operations using lots of memory are:
o large sorts where entire sort_area_size is used and
sort_area_size is hundreds of KB
o compiling large PL/SQL packages, procedures, or functions
o storing hundreds of KB of data within PL/SQL indexed tables
One can monitor user memory by tracking the statistics "session uga memory"
and
"session pga memory" in the v$sesstat/v$statname fixed views. Monitoring
these
statistics will also show how much memory this procedure has freed. The
behavior
of this procedure depends upon the configuration of the server operating on
behalf of the client:
o dedicated server - returns unused PGA memory to the OS o MTS server - returns unused session memory to the shared_pool
In order to free memory using this procedure, the memory must not be in use.
Once an operation allocates memory, only the same type of operation can
reuse
the allocated memory. For example, once memory is allocated for sort, even
if
the sort is complete and the memory is no longer in use, only another sort
can
reuse the sort-allocated memory. For both sort and compilation, after the
operation is complete, the memory is no longer in use and the user can
invoke
this procedure to free the unused memory.
An indexed table implicitly allocates memory to store values assigned to the
indexed table's elements. Thus, the more elements in an indexed table, the
more
memory the RDBMS allocates to the indexed table. As long as there are
elements
within the indexed table, the memory associated with an indexed table is in
use.
The scope of indexed tables determines how long their memory is in use.
Indexed
tables declared globally are indexed tables declared in packages or package
bodies. They allocate memory from session memory. For an indexed table
declared globally, the memory will remain in use for the lifetime of a
user's
login (lifetime of a user's session), and is freed after the user
disconnects
from ORACLE.
Indexed tables declared locally are indexed tables declared within
functions,
procedures, or anonymous blocks. These indexed tables allocate memory from
PGA
memory. For an indexed table declared locally, the memory will remain in
use
for as long as the user is still executing the procedure, function, or
anonymous
block in which the indexed table is declared. After the procedure,
function, or
anonymous block is finished executing, the memory is then available for
other
locally declared indexed tables to use (i.e., the memory is no longer in
use).
Assigning an uninitialized, "empty," indexed table to an existing index
table is
a method to explicitly re-initialize the indexed table and the memory
associated
with the indexed table. After this operation, the memory associated with
the
indexed table will no longer be in use, making it available to be freed by
calling this procedure. This method is particularly useful on indexed
tables
declared globally which can grow during the lifetime of a user's session, as
long as the user no longer needs the contents of the indexed table.
The memory rules associated with an indexed table's scope still apply; this
method and this procedure, however, allow users to intervene and to
explictly
free the memory associated with an indexed table.
The PL/SQL fragment below illustrates the method and the use of procedure free_unused_user_memory.
create package foobar
type number_idx_tbl is table of number indexed by binary_integer;
store1_table number_idx_tbl; -- PL/SQL indexed table store2_table number_idx_tbl; -- PL/SQL indexed table store3_table number_idx_tbl; -- PL/SQL indexed table ... end; -- end of foobar
store1_table(1) := 100; -- index tables still declared; store2_table(2) := 200; -- but truncated....
Copyright (c) 1995,1999 Oracle Corporation. All Rights Reserved. Legal Notices and Terms of Use.
Phil West - Impex IT ltd
Unix Sys Admin and Oracle Financials DBA Services
all opinions are worth [at most] what you paid for them
When addressed to our clients any opinions or advice contained in this Internet e-mail are subject to the terms and conditions expressed in any applicable documentation or market practices governing the relationship between Garban Intercapital plc and its clients.
Any views expressed in this message are those of the individual sender except where they are stated to be the views of Garban Intercapital plc.
--
Author: Philip West
INET: P.West_at_g-icap.com
Fat City Network Services -- (858) 538-5051 FAX: (858) 538-5051
San Diego, California -- Public Internet access / Mailing Lists
--------------------------------------------------------------------
To REMOVE yourself from this mailing list, send an E-Mail message
to: ListGuru_at_fatcity.com (note EXACT spelling of 'ListGuru') and in
the message BODY, include a line containing: UNSUB ORACLE-L
(or the name of mailing list you want to be removed from). You may
also send the HELP command for other information (like subscribing).
------_=_NextPart_001_01C00DE3.CFD168DE
Content-Type: text/html;
charset="iso-8859-1"
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML><HEAD>
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1">
<TITLE>RE: Who and What is using the shared pool.</TITLE>
<META content="MSHTML 5.00.2314.1000" name=GENERATOR></HEAD>
<BODY>
<DIV><FONT color=#0000ff face=Arial size=2><SPAN
class=343393315-24082000>Lisa,</SPAN></FONT></DIV>
<DIV><FONT color=#0000ff face=Arial size=2><SPAN
class=343393315-24082000></SPAN></FONT> </DIV>
<DIV><FONT color=#0000ff face=Arial size=2><SPAN class=343393315-24082000>I am
baffled. I do not have access to 8.x at the moment. Is there anyone
out there who can help Lisa? </SPAN></FONT></DIV>
<DIV> </DIV>
<P><FONT face=Arial>Phil West - Impex IT ltd</FONT> <BR><FONT
face="Arial Narrow" size=1>Unix Sys Admin and Oracle Financials DBA
Services</FONT> </P>
<P><FONT face="Arial Narrow" size=1>all opinions are worth [at most] what you
paid for them</FONT> </P>
<BLOCKQUOTE style="MARGIN-RIGHT: 0px">
<DIV align=left class=OutlookMessageHeader dir=ltr><FONT face=Tahoma
size=2>-----Original Message-----<BR><B>From:</B> Koivu, Lisa
[mailto:lkoivu_at_qode.com]<BR><B>Sent:</B> 24 August 2000 16:52<BR><B>To:</B>
Multiple recipients of list ORACLE-L<BR><B>Subject:</B> RE: Who and What is
using the shared pool.<BR><BR></DIV></FONT>
<DIV><FONT color=#0000ff face=Arial size=2><SPAN class=473444114-24082000>Hi
Phil, </SPAN></FONT></DIV>
<DIV><FONT color=#0000ff face=Arial size=2><SPAN
class=473444114-24082000></SPAN></FONT> </DIV>
<DIV><FONT color=#0000ff face=Arial size=2><SPAN
class=473444114-24082000>8.1.5 on HP/UX 11.0. Check it out below.
I figured I would have to look at executions to determine if something that is
constantly being reloaded really needs to be pinned. Seems to me if it's
being executed a lot, and reloaded a lot, it should be pinned - and if it's
being reloaded a lot but not executed more than once per load, it's not worth
the effort. </SPAN></FONT></DIV>
<DIV><FONT color=#0000ff face=Arial size=2><SPAN
class=473444114-24082000></SPAN></FONT> </DIV>
<DIV><FONT color=#0000ff face=Arial size=2><SPAN
class=473444114-24082000>Thanks in advance for any comments.
</SPAN></FONT></DIV>
<DIV><FONT color=#0000ff face=Arial size=2><SPAN
class=473444114-24082000>Lisa</SPAN></FONT></DIV>
<DIV><FONT color=#0000ff face=Arial size=2><SPAN
class=473444114-24082000></SPAN></FONT> </DIV>
<DIV><FONT color=#0000ff face="Courier New" size=2><SPAN
class=473444114-24082000>SQL> select startup_time from
v$instance;</SPAN></FONT></DIV>
<DIV> </DIV>
<DIV><FONT color=#0000ff face="Courier New" size=2><SPAN
class=473444114-24082000>STARTUP_T<BR>---------<BR>02-AUG-00</SPAN></FONT></DIV>
<DIV><FONT color=#0000ff><SPAN
class=473444114-24082000></SPAN></FONT> </DIV>
<DIV><FONT color=#0000ff face="Courier New" size=2><SPAN
class=473444114-24082000> 1 select owner || '.' || name
OBJECT<BR> 2 ,
type<BR> 3 ,
to_char(sharable_mem/1024,'9,999.9') "SPACE(K)"<BR>
4 , loads<BR>
5 , executions
execs<BR> 6 ,
kept<BR> 7 from v$db_object_cache<BR> 8 where type in
('FUNCTION','PACKAGE','PACKAGE BODY','PROCEDURE')<BR>
9 and owner not in ('SYS')<BR> 10* order by loads
desc<BR>SQL> /</SPAN></FONT></DIV>
<DIV> </DIV>
<DIV><FONT color=#0000ff face="Courier New" size=2><SPAN
class=473444114-24082000>OBJECT
TYPE
SPACE(K) LOADS EXECS
KEP<BR>---------------------------------------- --------------- --------
--------- ---------
---<BR>QODE_LOAD.F_VALIDATE_ISBN
FUNCTION
1.9
31 0
NO<BR>QODE_BC.PKG_GN_SPECIAL_OFFERS
PACKAGE BODY
12.3
29 0
NO<BR>QODE_APP.CLEANUP_PARTNERNAME_STG2
PROCEDURE
2.8
25 0
NO<BR>QODE_APP.PKG_GENERATE_KEYWORD
PACKAGE BODY
3.1
21 0
NO<BR>QODE_APP.PKG_UTIL
PACKAGE
28.0
17 0
NO<BR>QODE_APP.PKG_CLEANUP
PACKAGE BODY
9.3
17 0
NO<BR>QODE_BC.PKG_GN_SPECIAL_OFFERS
PACKAGE
11.3
16 0
NO<BR>QODE_BC.CATHIERARCHY
PACKAGE
1.7
15 0
NO<BR>QODE_BC.RPT_PARTNER_EMAIL
PACKAGE
1.7
15 0
NO<BR>QODE_BC.PARTNER1
PACKAGE
1.7
15 0
NO<BR>QODE_APP.P_GUESTHOME
PROCEDURE
73.7
15 0
NO<BR>QODE_USER.WEBDBTEST012345678912
PROCEDURE
1.7
15 0
NO<BR>QODE_BC.PARTRELATIONSHIP
PACKAGE
1.2
15 0
NO<BR>QODE_BC.PARTNER_RELATIONSHIP1
PACKAGE
1.7
15 0
NO<BR>QODE_BC.CATHIERARCHY2
PACKAGE
1.7
15 0
NO<BR>QODE_APP.P_BUYQODER
PROCEDURE
38.8
15 0
NO<BR>QODE_LOAD.PKG_LOAD
PACKAGE BODY
1.4
15 0
NO<BR>QODE_APP.P_LOGIN
PROCEDURE
75.2
15 0
NO<BR>QODE_BC.PARTNER9
PACKAGE
1.6
15 0
NO<BR>QODE_APP.PKG_SPECIALOFFERS_OBJ
PACKAGE
35.6
14 0
NO<BR>QODE_APP.P_SIGN_UP_ERROR_VALIDATE
PROCEDURE
17.6
13 0
NO<BR>QODE_BC.PARTNER9
PACKAGE BODY
1.4
13 0
NO<BR>QODE_LOAD.PKG_PRODUCT_CATEGORY
PACKAGE BODY
2.6
13 0
NO<BR>QODE_APP.PKG_LIST_MAINT
PACKAGE
21.8
13 0
NO<BR>QODE_BC.CATEGORY
PACKAGE BODY
1.7
13 0 NO</SPAN></FONT></DIV>
<BLOCKQUOTE style="MARGIN-RIGHT: 0px">
<DIV align=left class=OutlookMessageHeader dir=ltr><FONT face=Tahoma
size=2>-----Original Message-----<BR><B>From:</B> Philip West
[mailto:P.West_at_g-icap.com]<BR><B>Sent:</B> Thursday, August 24, 2000 7:27
AM<BR><B>To:</B> Multiple recipients of list ORACLE-L<BR><B>Subject:</B> RE:
Who and What is using the shared pool.<BR><BR></DIV></FONT>
<DIV><FONT color=#0000ff face=Arial size=2><SPAN class=781273408-24082000>If
your database has been up and running for a while I am VERY suprised that
executions are 0 across the board. This is the way that I would always
check for pinning candidates. Maybe someone else on the list could
shed light. WHat versions are you running.</SPAN></FONT></DIV>
<P><FONT face=Arial>Phil West - Impex IT ltd</FONT> <BR><FONT
face="Arial Narrow" size=1>Unix Sys Admin and Oracle Financials DBA
Services</FONT> </P>
<P><FONT face="Arial Narrow" size=1>all opinions are worth [at most] what
you paid for them</FONT> </P>
<BLOCKQUOTE style="MARGIN-RIGHT: 0px">
<DIV align=left class=OutlookMessageHeader dir=ltr><FONT face=Tahoma
size=2>-----Original Message-----<BR><B>From:</B> Koivu, Lisa
[mailto:lkoivu_at_qode.com]<BR><B>Sent:</B> 23 August 2000
21:58<BR><B>To:</B> Multiple recipients of list
ORACLE-L<BR><B>Subject:</B> RE: Who and What is using the shared
pool.<BR><BR></DIV></FONT>
<P><FONT size=2>Thanks Philip for sending this to the list.
</FONT></P>
<P><FONT size=2>However now I see that executions in v$db_object_cache is
0 everywhere. Is there an easy way to join to v$sqlarea to
v$db_object_cache? I guess I was hoping to see if any heavily-used
objects were being reloaded frequently and are candidates for
pinning.</FONT></P>
<P><FONT size=2>Anyone?? Thanks</FONT> <BR><FONT size=2>Lisa</FONT>
<BR><FONT size=2>Ft. Lauderdale, FL, USA</FONT> <BR><FONT
size=2>*O*fficially *C*rabby and *P*eeved</FONT> </P>
<P><FONT size=2>-----Original Message-----</FONT> <BR><FONT size=2>From:
Philip West [<A
href="mailto:P.West_at_g-icap.com">mailto:P.West_at_g-icap.com</A>]</FONT>
<BR><FONT size=2>Sent: Monday, August 21, 2000 1:33 PM</FONT> <BR><FONT
size=2>To: Multiple recipients of list ORACLE-L</FONT> <BR><FONT
size=2>Subject: RE: Who and What is using the shared pool.</FONT> </P><BR>
<P><FONT size=2>Always keep to the shallow end of the shared pool.
There are things</FONT> <BR><FONT size=2>swimming around in the depths
that you do not want to meet!</FONT> </P>
<P><FONT size=2>Or, the problem is most likely shared pool
fragmentation rather than the</FONT> <BR><FONT size=2>sizing per se.
Fragmentation is a 'feature'. This is a big subject, which</FONT>
<BR><FONT size=2>I would recommend you read up on (good papers on metalink
on this subject.</FONT> <BR><FONT size=2>You do not tell us your db
version. Ways to improve the situation include</FONT> <BR><FONT
size=2>reserving a portion of the pool for larger objects. pinning
critical or</FONT> <BR><FONT size=2>frequently reloaded objects into the
pool. and, yes, increasing the size of</FONT> <BR><FONT size=2>the pool if
necessary.</FONT> </P>
<P><FONT size=2>Look at v$sgastat to see what is where in your sga.</FONT>
</P>
<P><FONT size=2>Try these (from the $AD_TOP/sql directory if you run
Applications)</FONT> </P>
<P><FONT size=2>select owner || '.' || name OBJECT</FONT> <BR><FONT
size=2> , type</FONT> <BR><FONT
size=2> ,
to_char(sharable_mem/1024,'9,999.9') "SPACE(K)"</FONT> <BR><FONT
size=2> , loads</FONT> <BR><FONT
size=2> , executions
execs</FONT> <BR><FONT size=2> ,
kept</FONT> <BR><FONT size=2>from v$db_object_cache</FONT> <BR><FONT
size=2>where type in ('FUNCTION','PACKAGE','PACKAGE
BODY','PROCEDURE')</FONT> <BR><FONT size=2> and owner not in
('SYS')</FONT> <BR><FONT size=2>order by owner, name</FONT> <BR><FONT
size=2>/</FONT> <BR><FONT size=2>select
to_char(sum(sharable_mem)/1024,'9,999,999.9') "TOTAL SPACE (K)"</FONT>
<BR><FONT size=2>from v$db_object_cache</FONT> <BR><FONT size=2>where type
in ('FUNCTION','PACKAGE','PACKAGE BODY','PROCEDURE')</FONT> <BR><FONT
size=2> and owner not in ('SYS')</FONT> <BR><FONT size=2>/</FONT>
</P><BR>
<P><FONT size=2>also look here:</FONT> <BR><FONT size=2>
</FONT><BR><FONT size=2> </FONT><BR><FONT size=2>
Bookmark Fixed font Go to End </FONT></P>
<P><FONT size=2>Doc ID: Note:61623.1 </FONT><BR><FONT
size=2>Type: BULLETIN </FONT><BR><FONT size=2>Status:
PUBLISHED </FONT><BR><FONT size=2> Content Type: TEXT/PLAIN
</FONT><BR><FONT size=2>Creation Date: 12-SEP-1997 </FONT><BR><FONT
size=2>Last Revision Date: 23-MAY-2000 </FONT><BR><FONT
size=2>Language: USAENG </FONT><BR><FONT size=2> </FONT> </P>
<P><FONT size=2>PURPOSE</FONT> <BR><FONT size=2> This document
discusses some of the common issues associated with the</FONT> <BR><FONT
size=2>shared </FONT><BR><FONT size=2> pool in Oracle7 and describes
how to diagnose and respond to these issues.</FONT> </P>
<P><FONT size=2>RELATED DOCUMENTS</FONT> <BR><FONT size=2>
[NOTE:1012049.6] TUNING LIBRARY CACHE LATCH CONTENTION</FONT>
</P><BR>
<P><FONT size=2>With Release 7.2 and 7.3, changes have been made to reduce
usage of shared </FONT><BR><FONT size=2>memory as well as per-user (UGA)
memory. Also, memory is not being</FONT> <BR><FONT size=2>allocated
</FONT><BR><FONT size=2>in large contiguous chunks, resulting in better
shared-pool utilization and </FONT><BR><FONT size=2>reduction in
fragmentation.</FONT> </P>
<P><FONT size=2>1) MEMORY FRAGMENTATION</FONT> </P>
<P><FONT size=2>The primary problem that occurs is that free memory in the
shared pool</FONT> <BR><FONT size=2>becomes </FONT><BR><FONT
size=2>fragmented into small pieces over time. Any attempt to
allocate a large</FONT> <BR><FONT size=2>piece </FONT><BR><FONT size=2>of
memory in the shared pool will cause large amount of objects in the</FONT>
<BR><FONT size=2>library</FONT> <BR><FONT size=2>cache to be flushed out
and may result in an ORA-04031 out of shared memory </FONT><BR><FONT
size=2>error.</FONT> </P>
<P><FONT size=2>A) DIAGNOSIS OF FRAGMENTATION</FONT> </P>
<P><FONT size=2>i) ORA-04031 ERROR</FONT> </P>
<P><FONT size=2>One way to diagnose that this is happening is to look for
ORA-04031 errors</FONT> <BR><FONT size=2>being returned from
applications. When an attempt is made to allocate a</FONT> <BR><FONT
size=2>large </FONT><BR><FONT size=2>contiguous piece of shared memory,
and not enough contiguous memory can be </FONT><BR><FONT size=2>created in
the shared pool, the database will signal this error.</FONT> </P>
<P><FONT size=2>Before this error is signalled, all objects in the shared
pool that are not</FONT> <BR><FONT size=2>currently in use will be flushed
from the shared pool, and their memory will</FONT> <BR><FONT
size=2>be</FONT> <BR><FONT size=2>freed and merged. This error only
occurs when there is still not a large </FONT><BR><FONT size=2>enough
contiguous piece of free memory after this happens. There may
be</FONT> <BR><FONT size=2>very </FONT><BR><FONT size=2>large amounts of
total free memory in the shared pool, but just not enough </FONT><BR><FONT
size=2>contiguous memory.</FONT> </P>
<P><FONT size=2>ii) INIT.ORA PARAMETER</FONT> </P>
<P><FONT size=2>An init.ora parameter can be set so that whenever an
ORA-04031 error is</FONT> <BR><FONT size=2>signalled a dump will occur
into a trace file. By looking for these trace </FONT><BR><FONT
size=2>files, the DBA can determine that these errors are occurring.
This is</FONT> <BR><FONT size=2>useful</FONT> <BR><FONT size=2>when
applications do not always report errors signalled by oracle, or if</FONT>
<BR><FONT size=2>users</FONT> <BR><FONT size=2>do not report the errors to
the DBAs. The parameter is the following:</FONT> </P>
<P><FONT size=2> event = "4031 trace name
errorstack"</FONT> </P>
<P><FONT size=2>If you are using 7.0.16 or higher you can use the
following:</FONT> </P>
<P><FONT size=2> event = "4031 trace name errorstack
level 4"</FONT> </P>
<P><FONT size=2>This will cause a dump of the Oracle state objects to
occur when this error</FONT> <BR><FONT size=2>is </FONT><BR><FONT
size=2>signalled. By looking in the dump for 'load=X' and then
looking up a few</FONT> <BR><FONT size=2>lines</FONT> <BR><FONT size=2>for
'name=' you can often tell whether an object was being loaded into the
</FONT><BR><FONT size=2>shared pool when this error occurred. If an
object was being loaded then it</FONT> <BR><FONT size=2>is</FONT>
<BR><FONT size=2>likely that this load is the cause of the problem and the
object should be </FONT><BR><FONT size=2>'kept' in the shared pool.
The object being loaded is the object printed</FONT> <BR><FONT
size=2>after</FONT> <BR><FONT size=2>the 'name='. Do not use the 'level 4'
option in versions before 7.0.16</FONT> <BR><FONT size=2>because</FONT>
<BR><FONT size=2>a bug existed that often caused the system to crash with
this option enabled</FONT> </P>
<P><FONT size=2>due to a latch level violation.</FONT> </P>
<P><FONT size=2>Prior to version 7.3, there were a handful of cases where
the RDBMS or</FONT> <BR><FONT size=2>PL/SQL</FONT> <BR><FONT size=2>would
attempt to allocate large pieces of contiguous memory. Most of this</FONT>
<BR><FONT size=2>has</FONT> <BR><FONT size=2>been fixed for 7.3. This
problem was especially acute when running MTS, when</FONT> </P>
<P><FONT size=2>the UGA would be located in the SGA. This should also be
fixed in 7.3 and</FONT> <BR><FONT size=2>using</FONT> <BR><FONT size=2>MTS
for a high OLTP scenario is recommended. As a result of all these</FONT>
<BR><FONT size=2>changes, </FONT><BR><FONT size=2>the ORA-04031 error
should be virtually eliminated. If an ORA-04031 error is</FONT> <BR><FONT
size=2>signalled, quite likely the shared pool is over 90% utilized and
the </FONT><BR><FONT size=2>alternative is to increase the shared pool.
The only known situation is</FONT> <BR><FONT size=2>PL/SQL</FONT>
<BR><FONT size=2>packages (like STANDARD) where the package contains a
very large number</FONT> <BR><FONT size=2>(over</FONT> <BR><FONT
size=2>400) procedure/function definitions. This still needs to be in
contiguous</FONT> <BR><FONT size=2>memory and may request memory chunks as
large as 15K. Packages like this</FONT> <BR><FONT size=2>should
</FONT><BR><FONT size=2>be the only ones that should be kept.</FONT> </P>
<P><FONT size=2>iii) X$KSMLRU</FONT> </P>
<P><FONT size=2>There is a fixed table called x$ksmlru
that tracks allocations in the </FONT><BR><FONT size=2>shared
pool that cause other objects in the shared pool to be aged
out.</FONT> <BR><FONT size=2>This</FONT> <BR><FONT size=2>fixed table can
be used to identify what is causing the large
allocation.</FONT> </P>
<P><FONT size=2>The columns of this fixed table are the following:</FONT>
</P>
<P><FONT size=2>KSMLRCOM - allocation comment that describes the type of
allocation.</FONT> </P>
<P><FONT size=2>If this comment is something like 'MPCODE' or 'PLSQL%'
then there is a large</FONT> </P>
<P><FONT size=2>PL/SQL object being loaded into the shared pool.
This PL/SQL object will</FONT> <BR><FONT size=2>need </FONT><BR><FONT
size=2>to be 'kept' in the shared pool.</FONT> </P>
<P><FONT size=2>If this comment is 'kgltbtab' then the allocation is for a
dependency table</FONT> <BR><FONT size=2>in </FONT><BR><FONT size=2>the
library cache. This is only a problem when several hundred users
are</FONT> <BR><FONT size=2>logged</FONT> <BR><FONT size=2>on using
distinct user ids. The solution in this case is to use fully</FONT>
<BR><FONT size=2>qualified</FONT> <BR><FONT size=2>names for all table
references.</FONT> </P>
<P><FONT size=2>If you are running MTS and the comment is something like
'Fixed UGA' then</FONT> <BR><FONT size=2>the </FONT><BR><FONT
size=2>problem is that the init.ora parameter 'open_cursors' is set too
high.</FONT> </P>
<P><FONT size=2>KSMLRSIZ - amount of contiguous memory being
allocated. Values over around</FONT> <BR><FONT size=2>5K
</FONT><BR><FONT size=2>start to be a problem, values over 10K are a
serious problem, and values</FONT> <BR><FONT size=2>over </FONT><BR><FONT
size=2>20K are very serious problems. Anything less then 5K should
not be a</FONT> <BR><FONT size=2>problem.</FONT> </P>
<P><FONT size=2>KSMLRNUM - number of objects that were flushed from the
shared pool in order</FONT> <BR><FONT size=2>allocate the memory.</FONT>
</P>
<P><FONT size=2>In release 7.1.3 or later, the following columns also
exist:</FONT> </P>
<P><FONT size=2>KSMLRHON - the name of the object being loaded into the
shared pool if the</FONT> <BR><FONT size=2>object is a PL/SQL object or a
cursor.</FONT> </P>
<P><FONT size=2>KSMLROHV - hash value of object being loaded</FONT> </P>
<P><FONT size=2>KSMLRSES - SADDR of the session that loaded the
object.</FONT> </P>
<P><FONT size=2>The advantage of X$KSMLRU is that it allows you to
identify problems with</FONT> <BR><FONT size=2>fragmentation that are
effecting performance, but that are not bad enough to</FONT> <BR><FONT
size=2>be</FONT> <BR><FONT size=2>causing ORA-04031 errors to be
signalled. If a lot of objects are being </FONT><BR><FONT
size=2>periodically flushed from the shared pool then this will cause
response time</FONT> </P>
<P><FONT size=2>problems and will likely cause library cache latch
contention problems when</FONT> <BR><FONT size=2>the</FONT> <BR><FONT
size=2>objects are reloaded into the shared pool. With version 7.2, the
library</FONT> <BR><FONT size=2>cache </FONT><BR><FONT size=2>latch
contention should be significantly reduced with the breaking up of
the</FONT> </P>
<P><FONT size=2>library cache pin latch into a configurable set of
symmetric library cache </FONT><BR><FONT size=2>latches.</FONT> </P>
<P><FONT size=2>One unusual thing about the x$ksmlru fixed table is that
the contents of the</FONT> </P>
<P><FONT size=2>fixed table are erased whenever someone selects from the
fixed table. This</FONT> <BR><FONT size=2>is </FONT><BR><FONT size=2>done
since the fixed table stores only the largest allocations that have
</FONT><BR><FONT size=2>occurred. The values are reset after being
selected so that subsequent</FONT> <BR><FONT size=2>large </FONT><BR><FONT
size=2>allocations can be noted even if they were not quite as large as
others that</FONT> </P>
<P><FONT size=2>occurred previously. Because of this resetting, the
output of selecting</FONT> <BR><FONT size=2>from </FONT><BR><FONT
size=2>this table should be carefully noted since it cannot be reselected
if it is </FONT><BR><FONT size=2>forgotten. Also you should take
care that there are not multiple people on</FONT> <BR><FONT
size=2>one</FONT> <BR><FONT size=2>database that select from this table
because only one of them will select</FONT> <BR><FONT size=2>the
</FONT><BR><FONT size=2>real data.</FONT> </P>
<P><FONT size=2>To monitor this fixed table just run the following:</FONT>
</P>
<P><FONT size=2> select * from x$ksmlru where ksmlrsiz
> 5000;</FONT> </P>
<P><FONT size=2>iv) MTS</FONT> </P>
<P><FONT size=2>Oracle users using SQL*Net V2 can connect to the database
using dedicated</FONT> <BR><FONT size=2>servers, or multiple clients can
use a pool of shared (or MTS) servers. The</FONT> <BR><FONT size=2>biggest
memory implication of this mode is that the session memory (also</FONT>
<BR><FONT size=2>known</FONT> <BR><FONT size=2>as the UGA) for every
session needs to be accessible to every MTS server.</FONT> <BR><FONT
size=2>This</FONT> <BR><FONT size=2>implies that the logical UGA comes out
of the physical SGA (or the shared</FONT> <BR><FONT size=2>pool) instead
of the PGA (process memory).</FONT> </P>
<P><FONT size=2>In versions prior to 7.3, there were a few components in
the UGA that would</FONT> <BR><FONT size=2>request large contiguous chunks
of memory, contributing to fragmentation of</FONT> <BR><FONT size=2>the
shared pool if using MTS. If the system had been up for a while,
users</FONT> <BR><FONT size=2>would have failures when attempting to
connect or executing sql. Starting</FONT> <BR><FONT size=2>with</FONT>
<BR><FONT size=2>7.3, all these allocations have been segmented such that
the average size of</FONT> <BR><FONT size=2>memory chunks allocated to the
UGA should be about 5K.</FONT> </P>
<P><FONT size=2>B) CORRECTION OF FRAGMENTATION</FONT> </P>
<P><FONT size=2>i) KEEPING OBJECTS</FONT> </P>
<P><FONT size=2>The primary source of problems is large PL/SQL objects.
The means of</FONT> <BR><FONT size=2>correcting</FONT> <BR><FONT
size=2>these errors is to 'keep' large PL/SQL object in the shared pool at
startup </FONT><BR><FONT size=2>time. This will load the objects into the
shared pool and will make sure</FONT> <BR><FONT size=2>that
</FONT><BR><FONT size=2>the objects are never aged out of the shared pool.
If the objects are never </FONT><BR><FONT size=2>aged out then there will
not be a problem with trying to load them and not </FONT><BR><FONT
size=2>having enough memory.</FONT> </P>
<P><FONT size=2>Objects are 'kept' in the shared pool using the
dbms_shared_pool package</FONT> <BR><FONT size=2>that </FONT><BR><FONT
size=2>is defined in the dbmspool.sql file. For example:</FONT> </P>
<P><FONT size=2> execute
dbms_shared_pool.keep('SYS.STANDARD');</FONT> </P>
<P><FONT size=2>All large packages that are shipped should be 'kept' if
the customer uses</FONT> <BR><FONT size=2>PL/SQL. This includes
'STANDARD', 'DBMS_STANDARD', and 'DIUTIL'. With 7.3,</FONT> <BR><FONT
size=2>the</FONT> <BR><FONT size=2>only package left in this list is
'STANDARD'.</FONT> </P>
<P><FONT size=2>All large customer packages should also be marked
'kept'.</FONT> </P>
<P><FONT size=2>To mark all packages in the system 'kept' execute the
following:</FONT> </P>
<P><FONT size=2>declare</FONT> <BR><FONT size=2> own
varchar2(100);</FONT> <BR><FONT size=2> nam varchar2(100);</FONT>
<BR><FONT size=2> cursor pkgs is</FONT> <BR><FONT
size=2> select owner, object_name</FONT> <BR><FONT
size=2> from dba_objects</FONT> <BR><FONT
size=2> where object_type =
'PACKAGE';</FONT> <BR><FONT size=2>begin</FONT> <BR><FONT size=2>
open pkgs;</FONT> <BR><FONT size=2> loop</FONT> <BR><FONT
size=2> fetch pkgs into own, nam;</FONT> <BR><FONT
size=2> exit when pkgs%notfound;</FONT> <BR><FONT
size=2> dbms_shared_pool.keep(own || '.' || nam,
'P');</FONT> <BR><FONT size=2> end loop;</FONT> <BR><FONT
size=2>end;</FONT> </P>
<P><FONT size=2>The dbms_shared_pool package was introduced in 7.0 and has
evolved over the </FONT><BR><FONT size=2>versions. Until 7.1.5, 'keep'
could only be used for packages. Starting with</FONT> </P>
<P><FONT size=2>7.1.6, this was extended to standalone procedures, cursors
as well as</FONT> <BR><FONT size=2>triggers.</FONT> <BR><FONT size=2>For
detailed usage instructions, see the dbmspool.sql file. So, prior
to</FONT> <BR><FONT size=2>this </FONT><BR><FONT size=2>version, if you
have large procedures or large anonymous blocks, then these
</FONT><BR><FONT size=2>will need to be put into packages and marked kept.
With 7.3, most packages</FONT> <BR><FONT size=2>do </FONT><BR><FONT
size=2>not need to be kept any longer since PL/SQL no longer requires
large amounts</FONT> <BR><FONT size=2>of</FONT> <BR><FONT
size=2>contiguous memory to load packages/procedures in memory.</FONT>
</P>
<P><FONT size=2>You can determine what large stored objects are in the
shared pool by</FONT> <BR><FONT size=2>selecting</FONT> <BR><FONT
size=2>from the v$db_object_cache fixed view. This will also tell
you which</FONT> <BR><FONT size=2>objects </FONT><BR><FONT size=2>have
been marked kept. This can be done with the following query:</FONT>
</P>
<P><FONT size=2> select * from v$db_object_cache where
sharable_mem > 10000;</FONT> </P>
<P><FONT size=2>Note that this query will not catch PL/SQ: objects that
are only rarely used</FONT> </P>
<P><FONT size=2>and therefore the PL/SQL object is not currently loaded in
the shared pool.</FONT> </P>
<P><FONT size=2>To determine what large PL/SQL objects are currently
loaded in the shared</FONT> <BR><FONT size=2>pool </FONT><BR><FONT
size=2>and are not marked 'kept' and therefore may cause a problem,
execute the</FONT> <BR><FONT size=2>following:</FONT> </P>
<P><FONT size=2> select name, sharable_mem</FONT>
<BR><FONT size=2> from v$db_object_cache</FONT>
<BR><FONT size=2> where sharable_mem > 10000</FONT>
<BR><FONT size=2> and (type = 'PACKAGE' or type =
'PACKAGE BODY' or type = 'FUNCTION'</FONT> <BR><FONT
size=2> or type =
'PROCEDURE')</FONT> <BR><FONT size=2> and kept =
'NO';</FONT> </P>
<P><FONT size=2>Another approach to the above is to use the
dbms_shared_pool.sizes</FONT> <BR><FONT size=2>procedure.</FONT> <BR><FONT
size=2>To use this in SQLDBA:</FONT> </P>
<P><FONT size=2> set serveroutput on;</FONT> <BR><FONT
size=2> execute dbms_shared_pool.sizes(10);</FONT> </P>
<P><FONT size=2>This should show you the names of all the objects in the
shared pool that</FONT> <BR><FONT size=2>take</FONT> <BR><FONT size=2>more
that 10K of memory as well as if they are marked kept or not. For
SQL</FONT> <BR><FONT size=2>statements, if there are multiple versions of
a query (usually a bug if the</FONT> <BR><FONT size=2>count is more than
3), they will also be indicated in parenthesis. Use the</FONT> <BR><FONT
size=2>following query to check for problems:</FONT> </P>
<P><FONT size=2> select sql_text, loaded_versions, version_count,
sharable_mem</FONT> <BR><FONT size=2> from v$sqlarea where
loaded_versions > 3</FONT> <BR><FONT size=2> order by
sharable_mem;</FONT> </P>
<P><FONT size=2>In Oracle7.3 onwards the best candidates for keeping can
be seen by querying</FONT> </P>
<P><FONT size=2>the table X$KSMSP to see if there are any chunks in the
shared-pool that</FONT> <BR><FONT size=2>have </FONT><BR><FONT size=2>the
KSMCHSIZ larger than 5K and KSMCHCOM like '%PL/SQL%'. If so then one
can</FONT> </P>
<P><FONT size=2>identify the object name and owner of this chunk using the
following SQL:</FONT> </P>
<P><FONT size=2> select distinct</FONT> <BR><FONT size=2>
decode(kglobtyp,0,'CURSOR',7,'PROCEDURE',8,'FUNCTION',9,'PACKAGE',</FONT>
<BR><FONT
size=2>
11,'PACKAGE BODY',12,'TRIGGER',13,'TYPE',14,'TYPE</FONT> <BR><FONT
size=2>BODY','OTHER')</FONT> <BR><FONT size=2> ||' -
'||kglnaown||'.'||kglnaobj "Eligible PL/SQL objects"</FONT> <BR><FONT
size=2> from x$kglob</FONT> <BR><FONT size=2> where kglobhd4
in</FONT> <BR><FONT size=2> (select ksmchpar from
x$ksmsp</FONT> <BR><FONT size=2> where
ksmchcom='PL/SQL MPCODE' and ksmchsiz>5120)</FONT> </P>
<P><FONT size=2>If you are 'keeping' PL/SQL objects today and migrate to
7.3 or higher there</FONT> <BR><FONT size=2>is</FONT> <BR><FONT size=2>no
need to re-assess the list of objects that you are keeping.</FONT> </P>
<P><FONT size=2>ii) USE BIND VARIABLES</FONT> </P>
<P><FONT size=2>One of the best things that can be done to reduce the
amount of</FONT> <BR><FONT size=2>fragmentation</FONT> <BR><FONT size=2>is
to reduce or eliminate the number of sql statements in the shared
pool</FONT> <BR><FONT size=2>that</FONT> <BR><FONT size=2>are duplicates
of each other except for a constant that is embedded in the</FONT>
<BR><FONT size=2>statement. The statements should be replaced with
one statement that uses</FONT> <BR><FONT size=2>a bind variable instead of
a constant.</FONT> </P>
<P><FONT size=2>For example:</FONT> </P>
<P><FONT size=2> select * from emp where empno=1;</FONT> <BR><FONT
size=2> select * from emp where empno=2;</FONT> <BR><FONT
size=2> select * from emp where empno=3;</FONT> </P>
<P><FONT size=2>Should all be replaced with:</FONT> </P>
<P><FONT size=2> select * from emp where empno=:1;</FONT> </P>
<P><FONT size=2>You can identify statements that potentially fall into
this class with a</FONT> <BR><FONT size=2>query </FONT><BR><FONT
size=2>like the following:</FONT> </P>
<P><FONT size=2> select substr(sql_text, 1, 30) sql, count(*)
copies</FONT> <BR><FONT size=2> from v$sqlarea</FONT>
<BR><FONT size=2> group by substr(sql_text, 1, 30)</FONT>
<BR><FONT size=2> having count(*) > 3;</FONT> </P>
<P><FONT size=2>iii) MAX BIND SIZE</FONT> </P>
<P><FONT size=2>It is possible for a SQL statement to not be shared
because the max bind </FONT><BR><FONT size=2>variable lengths of the bind
variables in the statement do not match. This</FONT> <BR><FONT
size=2>is </FONT><BR><FONT size=2>automatically taken care of for
precompiler programs and forms programs, but</FONT> </P>
<P><FONT size=2>could be a problem for programs that directly use
OCI. The bind call in OCI</FONT> </P>
<P><FONT size=2>takes two arguments, one is the max length of the value,
and the other is a </FONT><BR><FONT size=2>pointer to the actual
length. If the current length is always passed in as</FONT>
<BR><FONT size=2>the</FONT> <BR><FONT size=2>max length instead of the max
possible length for the variable, then this</FONT> <BR><FONT size=2>could
</FONT><BR><FONT size=2>cause the SQL statement not to be shared.</FONT>
</P>
<P><FONT size=2>To identify statements that might potentially have this
problem execute the </FONT><BR><FONT size=2>following statement:</FONT>
</P>
<P><FONT size=2> select sql_text, version_count from
v$sqlarea where version_count > 5;</FONT> </P>
<P><FONT size=2>Starting with 7.1.6 this should no longer be an issue as
the server can </FONT><BR><FONT size=2>graduate bind buffers even when the
user's max bind lengths are jumping up</FONT> <BR><FONT size=2>or</FONT>
<BR><FONT size=2>down and continue to share cursors that are built for
larger buffer lengths</FONT> <BR><FONT size=2>and flush the smaller sql
compilation from the shared pool.</FONT> </P>
<P><FONT size=2>iv) ELIMINATING LARGE ANONYMOUS PL/SQL</FONT> </P>
<P><FONT size=2>Large anonymous PL/SQL blocks should be turned into small
anonymous PL/SQL</FONT> <BR><FONT size=2>blocks that call packaged
functions. The packages should be 'kept' in</FONT> <BR><FONT
size=2>memory. </FONT><BR><FONT size=2>For version earlier that 7.3, this
includes anonymous PL/SQL blocks that are</FONT> </P>
<P><FONT size=2>used for trigger definitions. With 7.3, triggers are
compiled and stored to </FONT><BR><FONT size=2>disk like standalone
procedures and should be treated as such. Large</FONT> <BR><FONT
size=2>anonymous </FONT><BR><FONT size=2>blocks can be identified with the
following query:</FONT> </P>
<P><FONT size=2> select sql_text from v$sqlarea</FONT> <BR><FONT
size=2> where
command_type=47 -- command type for
anonymous block</FONT> <BR><FONT size=2> and
length(sql_text) > 500;</FONT> </P>
<P><FONT size=2>Note that this query will not catch PL/SQL blocks that are
only rarely used</FONT> <BR><FONT size=2>and</FONT> <BR><FONT
size=2>therefore the PL/SQL block is not currently loaded in the shared
pool.</FONT> </P>
<P><FONT size=2>Another option that can be used when an anonymous block
cannot be turned</FONT> <BR><FONT size=2>into</FONT> <BR><FONT size=2>a
package is to mark the anonymous block with some string so that it can
be</FONT> <BR><FONT size=2>identified in v$sqlarea and marked
'kept'.</FONT> </P>
<P><FONT size=2>For example, instead of using:</FONT> <BR><FONT
size=2> declare x number; begin x := 5; end;;</FONT> </P>
<P><FONT size=2>you can use:</FONT> <BR><FONT size=2> declare /*
KEEP_ME */ x number; begin x := 5; end;</FONT> </P>
<P><FONT size=2>You can then use the following procedure to select these
statements out of</FONT> <BR><FONT size=2>the </FONT><BR><FONT
size=2>shared pool and mark them 'kept' using the dbms_shared_pool.keep
package.</FONT> </P>
<P><FONT size=2>declare</FONT> <BR><FONT size=2> /* DONT_KEEP_ME
*/</FONT> <BR><FONT size=2> addr varchar2(10);</FONT> <BR><FONT
size=2> hash number;</FONT> <BR><FONT size=2> cursor anon
is</FONT> <BR><FONT size=2> select address, hash_value</FONT>
<BR><FONT size=2> from v$sqlarea</FONT> <BR><FONT
size=2> where command_type =
47
-- command type for anonymous</FONT> <BR><FONT size=2>block</FONT>
<BR><FONT size=2> and sql_text like '%
KEEP_ME %'</FONT> <BR><FONT size=2> and
sql_text not like '%DONT_KEEP_ME%';</FONT> <BR><FONT size=2>begin</FONT>
<BR><FONT size=2> open anon;</FONT> <BR><FONT size=2>
loop</FONT> <BR><FONT size=2> fetch anon into addr,
hash;</FONT> <BR><FONT size=2> exit when
anon%notfound;</FONT> <BR><FONT size=2>
dbms_shared_pool.keep(addr || ',' || to_char(hash), 'C');</FONT> <BR><FONT
size=2> end loop;</FONT> <BR><FONT size=2>end;</FONT> </P>
<P><FONT size=2>v) REDUCING USAGE</FONT> </P>
<P><FONT size=2>Another way to reducing fragmentation is to reduce
consumption. This is of</FONT> <BR><FONT size=2>special importance when
using MTS, when every user's session memory is in</FONT> <BR><FONT
size=2>the</FONT> <BR><FONT size=2>shared pool and the impact is
multiplied by the total concurrent users.</FONT> </P>
<P><FONT size=2>Insert, update, delete and anonymous blocks complete the
execution in one</FONT> <BR><FONT size=2>round </FONT><BR><FONT
size=2>trip. All the memory that is allocated on the server for the
execute comes</FONT> <BR><FONT size=2>from</FONT> <BR><FONT size=2>the PGA
and is freed before the call returns to the user. But in the case
of</FONT> </P>
<P><FONT size=2>selects, memory required to execute the statement - which
could be large if</FONT> <BR><FONT size=2>a </FONT><BR><FONT size=2>sort
was involved - is not freed until the end-of-fetch is reached or
the</FONT> <BR><FONT size=2>query </FONT><BR><FONT size=2>is cancelled. In
these situations using the OCI features to do an exact</FONT> <BR><FONT
size=2>fetch </FONT><BR><FONT size=2>and cancel helps free memory back to
the pool.</FONT> </P>
<P><FONT size=2>If the application logic has been embedded into server
side PL/SQL, a large</FONT> <BR><FONT size=2>number of cursors may be
getting cached on the server for every user. Though</FONT> <BR><FONT
size=2>this results in reduced latch contention and faster response, it
does use</FONT> <BR><FONT size=2>more</FONT> <BR><FONT size=2>memory in
the UGA. Setting the close_cached_open_cursors init.ora to TRUE</FONT>
<BR><FONT size=2>closes the PL/SQL cached cursors on the server, freeing
the memory.</FONT> </P>
<P><FONT
size=2>*************************************************************************</FONT>
</P>
<P><FONT size=2>2) COMMON FALLACIES</FONT> </P>
<P><FONT size=2>There are a number of common fallacies about the shared
pool that are often</FONT> <BR><FONT size=2>stated as fact.</FONT> </P>
<P><FONT size=2>A) FREE MEMORY</FONT> </P>
<P><FONT size=2>One fallacy is that the amount of 'free memory' reported
in v$sgastat needs</FONT> <BR><FONT size=2>to </FONT><BR><FONT size=2>be
kept high. This is incorrect. The free memory reported in this
table is</FONT> <BR><FONT size=2>not</FONT> <BR><FONT size=2>like the free
memory reported by operating system statistics. Since the</FONT>
<BR><FONT size=2>shared</FONT> <BR><FONT size=2>pool acts as a cache,
nothing will ever be aged out of the shared pool until</FONT> <BR><FONT
size=2>all</FONT> <BR><FONT size=2>the free memory has been used up. This
is entirely normal.</FONT> </P>
<P><FONT size=2>Free memory is more properly thought of as 'wasted
memory'. You would</FONT> <BR><FONT size=2>rather</FONT> <BR><FONT
size=2>see this value be low than very high. In fact, a high value
of free memory</FONT> <BR><FONT size=2>is </FONT><BR><FONT
size=2>sometimes a symptom that a lot of objects have been aged out of the
shared</FONT> <BR><FONT size=2>pool</FONT> <BR><FONT size=2>and therefore
the system is experiencing fragmentation problems.</FONT> </P>
<P><FONT size=2>B) FLUSH SHARED POOL</FONT> </P>
<P><FONT size=2>Some people think that frequently executing 'alter system
flush shared_pool'</FONT> <BR><FONT size=2>improves the performance of the
system and decreases the amount of </FONT><BR><FONT
size=2>fragmentation. This is incorrect. Executing this
statement causes a big</FONT> <BR><FONT size=2>spike</FONT> <BR><FONT
size=2>in performance and does nothing to improve fragmentation.</FONT>
</P>
<P><FONT size=2>The only time when it might be useful to run this
statement is between</FONT> <BR><FONT size=2>shifts of</FONT> <BR><FONT
size=2>users so that the objects that are relevant to the last shift of
users can</FONT> <BR><FONT size=2>be </FONT><BR><FONT size=2>flushed out
before the next shift of users starts to use the system. This</FONT>
<BR><FONT size=2>is </FONT><BR><FONT size=2>almost never needed
though.</FONT> </P>
<P><FONT
size=2>*************************************************************************</FONT>
</P>
<P><FONT size=2>3) SIZING OF SHARED POOL</FONT> </P>
<P><FONT size=2>One very difficult judgement that needs to be make in
Oracle7 is to</FONT> <BR><FONT size=2>determine</FONT> <BR><FONT
size=2>the proper size of the shared pool. The following provides
some guidelines</FONT> <BR><FONT size=2>for</FONT> <BR><FONT
size=2>this. It should be emphasized that these are just guidelines,
there are no </FONT><BR><FONT size=2>hard and fast rules here and
experimentation will be needed to determine a</FONT> <BR><FONT
size=2>good</FONT> <BR><FONT size=2>value.</FONT> </P>
<P><FONT size=2>The shared pool size is highly application
dependent. To determine the</FONT> <BR><FONT size=2>shared
</FONT><BR><FONT size=2>pool size that will be needed for a production
system it is generally</FONT> <BR><FONT size=2>necessary</FONT> <BR><FONT
size=2>to first develop the application and run it on a test system and
take some </FONT><BR><FONT size=2>measurements. The test system
should be run with a very large value for the</FONT> </P>
<P><FONT size=2>shared pool size to make the measurements
meaningful.</FONT> </P>
<P><FONT size=2>A) OBJECTS STORED IN THE DATABASE</FONT> </P>
<P><FONT size=2>The amount of shared pool that needs to be allocated for
objects that are </FONT><BR><FONT size=2>stored in the database like
packages and views is easy to measure. You can </FONT><BR><FONT
size=2>just measure their size directly with the following
statement:</FONT> </P>
<P><FONT size=2> select sum(sharable_mem) from
v$db_object_cache;</FONT> </P>
<P><FONT size=2>This is especially effective because all large pl/sql
object should be</FONT> <BR><FONT size=2>'kept'</FONT> <BR><FONT size=2>in
the shared pool at all times.</FONT> </P>
<P><FONT size=2>B) SQL</FONT> </P>
<P><FONT size=2>The amount of memory needed to store SQL statements in the
shared pool is</FONT> <BR><FONT size=2>more </FONT><BR><FONT
size=2>difficult to measure because of the needs of dynamic SQL. If
an application</FONT> </P>
<P><FONT size=2>has no dynamic SQL then the amount of memory can simply be
measured after</FONT> <BR><FONT size=2>the </FONT><BR><FONT
size=2>application has run for a while by just selecting it out of the
shared pool</FONT> <BR><FONT size=2>as </FONT><BR><FONT
size=2>follows:</FONT> </P>
<P><FONT size=2> select sum(sharable_mem) from
v$sqlarea;</FONT> </P>
<P><FONT size=2>If the application has a moderate or large amount of
dynamic SQL like most </FONT><BR><FONT size=2>applications do, then a
certain amount of memory will be needed for the</FONT> <BR><FONT
size=2>shared </FONT><BR><FONT size=2>SQL, plus more for the dynamic SQL,
and more so that the dynamic SQL does</FONT> <BR><FONT size=2>not
</FONT><BR><FONT size=2>age the shared SQL out of the shared pool.</FONT>
</P>
<P><FONT size=2>The amount of memory for the shared SQL can be
approximated by the</FONT> <BR><FONT size=2>following:</FONT> </P>
<P><FONT size=2> select sum(sharable_mem) from v$sqlarea
where executions > 5;</FONT> </P>
<P><FONT size=2>The remaining memory in v$sqlarea is for dynamic SQL
Some shared pool will</FONT> <BR><FONT size=2>need to be budgeted for this
also, but there are few rules here.</FONT> </P>
<P><FONT size=2>C) PER-USER PER-CURSOR MEMORY</FONT> </P>
<P><FONT size=2>You will need to allow around 250 bytes of memory in the
shared pool per</FONT> <BR><FONT size=2>concurrent user for each open
cursor that the user has whether the cursor is</FONT> </P>
<P><FONT size=2>shared or not. During the peak usage time of the
production system, you can</FONT> </P>
<P><FONT size=2>measure this as follows:</FONT> </P>
<P><FONT size=2> select sum(250 * users_opening) from
v$sqlarea;</FONT> </P>
<P><FONT size=2>In a test system you can measure it by selecting the
number of open cursors</FONT> <BR><FONT size=2>for a test user and
multiplying by the total number of users:</FONT> </P>
<P><FONT size=2> select 250 * value bytes_per_user</FONT> <BR><FONT
size=2> from v$sesstat s, v$statname n</FONT> <BR><FONT
size=2> where s.statistic# = n.statistic#</FONT> <BR><FONT
size=2> and n.name = 'opened cursors
current'</FONT> <BR><FONT size=2> and s.sid
= 23; -- replace 23 with session id of user
being</FONT> <BR><FONT size=2>measured</FONT> </P>
<P><FONT size=2>The per-user per-cursor memory is one of the classes of
memory that shows up</FONT> <BR><FONT size=2>as</FONT> <BR><FONT
size=2>'library cache' in v$sgastat.</FONT> </P>
<P><FONT size=2>D) MTS</FONT> </P>
<P><FONT size=2>If you are using multi-threaded server, then you will need
to allow enough</FONT> <BR><FONT size=2>memory for all the shared server
users to put their session memory in the </FONT><BR><FONT size=2>shared
pool. This can be measured for one user with the following
query:</FONT> </P>
<P><FONT size=2> select value sess_mem</FONT> <BR><FONT
size=2> from v$sesstat s, v$statname n</FONT> <BR><FONT
size=2> where s.statistic# = n.statistic#</FONT> <BR><FONT
size=2> and n.name = 'session uga memory'</FONT>
<BR><FONT size=2> and s.sid =
23; -- replace 23 with session id of user being</FONT>
<BR><FONT size=2>measured</FONT> </P>
<P><FONT size=2>A more conservative value to use is the maximum session
memory that was</FONT> <BR><FONT size=2>ever allocated by the user:</FONT>
</P>
<P><FONT size=2> select value sess_max_mem</FONT> <BR><FONT
size=2> from v$sesstat s, v$statname n</FONT> <BR><FONT
size=2> where s.statistic# = n.statistic#</FONT> <BR><FONT
size=2> and n.name = 'session uga memory
max'</FONT> <BR><FONT size=2> and s.sid
= 23; -- replace 23 with session id of user
being</FONT> <BR><FONT size=2>measured</FONT> </P>
<P><FONT size=2>To select this value for all the currently logged on users
the following</FONT> <BR><FONT size=2>query</FONT> <BR><FONT size=2>can be
used:</FONT> </P>
<P><FONT size=2> select sum(value) all_sess_mem</FONT> <BR><FONT
size=2> from v$sesstat s, v$statname n</FONT> <BR><FONT
size=2> where s.statistic# = n.statistic#</FONT> <BR><FONT
size=2> and n.name = 'session uga memory
max';</FONT> </P>
<P><FONT size=2>E) OVERHEAD</FONT> </P>
<P><FONT size=2>You will need to add a minimum of 30% overhead to the
values calculated</FONT> <BR><FONT size=2>above </FONT><BR><FONT size=2>to
allow for unexpected and unmeasured usage of the shared pool.</FONT> </P>
<P><FONT
size=2>*************************************************************************</FONT>
</P>
<P><FONT size=2>4) FINAL COMMENTS</FONT> </P>
<P><FONT size=2>The most important point that needs to be understood by
everyone using</FONT> <BR><FONT size=2>Oracle7 </FONT><BR><FONT size=2>and
PL/SQL (prior to release 7.3) is that all large PL/SQL objects must
be</FONT> <BR><FONT size=2>made </FONT><BR><FONT size=2>into packages and
those packages must be kept in the shared pool. This point</FONT> </P>
<P><FONT size=2>cannot be over emphasized. Many customers,
especially those running a lot</FONT> <BR><FONT size=2>of </FONT><BR><FONT
size=2>users, have had terrible performance problems that were completely
cleared</FONT> <BR><FONT size=2>up </FONT><BR><FONT size=2>by doing
this.</FONT> </P><BR>
<P><FONT
size=2>
APPENDIX I: Reserved Shared Pool</FONT> <BR><FONT
size=2>
=================================</FONT> </P>
<P><FONT size=2>1. RESERVED SPACE FROM THE SHARED POOL</FONT> <BR><FONT
size=2>======================================</FONT> <BR><FONT size=2>On
busy systems, the RDBMS may have difficulty finding a contiguous piece
of</FONT> </P>
<P><FONT size=2>memory to satisfy a large request for memory.
Because the RDBMS will search</FONT> </P>
<P><FONT size=2>for and free currently unused memory, the search for this
large piece of</FONT> <BR><FONT size=2>memory </FONT><BR><FONT size=2>may
disrupt the behavior of the share pool, leading to more
fragmentation</FONT> <BR><FONT size=2>and </FONT><BR><FONT size=2>poor
performance.</FONT> </P>
<P><FONT size=2>RDBMS 7.1.5 allows DBAs to reserve memory within the
shared pool to satisfy </FONT><BR><FONT size=2>these large allocations
during RDBMS operations such as PL/SQL compilation</FONT> <BR><FONT
size=2>and </FONT><BR><FONT size=2>trigger compilation. Smaller
objects will not fragment the reserved list, </FONT><BR><FONT
size=2>helping to ensure the reserved list will have large contiguous
chunks of</FONT> <BR><FONT size=2>memory.</FONT> <BR><FONT size=2>Once the
memory allocated from the reserved list is freed, it returns to the</FONT>
</P>
<P><FONT size=2>reserved list.</FONT> </P>
<P><FONT size=2>The size of the reserved list, as well as the minimum size
of the objects</FONT> <BR><FONT size=2>that </FONT><BR><FONT size=2>can be
allocated from the reserved list are controlled via init.ora</FONT>
<BR><FONT size=2>parameters:</FONT> <BR><FONT
size=2>shared_pool_reserved_size and
shared_pool_reserved_min_alloc.</FONT> </P>
<P><FONT size=2>1.1 shared_pool_reserved_size</FONT> <BR><FONT
size=2>------------------------------</FONT> <BR><FONT size=2>The init.ora
parameter shared_pool_reserved_size controls the amount of</FONT>
<BR><FONT size=2>shared_pool_size reserved for large allocations. In
order to create a</FONT> <BR><FONT size=2>reserved</FONT> <BR><FONT
size=2>list, shared_pool_reserved_size must be greater than
</FONT><BR><FONT size=2>shared_pool_reserved_min_alloc.</FONT> </P>
<P><FONT size=2> units : bytes</FONT> <BR><FONT
size=2> default: 0 (no reserved list)</FONT> <BR><FONT
size=2> minimum: > shared_pool_reserved_min_alloc</FONT>
<BR><FONT size=2> maximum: 1/2 shared_pool_size</FONT> </P>
<P><FONT size=2>1.2 shared_pool_reserved_min_alloc</FONT> <BR><FONT
size=2>-----------------------------------</FONT> <BR><FONT size=2>The
init.ora parameter shared_pool_reserved_min_alloc controls
allocation</FONT> <BR><FONT size=2>for </FONT><BR><FONT size=2>the
reserved memory. Only allocations larger than </FONT><BR><FONT
size=2>shared_pool_reserved_min_alloc are allowed to allocate space from
the</FONT> <BR><FONT size=2>reserved </FONT><BR><FONT size=2>list if a
chunk of memory of sufficient size is not found on the shared</FONT>
<BR><FONT size=2>pool's </FONT><BR><FONT size=2>free lists.</FONT> </P>
<P><FONT size=2> units : bytes</FONT> <BR><FONT
size=2> default: 5000</FONT> <BR><FONT size=2>
minimum: 5000</FONT> <BR><FONT size=2> maximum: <
shared_pool_reserved_size</FONT> </P>
<P><FONT size=2>The default value for shared_pool_reserved_min_alloc
should be adequate for </FONT><BR><FONT size=2>almost all systems.</FONT>
</P>
<P><FONT size=2>2. CONTROLLING SPACE RECLAMATION OF THE SHARED
POOL</FONT> <BR><FONT
size=2>====================================================</FONT>
<BR><FONT size=2>RDBMS 7.1.5 also provides a new procedure,
aborted_request_threshold, in</FONT> <BR><FONT size=2>package</FONT>
<BR><FONT size=2>dbms_shared_pool, which allows users to set the limit on
the size of</FONT> <BR><FONT size=2>allocations</FONT> <BR><FONT
size=2>allowed to flush the shared pool if the free lists cannot satisfy
the</FONT> <BR><FONT size=2>request </FONT><BR><FONT size=2>size.</FONT>
</P>
<P><FONT size=2>Before the RDBMS signals the ORA-04031 error, it
incrementally flushes</FONT> <BR><FONT size=2>unused </FONT><BR><FONT
size=2>objects from the shared pool until there is sufficient memory to
satisfy the</FONT> </P>
<P><FONT size=2>allocation request. In most cases, incrementally
flushing objects from the </FONT><BR><FONT size=2>shared pool frees enough
memory for the allocation to complete succesfully.</FONT> <BR><FONT
size=2>If </FONT><BR><FONT size=2>the RDBMS signals an ORA-04031 error, it
has flushed all objects currently</FONT> <BR><FONT size=2>not
</FONT><BR><FONT size=2>in use on the system without finding a large
enough piece of contiguous</FONT> <BR><FONT size=2>memory.</FONT> </P>
<P><FONT size=2>On a busy system, the larger the space allocation, the
more likely the RDBMS</FONT> </P>
<P><FONT size=2>will signal the ORA-04031 error. Flushing all
objects, however, will impact</FONT> </P>
<P><FONT size=2>other users on the system, possibly causing a degradation
in performance.</FONT> </P>
<P><FONT size=2>The aborted_request_threshold procedure allows the DBA to
localize the</FONT> <BR><FONT size=2>impact </FONT><BR><FONT size=2>the
ORA-04031 error to the process that couldn't allocate memory. The</FONT>
<BR><FONT size=2>procedure</FONT> <BR><FONT size=2>takes a numeric value
between 5000 and 2147483647, representing the size, in</FONT> </P>
<P><FONT size=2>bytes, of the threshold.</FONT> </P>
<P><FONT size=2>3. NEW FIXED VIEW V$SHARED_POOL_RESERVED</FONT>
<BR><FONT size=2>=========================================</FONT>
<BR><FONT size=2>RDBMS 7.1.5 has a new fixed view to help tune the
reserved pool and space</FONT> <BR><FONT size=2>within</FONT> <BR><FONT
size=2>the shared pool. The name of the new fixed view is
V$SHARED_POOL_RESERVED</FONT> <BR><FONT size=2>and </FONT><BR><FONT
size=2>has the following columns:</FONT> </P>
<P><FONT
size=2>Name
Null? Type</FONT> <BR><FONT
size=2>------------------------------- -------- --------------</FONT>
<BR><FONT
size=2>FREE_SPACE
NUMBER</FONT> <BR><FONT
size=2>AVG_FREE_SIZE
NUMBER</FONT> <BR><FONT
size=2>FREE_COUNT
NUMBER</FONT> <BR><FONT
size=2>MAX_FREE_SIZE
NUMBER</FONT> <BR><FONT
size=2>USED_SPACE
NUMBER</FONT> <BR><FONT
size=2>AVG_USED_SIZE
NUMBER</FONT> <BR><FONT
size=2>USED_COUNT
NUMBER</FONT> <BR><FONT
size=2>MAX_USED_SIZE
NUMBER</FONT> <BR><FONT
size=2>REQUESTS
NUMBER</FONT> <BR><FONT
size=2>REQUEST_MISSES
NUMBER</FONT> <BR><FONT
size=2>LAST_MISS_SIZE
NUMBER</FONT> <BR><FONT
size=2>MAX_MISS_SIZE
NUMBER</FONT> <BR><FONT
size=2>REQUEST_FAILURES
NUMBER</FONT> <BR><FONT
size=2>LAST_FAILURE_SIZE
NUMBER</FONT> <BR><FONT
size=2>ABORTED_REQUEST_THRESHOLD
NUMBER</FONT> <BR><FONT
size=2>ABORTED_REQUESTS
NUMBER</FONT> <BR><FONT
size=2>LAST_ABORTED_SIZE
NUMBER</FONT> </P>
<P><FONT size=2>These columns of V$SHARED_POOL_RESERVED are only valid if
the parameter</FONT> <BR><FONT size=2>shared_pool_reserved_size is set to
a valid value.</FONT> </P>
<P><FONT size=2> FREE_SPACE is the total amount of free space on the
reserved list.</FONT> <BR><FONT size=2> </FONT><BR><FONT
size=2> AVG_FREE_SIZE is the average size of the free memory on the
reserved list.</FONT> </P>
<P><FONT size=2> FREE_COUNT is the number of free pieces of memory
on the reserved list.</FONT> </P>
<P><FONT size=2> MAX_FREE_SIZE is the size of the largest free piece
of memory on the</FONT> <BR><FONT size=2>reserved </FONT><BR><FONT
size=2>
list.</FONT> </P>
<P><FONT size=2> USED_SPACE is the total amount of used memory on
the reserved list.</FONT> </P>
<P><FONT size=2> AVG_USED_SIZE is the average size of the of the
used memory on the</FONT> <BR><FONT size=2>reserved </FONT><BR><FONT
size=2>
list.</FONT> </P>
<P><FONT size=2> USED_COUNT is the number of used pieces of memory
on the reserved list.</FONT> </P>
<P><FONT size=2> MAX_USED_SIZE is the size of the largest used piece
of memory on the</FONT> <BR><FONT size=2>reserved </FONT><BR><FONT
size=2>
list.</FONT> </P>
<P><FONT size=2> REQUESTS is the number of times that the reserved
list was searched for a </FONT><BR><FONT
size=2> free
piece of memory.</FONT> </P>
<P><FONT size=2> REQUEST_MISSES is the number of times the reserved
list didn't have a free</FONT> </P>
<P><FONT
size=2>
piece of memory to satisfy the request, and proceeded to</FONT> <BR><FONT
size=2>start</FONT> <BR><FONT
size=2>
flushing objects from the LRU list.</FONT> </P>
<P><FONT size=2> LAST_MISS_SIZE is the request size of the last
REQUEST_MISS.</FONT> </P>
<P><FONT size=2> MAX_MISS_SIZE is the request size of the largest
REQUEST_MISS.</FONT> </P>
<P><FONT size=2>The next set of columns contain values which are valid
even if</FONT> <BR><FONT size=2>shared_pool_reserved_size is not
set.</FONT> </P>
<P><FONT size=2> REQUEST_FAILURES is the number of times that no
memory was found to</FONT> <BR><FONT size=2>satisfy a</FONT> <BR><FONT
size=2>
request (example: number of times ORA-04031 occurred)</FONT> </P>
<P><FONT size=2> LAST_FAILURE_SIZE is the request size of the last
failed request </FONT><BR><FONT
size=2>
(example: the request size of last ORA-04031).</FONT> </P>
<P><FONT size=2> ABORTED_REQUEST_THRESHOLD is the minimum size of a
request which will</FONT> <BR><FONT size=2>signal </FONT><BR><FONT
size=2>
an ORA-04031 error without flushing objects. See</FONT> </P>
<P><FONT
size=2>
the procedure aborted_request_threshold</FONT> <BR><FONT size=2>described
</FONT><BR><FONT
size=2>
above.</FONT> </P>
<P><FONT size=2> LAST_ABORTED_SIZE is the last size of the request
which returned an</FONT> <BR><FONT size=2>ORA-04031 </FONT><BR><FONT
size=2>
error without flushing objects from the LRU list.</FONT> </P><BR>
<P><FONT size=2>4. TUNING HINTS BASED ON
V$SHARED_POOL_RESERVED</FONT> <BR><FONT
size=2>================================================</FONT> <BR><FONT
size=2>Information in V$SHARED_POOL_RESERVED can help to set values
for</FONT> <BR><FONT size=2>shared_pool_reserved_size and even
shared_pool_size. This section assumes</FONT> <BR><FONT size=2>the
</FONT><BR><FONT size=2>DBA has performed all other shared pool tuning on
his system.</FONT> </P>
<P><FONT size=2>4.1 Initial Value for
shared_pool_reserved_size</FONT> <BR><FONT
size=2>------------------------------------------------</FONT> <BR><FONT
size=2>The DBA should make shared_pool_reserved_size 10% of the
shared_pool_size.</FONT> <BR><FONT size=2>For</FONT> <BR><FONT size=2>most
systems, this value should be sufficient, if the DBA has already
spent</FONT> <BR><FONT size=2>time</FONT> <BR><FONT size=2>tuning the
shared pool.</FONT> </P>
<P><FONT size=2>4.2 Initial Value for
shared_pool_reserved_min_alloc</FONT> <BR><FONT
size=2>-----------------------------------------------------</FONT>
<BR><FONT size=2>In most cases, the default value for this parameter is
adequate. If the DBA </FONT><BR><FONT size=2>increases this value, then
the RDBMS will allow fewer allocations from the </FONT><BR><FONT
size=2>reserved list and will request more memory from the shared pool
list.</FONT> </P>
<P><FONT size=2>4.4 Tuning shared_pool_reserved_size</FONT>
<BR><FONT size=2>-------------------------------------</FONT> <BR><FONT
size=2>Ideally, shared_pool_reserved_size should be made large enough to
satisfy</FONT> <BR><FONT size=2>any </FONT><BR><FONT size=2>request
scanning for memory on the reserved list without flushing objects</FONT>
<BR><FONT size=2>from </FONT><BR><FONT size=2>the shared pool. The
amount of operating system memory, however, may</FONT> <BR><FONT
size=2>constrain</FONT> <BR><FONT size=2>the size of the SGA, and
therefore the size of the shared pool such that</FONT> <BR><FONT
size=2>this </FONT><BR><FONT size=2>is not a feasible goal.</FONT> </P>
<P><FONT size=2>If the DBA has a system with ample free memory to increase
his SGA, the goal</FONT> <BR><FONT size=2>is </FONT><BR><FONT size=2>to
have:</FONT> </P>
<P><FONT size=2> REQUEST_MISS =
0</FONT> </P>
<P><FONT size=2>If the DBA is constrained for OS memory, his goal
is:</FONT> </P>
<P><FONT size=2> REQUEST_FAILURES = 0 or not
increasing</FONT> <BR><FONT size=2> LAST_FAILURE_SIZE >
shared_pool_reserved_min_alloc</FONT> <BR><FONT size=2>
AVG_FREE_SIZE >
shared_pool_reserved_min_alloc</FONT> </P>
<P><FONT size=2>If neither of these goals are met, increase
shared_pool_reserved_size; the</FONT> <BR><FONT size=2>DBA
</FONT><BR><FONT size=2>also needs to increase shared_pool_size by the
same amount, since the</FONT> <BR><FONT size=2>reserved </FONT><BR><FONT
size=2>list is taken from the shared pool.</FONT> </P>
<P><FONT size=2>4.5 shared_pool_reserved_size too low</FONT>
<BR><FONT size=2>--------------------------------------</FONT> <BR><FONT
size=2>The reserved pool is too small when:</FONT> </P>
<P><FONT size=2> REQUEST_FAILURES > 0 (and
increasing)</FONT> </P>
<P><FONT size=2>and at least one of the following is true:</FONT> </P>
<P><FONT size=2> LAST_FAILURE_SIZE >
shared_pool_reserved_min_alloc</FONT> <BR><FONT size=2>
MAX_FREE_SIZE <
shared_pool_reserved_min_alloc</FONT> <BR><FONT size=2>
FREE_MEMORY <
shared_pool_reserved_min_alloc</FONT> </P>
<P><FONT size=2>The DBA has two options, depending on his SGA size
constraints:</FONT> </P>
<P><FONT size=2> o Increase shared_pool_reserved_size
and shared_pool_size, accordingly</FONT> <BR><FONT size=2>
o Increase shared_pool_reserved_min_alloc (but may need to
increase</FONT> <BR><FONT size=2>
shared_pool_size)</FONT> </P>
<P><FONT size=2>The first option will increase the amount of memory
available on the</FONT> <BR><FONT size=2>reserved </FONT><BR><FONT
size=2>list without impacting users not allocating memory from the
reserved list.</FONT> <BR><FONT size=2>The </FONT><BR><FONT size=2>second
options reduces the number of allocations allowed to use memory
from</FONT> <BR><FONT size=2>the</FONT> <BR><FONT size=2>reserved list;
doing so, however, will increase normal shared pool perhaps
</FONT><BR><FONT size=2>impacting other users on the system.</FONT> </P>
<P><FONT size=2>4.6 shared_pool_reserved_size too high</FONT>
<BR><FONT size=2>---------------------------------------</FONT> <BR><FONT
size=2>It is possible that too much memory has been allocated to the
reserved list.</FONT> </P>
<P><FONT size=2>If:</FONT> </P>
<P><FONT size=2> REQUEST_MISS =
0 or not increasing</FONT> <BR><FONT size=2>
FREE_MEMORY = > 50% of
shared_pool_reserved_size minimum</FONT> </P>
<P><FONT size=2>The DBA has two options:</FONT> </P>
<P><FONT size=2> o Decrease
shared_pool_reserved_size</FONT> <BR><FONT size=2> o
Decrease shared_pool_reserved_min_alloc (if not the default</FONT>
<BR><FONT size=2> value)</FONT> </P>
<P><FONT size=2>4.7 shared_pool_size too small</FONT> <BR><FONT
size=2>-------------------------------</FONT> <BR><FONT size=2>The new
fixed table can also indicate when shared_pool_size is too small.
</FONT><BR><FONT size=2>If:</FONT> </P>
<P><FONT size=2> REQUEST_FAILURES > 0 and
increasing</FONT> <BR><FONT size=2> LAST_FAILURE_SIZE
< shared_pool_reserved_min_alloc</FONT> </P>
<P><FONT size=2>Then the DBA has two options if he has enabled the
reserved list:</FONT> </P>
<P><FONT size=2> o Decrease
shared_pool_reserved_size</FONT> <BR><FONT size=2> o
Decrease shared_pool_reserved_min_alloc (if set larger than the</FONT>
<BR><FONT size=2>default)</FONT> </P>
<P><FONT size=2>Otherwise, the DBA the could:</FONT> </P>
<P><FONT size=2> o Increase shared_pool_size</FONT>
</P><BR>
<P><FONT
size=2>
APPENDIX 2: Procedure free_unused_memory</FONT> <BR><FONT
size=2>
=========================================</FONT> </P>
<P><FONT size=2>This text is also in the specification for this procedure
in dbmsutil.sql.</FONT> <BR><FONT size=2>It is part of package
dbms_session.</FONT> </P>
<P><FONT size=2>Procedure free_unused_memory --</FONT> </P>
<P><FONT size=2>Procedure for users to reclaim unused memory after
performing operations</FONT> <BR><FONT size=2>requiring large amounts of
memory (where large is >100K). Note that this </FONT><BR><FONT
size=2>procedure should only be used in cases where memory is at a
premium.</FONT> </P>
<P><FONT size=2>Examples operations using lots of memory are:</FONT> </P>
<P><FONT size=2> o large sorts where entire
sort_area_size is used and</FONT> <BR><FONT
size=2> sort_area_size is hundreds of
KB</FONT> <BR><FONT size=2> o compiling large PL/SQL
packages, procedures, or functions</FONT> <BR><FONT size=2>
o storing hundreds of KB of data within PL/SQL indexed tables</FONT>
</P>
<P><FONT size=2>One can monitor user memory by tracking the statistics
"session uga memory"</FONT> <BR><FONT size=2>and</FONT> <BR><FONT
size=2>"session pga memory" in the v$sesstat/v$statname fixed views.
Monitoring</FONT> <BR><FONT size=2>these </FONT><BR><FONT
size=2>statistics will also show how much memory this procedure has freed.
The</FONT> <BR><FONT size=2>behavior</FONT> <BR><FONT size=2>of this
procedure depends upon the configuration of the server operating on
</FONT><BR><FONT size=2>behalf of the client:</FONT> </P>
<P><FONT size=2> o dedicated server - returns unused PGA
memory to the OS</FONT> <BR><FONT size=2> o MTS
server - returns unused session memory
to the shared_pool</FONT> </P>
<P><FONT size=2>In order to free memory using this procedure, the memory
must not be in use.</FONT> </P>
<P><FONT size=2>Once an operation allocates memory, only the same type of
operation can</FONT> <BR><FONT size=2>reuse </FONT><BR><FONT size=2>the
allocated memory. For example, once memory is allocated for sort,
even</FONT> <BR><FONT size=2>if </FONT><BR><FONT size=2>the sort is
complete and the memory is no longer in use, only another sort</FONT>
<BR><FONT size=2>can </FONT><BR><FONT size=2>reuse the sort-allocated
memory. For both sort and compilation, after the </FONT><BR><FONT
size=2>operation is complete, the memory is no longer in use and the user
can</FONT> <BR><FONT size=2>invoke </FONT><BR><FONT size=2>this procedure
to free the unused memory.</FONT> </P>
<P><FONT size=2>An indexed table implicitly allocates memory to store
values assigned to the</FONT> </P>
<P><FONT size=2>indexed table's elements. Thus, the more elements in
an indexed table, the</FONT> <BR><FONT size=2>more</FONT> <BR><FONT
size=2>memory the RDBMS allocates to the indexed table. As long as
there are</FONT> <BR><FONT size=2>elements </FONT><BR><FONT size=2>within
the indexed table, the memory associated with an indexed table is
in</FONT> <BR><FONT size=2>use.</FONT> </P>
<P><FONT size=2>The scope of indexed tables determines how long their
memory is in use.</FONT> <BR><FONT size=2>Indexed </FONT><BR><FONT
size=2>tables declared globally are indexed tables declared in packages or
package </FONT><BR><FONT size=2>bodies. They allocate memory from
session memory. For an indexed table </FONT><BR><FONT
size=2>declared globally, the memory will remain in use for the lifetime
of a</FONT> <BR><FONT size=2>user's </FONT><BR><FONT size=2>login
(lifetime of a user's session), and is freed after the user</FONT>
<BR><FONT size=2>disconnects </FONT><BR><FONT size=2>from ORACLE.</FONT>
</P>
<P><FONT size=2>Indexed tables declared locally are indexed tables
declared within</FONT> <BR><FONT size=2>functions, </FONT><BR><FONT
size=2>procedures, or anonymous blocks. These indexed tables
allocate memory from</FONT> <BR><FONT size=2>PGA</FONT> <BR><FONT
size=2>memory. For an indexed table declared locally, the memory
will remain in</FONT> <BR><FONT size=2>use </FONT><BR><FONT size=2>for as
long as the user is still executing the procedure, function, or</FONT>
<BR><FONT size=2>anonymous</FONT> <BR><FONT size=2>block in which the
indexed table is declared. After the procedure,</FONT> <BR><FONT
size=2>function, or</FONT> <BR><FONT size=2>anonymous block is finished
executing, the memory is then available for</FONT> <BR><FONT
size=2>other</FONT> <BR><FONT size=2>locally declared indexed tables to
use (i.e., the memory is no longer in</FONT> <BR><FONT size=2>use).</FONT>
</P>
<P><FONT size=2>Assigning an uninitialized, "empty," indexed table to an
existing index</FONT> <BR><FONT size=2>table is</FONT> <BR><FONT size=2>a
method to explicitly re-initialize the indexed table and the memory</FONT>
<BR><FONT size=2>associated</FONT> <BR><FONT size=2>with the indexed
table. After this operation, the memory associated with</FONT>
<BR><FONT size=2>the </FONT><BR><FONT size=2>indexed table will no longer
be in use, making it available to be freed by </FONT><BR><FONT
size=2>calling this procedure. This method is particularly useful on
indexed</FONT> <BR><FONT size=2>tables </FONT><BR><FONT size=2>declared
globally which can grow during the lifetime of a user's session, as</FONT>
</P>
<P><FONT size=2>long as the user no longer needs the contents of the
indexed table.</FONT> </P>
<P><FONT size=2>The memory rules associated with an indexed table's scope
still apply; this </FONT><BR><FONT size=2>method and this procedure,
however, allow users to intervene and to</FONT> <BR><FONT size=2>explictly
</FONT><BR><FONT size=2>free the memory associated with an indexed
table.</FONT> </P>
<P><FONT size=2>The PL/SQL fragment below illustrates the method and the
use of procedure </FONT><BR><FONT size=2>free_unused_user_memory.</FONT>
</P>
<P><FONT size=2> create package foobar</FONT> <BR><FONT
size=2> type number_idx_tbl is table of number indexed by
binary_integer;</FONT> <BR><FONT size=2> store1_table
number_idx_tbl; -- PL/SQL indexed
table</FONT> <BR><FONT size=2> store2_table
number_idx_tbl; -- PL/SQL indexed
table</FONT> <BR><FONT size=2> store3_table
number_idx_tbl; -- PL/SQL indexed
table</FONT> <BR><FONT size=2> ...</FONT> <BR><FONT
size=2> end;
-- end of foobar</FONT> <BR><FONT size=2> declare</FONT>
<BR><FONT size=2> ...</FONT> <BR><FONT size=2>
empty_table number_idx_tbl; --
uninitialized ("empty") version</FONT> <BR><FONT size=2> begin</FONT>
<BR><FONT size=2> for i in 1..1000000 loop</FONT> <BR><FONT
size=2> store1_table(i) :=
i; --
load data</FONT> <BR><FONT size=2> end loop;</FONT> <BR><FONT
size=2> ...</FONT> <BR><FONT size=2> store1_table
:= empty_table; -- "truncate" the
indexed table</FONT> <BR><FONT size=2> ...</FONT> <BR><FONT
size=2> -</FONT> <BR><FONT size=2>
dbms_session.free_unused_user_memory; -- give memory back to
system</FONT> <BR><FONT size=2> store1_table(1) :=
100; --
index tables still declared;</FONT> <BR><FONT size=2>
store2_table(2) :=
200; --
but truncated.</FONT> <BR><FONT size=2> ...</FONT> <BR><FONT
size=2> end;</FONT> </P>
<P><FONT size=2> Copyright (c) 1995,1999 Oracle Corporation. All
Received on Thu Aug 24 2000 - 10:38:56 CDT
![]() |
![]() |