Sunteți pe pagina 1din 16

S hared P ool

Library Cache Control Structure


Dictionary Cache

ALL ABOUT SHARED


POOL S QL Area
PL?SQL Procedure Control Struct Object definition
Latch
LOCK

Tapas Kumar A shared SQL area contains the parse


Oracle DBA tree and execution plan for a single
TATA CONSULTANCY SERVICES SQL statement, or for similar SQL
statements. Oracle saves memory by
INTRODUCTION using one shared SQL area for
multiple similar DML statements,
What is shared pool? This first query particularly when many users
that comes, let us have a brief execute the same application.
introduction regarding shared pool A shared SQL area is always in the
here first. shared pool.
Most of the people knows that shared
pool is the part of System Global Oracle allocates memory from the
Area (SGA) it’s true but little else, shared pool when a SQL statement is
What exactly the shared pool? parsed; the size of this memory
Shared pool are contain lots of key depends on the complexity of the
memory areas of Oracle and in statement. If a SQL statement
Instance tuning the major area that requires a new shared SQL area and
we have to tune is shared pool if the entire shared pool has already
shared pool defined improperly the been allocated, Oracle can deallocate
overall database performance will items from the pool using a modified
suffer. least Recently used algorithm until
there is enough free space for the
INTERNAL STRUCTURE – new statement's shared SQL area. A
private SQL area contains data such
as bind information and runtime
buffers. Each session that issues a
Majority shared pool related to the SQL statement has a private SQL
two part of SGA one is fixed are area. Each user that submits an
which is relatively constant to a identical SQL statement has his or
oracle instance for a particular her own private SQL area that uses a
version and the second part is single shared SQL area; many private
Variable area which gradually shrink SQL areas can be associated with the
and grow for user and application same shared SQL area.
requirement. A private SQL area contains data
Now we should do a close look of such as bind information and runtime
various component of Shared Pool – buffers. Each session that issues a
SQL statement has a private SQL
Basically Shared Pool could be area. Each user that submits an
divided in three major parts – identical SQL statement has his or
1. Library Cache her own private SQL area that uses a
2. Dictionary Cache single shared SQL area; many private
3. Control Structure SQL areas can be associated with the
same shared SQL area.
Library Cache –
Memory Part where all the SQL and A private SQL area has a persistent area and a
PL/SQL statement executed, all runtime area:
execution plan reside here for SQL • The persistent area contains
statement stored here. bind information that persists
We can further subdivide this Library across executions, code for
Chache into – datatype conversion (in case
1. Shared and Private SQL the defined datatype is not
Area the same as the datatype of
2. PL/SQL Procedure Part the selected column), and
other state information (like
Shared and Private SQL Area – recursive or remote cursor
numbers or the state of a
parallel query). The size of the
persistent area depends on
the number of binds and PL/SQL Procedure Part –
columns specified in the
statement. For example, the Oracle processes PL/SQL program
persistent area is larger if units (procedures, functions,
many columns are specified in packages, anonymous blocks, and
a query. database triggers) much the same
• The runtime area contains way it processes individual SQL
information used while the statements. Oracle allocates a
SQL statement is being shared area to hold the parsed,
executed. The size of the compiled form of a program unit.
runtime area depends on the Oracle allocates a private area to
type and complexity of the hold values specific to the session
SQL statement being that executes the program unit,
executed and on the sizes of including local, global, and package
the rows that are processed variables (also known as package
by the statement. In general, instantiation) and buffers for
the runtime area is somewhat executing SQL. If more than one user
smaller for INSERT, UPDATE executes the same program unit,
and DELETE statements than then a single, shared area is used by
it is for SELECT statements, all users, while each user maintains a
particularly when the SELECT separate copy of his or her private
statement requires a sort. SQL area, holding values specific to
his or her session.
Oracle creates the runtime area as
the first step of an execute request. Individual SQL statements contained
For INSERT, UPDATE, and DELETE within a PL/SQL program unit are
statements, Oracle frees the runtime processed as described in the
area after the statement has been previous sections. Despite their
executed. For queries, Oracle frees origins within a PL/SQL program unit,
the runtime area only after all rows these SQL statements use a shared
are fetched or the query is cancelled. area to hold their parsed
representations and a private area
The location of a private SQL area for each session that executes the
depends on the type of connection statement.
established for a session. If a session (x$ksmms) table provide the
is connected via a dedicated server, runtime information regarding
private SQL areas are located in the PL/SQL area in Library Cache which is
user's PGA. However, if a session is suppose to be allocated to a
connected via the multi-threaded particular Oracle Instance –
server, the persistent areas and, for E.g. –
SELECT statements, the runtime select * from X$KSMSS
areas, are kept in the SGA where KSMSSNAM like 'PL/SQL%'
and KSMSSLEN <> 0 ;

(x$ksmms) table provide the ADDR INDX INST_ID KSMSSLEN


runtime information regarding SQL KSMSSNAM KSMDSIDX
---------------- ---------- ---------- ----------
area in Library Cache which is -------------------------- ----------
suppose to be allocated to a 000000011049B268 28 1 1501552
PL/SQL DIANA 1
particular Oracle Instance – 000000011049B268 37 1 1357968
E.g. – PL/SQL MPCODE 1

select * from X$KSMSS PL/SQL MPCODE stands for machine


where KSMSSNAM = 'sql_area'
and KSMSSLEN <> 0 ; dependent pseudocode.
PL/SQL DIANA stands for the PL/SQL
---------------- ---------- ---------- ----------
-------------------------- ---------- code size in the shared pool at
runtime.
ADDR INDX INST_ID KSMSSLEN
KSMSSNAM KSMDSIDX
000000011049B268 29 1 13480352 Library Cache Manager –
sql area 1
numbers are the next higher prime
The main purpose of the library value. They are 251, 509, 1021,
cache is to provide a mechanism to 2039, 4093, 8191, 16381, 32749,
locate and store any library cache 65521, 131071, and 4292967293
object quickly. A hashing mechanism where the "n+1"th size is
is used to locate a handle, which approximately twice the "n"th size.
contains the identity (name) of the The resulting expansion of the hash
object. The library cache handle then table will involve allocating a new
points us to one or more the library hash table at the next prime size,
cache objects and their contents. rehashing the library cache objects
The library cache caches different from the old table to the new table,
types of library objects (e.g. and freeing the space allocated from
packages, procedures, functions, the old hash table. Throughout this
shared cursors, anonymous procedure, access to the hash table
PL/SQL blocks, table definitions, view is blocked (by freezing access to the
definitions, form definitions). child
Library cache memory is allocated latches) as one user allocates new
out of the top most heap or the buckets to double the size of the
generic SGA heap. When the library hash table and then uses the least
cache, KGL, needs more memory, it significant bits of the hash value to
will call the heap manager (KGH) to determine which new bucket a
allocate it. The library cache consists handle belongs to. Contrary to
of a hash table, which consists of an common belief, this is a rare and
array of hash buckets. Each hash inexpensive operation that may
bucket is a doubly linked list of cause a short (approximately 3-5
library cache object handles. Each second) hiccup in the system. The
library cache object hash table never shrinks.
handle points to a library cache The library cache manager will apply
object and has a reference list. The a modulo hash function to a given
library cache object is further broken object’s namespace, object name,
down into other components such as owner, and database link to
a dependency table, a child table, determine the hash bucket where the
and an authorisation table (to name object should be found. It then walks
a few). down the corresponding linked list to
see if the object is there. If the object
does not exist, the library cache
manager will create an empty object
with the given name, insert it in the
hash table, and request the client
load it by calling the client's
environment-dependent load
function. Basically, the client would
read from disk, call the heap
manager to allocate memory, and
load the object.
Library Cache Handle –

Library Cache Manager (Hash


Table and Hash Bucket) –

The hash table is an array of hash


buckets. The initial number of the
hash buckets is 251; however, the
number of buckets will increase when
the number of objects in the table
exceeds the next number. The next
000000011049AE88 60 1 1092352
dictionary cache 2

Control Structure -

This contain the information


regarding Internal Latch and Locks
(Data Structure), it also contain
buffer header, the process session
A library cache handles points to a and transaction arrays.
library cache object. It contains the The size of these arrays depends on
name of the library object, the the setting of Initialisation parameter
namespace, a timestamp, a of Init.ora file and can’t be changed
reference list, a list of locks locking without shutting down the database.
the object and a list of pins pinning
the object. Each object is uniquely
identified by the name within its
namespace. The library cache
manager will generate a name for
every object, even anonymous
PL/SQL blocks. The handle uses
namespaces to partition library
cache objects by types. These are
examples of different types of Shared Pool Chunks –
namespaces: one namespace holds
all namespaces depended on PL/SQL Have close looks of Shared Pool, For
objects, one for package bodies and that we should have a close look at
table bodies, one for shared cursors; x$ksmsp each row in this table
one for triggers; one for indexes; and shows a chunk of shared pool –
one for clusters. The namespace
KSMCHCOM KSMCHPTR KSMCHSIZ
describes the type of an item KSMCHCLS
kept in the library cache. The name ---------------- ---------------- ---------- --------
sql area 0700000005D85750 1360
consists of the object owner name, freeabl
the object name, the database link 0700000005D846F8 4184 freeabl
KGL handles 0700000005D84520 472
name, and the database link owner recr
name. A comprehensive list can be library cache 0700000005D84478 168
viewed from v$librarycache. freeabl
0700000005D84150 808 recr
A handle can be freed if there are no KQR PO 0700000005D83D20 1072
current references to it and it has not recr
KGL handles 0700000005D83B48 472
been expressly marked to be kept. recr
We use this to determine when a library cache 0700000005D83AA0 168
freeabl
handle should be unpinned in 0700000005D83778 808 recr
memory. 0700000005D83450 808 freeabl
KGL handles 0700000005D83300 336

Dictionary Cache – recr

Table definition against which an When each shared pool chunk is


application user suppose to do a allocated the code is passed to a
query, it include table’s associated function that does the work of
Index and Columns and privilege allocation and this address is visible
information regarding table as we as to KSMCHCOM column, which
columns. describe the purpose of allocation.
This chunk is supposed to be larger
select * from X$KSMSS then the size of the object as it also
where KSMSSNAM like 'PL/SQL%'
and KSMSSLEN <> 0 ;
contains the header information.

ADDR INDX INST_ID KSMSSLEN The column KSMCHCLS represent


KSMSSNAM KSMDSIDX
---------------- ---------- ---------- ---------- the class, there are basically four
-------------------------- ---------- type of classes –
Freeable – can be freed only contain reserved size, here REQUEST_MISS
the objects needed for the session shows the number of times the
call. request miss for a large chunk.
Free – free and not contained by
valid object.
Recr – contain by temporary objects. SHARED_POOL SIZE
Parm – contained by the permanent CALCULATION –
object.
The shared pool size is highly
So the overall summary - application dependent. To determine
the shared pool size for a production
select KSMCHCOM name, system it is generally necessary to
count(KSMCHCOM),
sum(decode(KSMCHCLS,'recr',KSMCHSIZ)) develop the application run it on a
RECREATABLE, test environment (should be enough
sum(decode(KSMCHCLS,'freeabl',KSMCHSIZ))
FREEABLE like production system) get some test
from result and on the basis of that
x$ksmsp
group by KSMCHCOM ;
calculate the shared pool size. There
are some few step which we should
NAME COUNT(KSMCHCOM) RECREATABLE
FREEABLE
consider while calculating the shared
---------------- --------------- ----------- ---------- pool –
PARAMETER ENTRY 4 192
PARAMETER TABLE 1 2064
PL/SQL DIANA 237 12816 479672
PL/SQL MPCODE 23 11792 50336
STORED OBJECTS – The amount of
PLS cca hp desc 1 376 shared pool that needs to be
PLS non-lib hp 1 2136
PRESENTATION TA 1 2064 allocated for objects that are stored
SERVICE NAME EN
SERVICE NAMES T
2
1
152
2064
in the database like packages and
character set m 5 31936 views is
character set o 4 318648
easy to measure. You can just
LRU List – measure their size directly with the
following statement:
When a process starts it allocate
select sum(sharable_mem) from
some memory and when it’ fails to
V$DB_OBJECT_CACHE;
allocated required memory,
Then it try to remove chunk
containing recreatable object from SQL
shared pool to get the desired size of The amount of memory needed to
chunk, and removing these object store sql statements in the shared
from memory is based on LRU(Least pool is more difficult to measure
Recent Used) means those objects because of the needs of dynamic sql.
that are frequently pinned kept in the If an application has no dynamic sql
memory and those are unpinned we then the amount of memory can
generally remove those objects from simply be measured after the
the memory. Object those required application has run for a while by just
again known as transient and other selecting it out of the shared pool as
known as recurrent. follows:

ORA-04331 ‘unable to allocate x select sum(sharable_mem) from v$sqlarea;


bytes of shared pool’ when all
the free memory fully exhausted If the application has a moderate or
(Later we will discuss the shared large amount of dynamic sql like
pool fragmentation). most applications do, then a certain
amount of memory will be needed for
There is one list maintained which the shared sql plus more for the
known as Reserved List, it generally dynamic sql. Sufficient memory
5% of the total size of Shared Pool should be allocated so that the
and reserved size is defined by dynamic sql does not age the shared
SHARED_POOL_RESERVED_SIZE sql out of the shared pool.
parameter in Init.ora parameter file. Approximated memory could be
With the help of calculated by the following:
v$shared_pool_reserved we can see
select sum(sharable_mem) from v$sqlarea where
executions > 5; select sum(value) all_sess_mem
from v$sesstat s, v$statname n
The remaining memory in v$sqlarea where s.statistic# = n.statistic#
is for dynamic sql. and n.name = 'session uga memory max';

PER-USER PER-CURSOR MEMORY OVERHEAD –



You will need to add a minimum of
You will need to allow around 250 30% overhead to the values
bytes of memory in the shared pool calculated above to allow for
per concurrent user for each open unexpected and unmeasured usage
cursor that the user of the shared pool.
has whether the cursor is shared or
not. During the peak usage time of Estimating Procedure (From
the production system, you can Metalink) –
measure this as follows:
set serveroutput on;

select sum(250 * users_opening) from declare


v$sqlarea; object_mem number;
shared_sql number;
cursor_mem number;
In a test system you can measure it mts_mem number;
by selecting the number of open used_pool_size number;
free_mem number;
cursors for a test user and pool_size varchar2(100);
multiplying by the total number of begin
users: -- Stored objects (packages, views)
select sum(sharable_mem) into object_mem
from v$db_object_cache;
select 250 * value bytes_per_user -- Shared SQL -- need to have additional
from v$sesstat s, v$statname n memory if dynamic SQL used
where s.statistic# = n.statistic# select sum(sharable_mem) into shared_sql from
and n.name = 'opened cursors current' v$sqlarea;
and s.sid = 23; -- replace 23 with session id of -- User Cursor Usage -- run this during peak
user being measured usage
select sum(250*users_opening) into
The per-user per-cursor memory is cursor_mem from v$sqlarea;
-- For a test system -- get usage for one user,
one of the classes of memory that multiply by # users
shows up as 'library cache' in -- select (250 * value) bytes_per_user
-- from v$sesstat s, v$statname n
v$sgastat. -- where s.statistic# = n.statistic#
-- and n.name = 'opened cursors current'
MTS – -- and s.sid = 25; -- where 25 is the sid of the
process
-- MTS memory needed to hold session
If you are using multi-threaded information for shared server users
-- This query computes a total for all currently
server, then you will need to allow logged on users (run
enough memory for all the shared -- during peak period). Alternatively calculate
for a single user and
server users to put their session -- multiply by # users.
memory in the shared pool. This can select sum(value) into mts_mem from
be measured for one user with the v$sesstat s, v$statname n
where s.statistic#=n.statistic#
following query: and n.name='session uga memory max';
select value sess_mem -- Free (unused) memory in the SGA: gives an
from v$sesstat s, v$statname n indication of how much memory
where s.statistic# = n.statistic# -- is being wasted out of the total allocated.
and n.name = 'session uga memory' select bytes into free_mem from v$sgastat
and s.sid = 23; -- replace 23 with session id of where name = 'free memory';
user being measured -- For non-MTS add up object, shared sql,
A more conservative value to use is cursors and 30% overhead.
used_pool_size :=
the maximum session memory that round(1.3*(object_mem+shared_sql+cursor_me
was ever allocated by the user: m));
-- For MTS add mts contribution also.
-- used_pool_size :=
select value sess_max_mem round(1.3*(object_mem+shared_sql+cursor_me
from v$sesstat s, v$statname n m+mts_mem));
where s.statistic# = n.statistic# select value into pool_size from v$parameter
and n.name = 'session uga memory max' where name='shared_pool_size';
and s.sid = 23; -- replace 23 with session id of -- Display results
user being measured dbms_output.put_line ('Obj mem: '||to_char
To select this value for all the (object_mem) || ' bytes');
currently logged on users the dbms_output.put_line ('Shared sql: '||to_char
(shared_sql) || ' bytes');
following query can be used:
dbms_output.put_line ('Cursors: '||to_char
(cursor_mem) || ' bytes'); POOL_USED POOL_SIZE POOL_AVAIL POOL_PCT
dbms_output.put_line ('MTS session: '||to_char ---------------- ---------------- -------
(mts_mem) || ' bytes'); 8.98988342 32 23.0101166 28.0933857
dbms_output.put_line ('Free memory: '||to_char
(free_mem) || ' bytes ' || '(' ||
to_char(round(free_mem/1024/1024,2)) || 'M)'); If shared percentage (POOL_PCT) in
dbms_output.put_line ('Shared pool utilization
(total): '|| to_char(used_pool_size) || ' bytes ' || nineties then we need to increase the
'(' || size of shared pool, but some time
to_char(round(used_pool_size/1024/1024,2)) ||
'M)'); the reason may be other of hogh
Technical Reports Compendium, Volume I, 1996 percentage of shared pool. The
Shared Pool Internals
dbms_output.put_line ('Shared pool allocation
above scripts should run periodically
(actual): '|| pool_size ||' bytes ' || '(' || to get a summary of Shared Usage at
to_char(round(pool_size/1024/1024,2)) || 'M)'); peak and normal time.
dbms_output.put_line ('Percentage Utilized: '||
to_char (round(used_pool_size/pool_size*100))
|| '%'); Now we should focus on high
end; percentage usage of shared pool why
it high (more then 90%).
We should see whether the shared
pool fill with reusable sql or with bad
MONITORING & TUNING – sql, before increase the size of
shared pool we should examine all
Let begin with major part which is the key areas, it might be possible to
knows as shared pool tuning and flush the shared pool would resolved
Oracle recommend that the default the high percentage issue of shared
size of Shared Pool in Init.ora pool.
parameter should be ¼ of the Total So how we can see that what is in
SGA in a general scenario. the shared pool?
The other shared pool parameter Whether is being properly used or
controls how to the variable space not. For that we can generate some
area in the shared pool is parsed out. common useful report.
According to the suggestion give by First report will shown here the
Oracle if our total SGA size is 100 MB individual mapping of user with
then we should set our Shared Pool shared pool –
size 25 MB and latter increase
gradually as needed by the system.
Now a question comes in our mind
what are the key area should be Create a temporary table to hold the
monitored by the DBA to get the information related to sql area for all
knowledge that the shared pool size users,that produces a summary
is small. report for each user.
From V$SGASTAT and V$SQLAREA we
will get this information. create table temp_sql_report as (select
b.username,
a.SQL_TEXT,
Shared Pool usage we can see at a a.execution,
given point of time from the following a.load,
a.user_executing
script – a.SHARABLE_MEM,
select a.PERSISTENT_MEM,
sum(a.KSMSSLEN)/(1024*1024) Pool_used, a.RUNTIME_MEM
max(c.KSPPSTVL)/(1024*1024) pool_size, from v$sqlarea a,dba_users b
(max(c.KSPPSTVL)/(1024*1024))- where a.PARSING_USER_ID = b.USER_ID
sum(a.KSMSSLEN)/(1024*1024)) pool_avail,
(sum(a.KSMSSLEN)/max(c.KSPPSTVL))*100 SQL SUMMARY REPORT –
pool_pct
from x$ksmss a, x$ksppi b, x$ksppcv c REM <-- SQLAREA SUMMARY REPORT
where a.KSMSSNAM in ( REM Mapping between user and sql area
'reserved stopper',
usage.
'table definiti',
'dictionary cache',
'library cache',
'sql area', Col username for a20 heading USER
'PL/SQL DIANA', Col sharable_mem for a25 heading SHARABLE
'SEQ S.O.')and Col persistent_mem for a20 heading PERSIS
b.indx = c.indx and Col run_time for a20 heading RUNTIME
b.KSPPINM='shared_pool_size'
start title80 ‘SQL AREA SUMMARY REPORT’
Spool sql_area_summary_report
The out of the above script -
Select The out put of the report look like
Username,
Sum(SHARABLE_MEM), this –
Sum(PERSISTENT_MEM),
Sum(RUNTIME_MEM) USERS
From temp_sql_report ------------------------------
Group by username; SQL_TEXT
Spool off -----------------------------------------------------------------
/ -----------------------------------------------------------------
--
USERNAME SUM(SHARABLE_MEM) EXECUTIONS LOADS USERS_EXECUTING
SUM(PERSISTENT_MEM) SUM(RUNTIME_MEM) SHARABLE_MEM PERSISTENT_MEM
------------------------------ ----------------- ---------- ---------- --------------- ------------ --------------
------------------- ---------------- 0 2 0 16439 1376
SYS 3004291
237048 1097504 SYS
TEST 281085 DECLARE
18040 83328 P_EQP_NO
mv_tplans.eqm_eqp_no_fk%type :=
upper('GLDU0371682');
P_MESSAGE_NO
This output of this summary report mv_edimessages.message_no%type := NULL;
shows here the sql area used by each P_EQP_SIZE
user. Now try to analyse the mv_tplans.eqs_eqp_size_fk%type := 20;
P_EQP_TYPE
summary report, if a particular hold a mv_tplans.eqt_eqp_type_code_fk%type :=
large amount of memory then that upper('GP
'); P_REF_NO
means the sql’s used by that user are mv_edimessages.ref1_no%type :=
bad every time it generate different upper('HAI2000229/1');
P_REF_TYPE
execution plan for similar kind of mv_edimessages.ref1_type%type := B;
queries, the coding produce a large P_FACILITY
number of nonreusable sql area. mv_edimessages.fac_facility_fk%type :=
upper('SCTSOUGB');
P_EVENT_DATETM
Now we can generate an another mv_edimessages.event_datetm%type :=
SYSDATE; P_EVENT_TYPE
where we will shown the actual sql mv_eventtableitems.event_type%type := 4;
statement executed by a user and P_FCL_LCL mv_tplans.fcl_lcl%type := NULL;
P_BOOKING
how many time a sql statement _ITEM mv_tplans.booking_item%type := 1;
execute by a user , what amount of P_PLAN_ID mv_tplans.tplan_id%type ;
memory that sql statement took to P_VERSION_NO mv_tplans.version_no%type;
P_LEG_ID mv_tplanlegs.tleg_id%type;
execute the statement. p_ack_reqd_ind number := 0;
P_ACK_ERROR_CODE VARCHAR2(8);
column sql_text format a60 heading Text P_BOOKING_REF_NO mv
word_wrapped _tplans.booking_ref_no%type;
column sharable_mem heading Shared| P_RETURN_CODE NUMBER; P_RETURN_MESG
Bytes
column persistent_mem heading One warning about the script, the
Persistent|Bytes
column loads heading Loads
report it generates can run to several
column users format a15 heading "User" hundred pages for a user with a large
column executions number of SQL areas. What things
heading "Executions"
column users_executing heading should we watch for in a user's SQL
"Used By" areas? First, watch for the non-use of
start title132 "Users SQL Area Memory Use"
spool Sql_info bind variables, bind variable usage is
set long 2000 pages 59 lines 132 shown by the inclusion of variables
break on users
compute sum of sharable_mem on users
such as ":4" in the SQL text. As the
compute sum of persistent_mem on users stement using the bind variable: 4 so
compute sum of runtime_mem on users is reusable. Non-bind usage means
select
username users, hard coded values such as upper
sql_text, ('GLDU0371682') are used. Notice
Executions,
loads, that for most of the rest of the
users_executing, statements in the report no bind
sharable_mem,
persistent_mem
variables are used even though
from many of the SQL statements are
temp_sql_report nearly identical. This is one of the
where b.username like upper('%&user_name%')
order by 3 desc,1; leading causes of shared pool misuse
spool off and results in useful SQL being drown
pause Press enter to continue
in tons of non-reusable garbage SQL.

The problem with non-reusable SQL


is that it must still be looked at by
any new SQL inserted into the pool very expensive in both terms of CPU
(actually it's hash value is scanned). used, and in the number of latch gets
While a hash value scan may seem a performed.
small cost item, if your shared pool
contains tens of thousands of SQL Soft Parse -
areas this can be a performance If session issues a SQL statement,
bottleneck. which is already in the shared pool
AND it, can use an existing version of
As the SQL statement issued by the that statement then this is known as
user is directly related to the shared a 'soft parse'. As far as the
pool and using a good mechanism of application is concerned it has asked
coding improve the system to parse the statement.
performance and also avoid
redundant parsing of PL/SQL and SQL Identical Statements?
statement for Library Cache If two SQL statements mean the
(memory + CPU). As Library Cache is same thing but are not identical
a part of Shared pool so Indirectly we character for character then from an
can say we tuned the Shared Pool. Oracle viewpoint they are different
statements. Consider the following
Let have a Close look of various issued by SCOTT in a single session:
parsing type of SQL –
SELECT ENAME from TEMP_X;

Literal SQL – A literal SQL


SELECT ename from temp_x;
statement is considered as one which
use literals in the predicates rather Although both of these statements
then bind variable, where the value are really the same they are not
of the literal is likely to differ identical as an upper case 'T' is not
between various execution of the the same as a lower case 't'.
statement.
E.g 1 – Sharable SQL
SELECT * FROM temp_x WHERE col_1='x'; If two sessions issue identical SQL
is used by the application instead of statements it does NOT mean that
the statement is sharable. Consider
SELECT * FROM temp_x WHERE ename=:x; the following:
Eg 2:
SELECT sysdate FROM dual; User USER_X has a table called
does not use bind variables but TEMP_X and issues:
would not be considered as a literal
SELECT column_x from TEMP_X;
SQL statement for this article as it
can be shared.
Eg 3: User USER_Y has his own table called
TEMP_X and also issues:
SELECT vers ion FROM app_vers ion WHERE
vers ion>2.0; SELECT column_y from TEMP_X;
If this same statement was used for
checking the 'version' throughout Although the text of the statements
the application then the literal value are identical the TEMP_X tables are
'2.0' is always the same so this different objects. Hence these are
statement can be considered different versions of the same basic
sharable. statement. There are many things
that determine if two identical SQL
Hard Parse - strings are truly the same statement
If a new SQL statement is issued (and hence can be shared) including:
which does not exist in the shared
pool then this has to be parsed fully. All object names must resolve to the
Eg: Oracle has to allocate memory same actual objects
for the statement from the shared The optimiser goal of the sessions
pool, check the statement issuing the statement should be the
syntactically and semantically etc... same
This is referred to as a hard parse, is
The types and lengths of any bind To give a balanced picture this short
variables should be "similar". (We section describes the benefits of both
don’t discuss the details of this here literal SQL and sharable SQL.
but different types or lengths of bind
variables can cause statements to be Literal SQL
classed as different versions)
The NLS (National Language Support) The Cost Based Optimiser (CBO)
environment which applies to the works best when it has full statistics
statement must be the same and when statements use literals in
their predicates. Consider the
Versions of a statement following:
As described in 'Sharable SQL' if two
statements are textually identical but SELECT distinct cust_ref FROM orders WHERE
total_cost < 10000.0;
cannot be shared then these are
called 'versions' of the same Versus
statement. If Oracle matches to a
statement with many versions it has SELECT distinct cust_ref FROM orders WHERE
to check each version in turn to see if total_cost < :bindA;

it is truly identical to the statement


For the first statement the CBO could
currently being parsed. Hence high
use histogram statistics that have
version counts are best avoided by:
been gathered to decide if it would
be fastest to do a full table scan of
Standardising the maximum bind
ORDERS or to use an index scan on
lengths specified by the client
TOTAL_COST (assuming there is one).
Avoid using identical SQL from lots of
In the second statement CBO has no
different schemas, which use private
idea what percentage of rows fall
objects. Eg: SELECT xx FROM
below ":bindA" as it has no value for
MYTABLE; where each user has their
this bind variable to determine an
own MYTABLE
execution plan . Eg: ":bindA" could be
Setting
0.0 or 99999999999999999.9
_SQLEXEC_PROGRESSION_COST to
'0' in Oracle 8.1
There could be orders of magnitude
difference in the response time
Library Cache and Shared Pool
between the two execution paths so
latches
using the literal statement is
preferable if you want CBO to work
The shared pool latch is used to
out the best execution plan for you.
protect critical operations when
This is typical of Decision Support
allocating and freeing memory in the
Systems where there may not be any
shared pool.
'standard' statements, which are
The library cache latches (and the
issued repeatedly so the chance of
library cache pin latch in Oracle 7.1)
sharing a statement is small. Also the
protect operations within the library
amount of CPU spent on parsing is
cache itself.
typically only a small percentage of
All of these latches are potential
that used to execute each statement
points of contention. The number of
so it is probably more important to
latch gets occurring is influenced
give the optimiser as much
directly by the amount activity in the
information as possible than to
shared pool, especially parse
minimise parse times.
operations. Anything that can
minimise the number of latch gets
Sharable SQL
and indeed the amount of activity in
the shared pool is helpful to both
If an application makes use of literal
performance and scalability.
(unshared) SQL then this can
severely limit scalability and
Literal SQL versus Shared SQL
throughput. The cost of parsing a
new SQL statement is expensive both
in terms of CPU requirements and the
number of times the library cache
and shared pool latches may need to sum(executions) "TotExecs"
FROM v$sqlarea
be acquired and released. WHERE execut ions < 5
GROUP BY substr(sql_text,1,40)
HAVING count(*) > 30
Eg: Even parsing a simple SQL ORDER BY 2 ;
statement may need to acquire a
library cache latch 20 or 30 times. Note: If there is latch contention for
the library cache latches the above
The best approach to take is that all Statement may cause yet further
SQL should be sharable unless it is contention problems.
adhoc or infrequently used SQL The values 40,5 and 30 are example
where it is important to give CBO as values so this query is looking for
much information as possible in order different statements whose first 40
for it to produce a good execution characters are the same which have
plan. only been executed a few times each
and there are at least 30 different
Reducing the load on the Shared Pool occurrences in the shared pool. This
query uses the idea it is common for
Parse Once / Execute Many literal statements to begin "SELECT
col1, col2, col3 FROM table
By far the best approach to use in WHERE..." with the leading portion of
OLTP type applications is to parse a each statement being the same.
statement only once and hold the Note: There is often some degree of
cursor open, executing it as required. resistance to converting literal SQL to
This results in only the initial parse use bind variables. Be assured that it
for each statement (either soft or has been proven time and time again
hard). Obviously there will be some that performing this conversion for
statements which are rarely the most frequently occurring
executed and so maintaining an open statements can eliminate problems
cursor for them is a wasteful with the shared pool and improve
overhead. scalability greatly.

Note that a session only has


<Parameter: OPEN_CURSORS>
Performance Effects
cursors available and holding cursors
open is likely to increase the total Oracle performance can be severely
number of concurrently open cursors. compromised by large volumes of
literal SQL. Some of the symptoms
In precompilers the HOLD_CURSOR that may be noticed are:
parameter controls whether cursors
are held open or not while in OCI • System is CPU bound and exhibits
developers have direct control over an insatiable appetite for CPU.
cursors. • System appears to periodically
“hang” after some period of
Eliminating Literal SQL normal operation.
• Latch contention on shared pool
If you have an existing application it
and library cache latches.
is unlikely that you could eliminate
all literal SQL but you should be • Increasing the shared pool size
prepared to eliminate some if it is delays the problem but it re-
causing problems. By looking at the occurs more severely.
V$SQLAREA view it is possible to see
Identifying the Problem
which literal statements are good
candidates for converting to use bind An Oracle instance suffering from too
variables. The following query that much literal SQL will likely exhibit
shows SQL in the SGA where there some of the symptoms above. There
are a large number of similar are several investigations the DBA
statements: can use to help confirm that this is
indeed happening in the instance.
SELECT substr (sq l _ text ,1 ,40) "SQL" ,
count(*) ,
Library Cache Hit Ratio When this query selects more than 5-
10% of total sessions there is likely
The library cache hit ratio should be very serious performance
very high (98%) when SQL is being degradation taking place and literal
shared and will remain low regardless SQL may be the culprit.
of shared pool sizing adjustments
when SQL is chronically non- Finding Literal SQL
sharable. Use the following query to
We can attempt to locate literal SQL
determine the hit ratios by
in the V$SQL fixed view by grouping
namespace in the library cache.
and counting statements that are
identical up to a certain point based
SELECT namespace on the observation that most literal
,(100*gethitratio ) hit_ratio
FROM v$librarycache; SQL becomes textually distinct
toward the end of the statement (e.g.
in the WHERE clause). The following
The “SQL AREA” namespace will be query returns SQL statements having
the one affected by literal SQL. more than 10 statements that
SQL Parse-to- Execute Ratio textually match on leading substring.

The following query displays the


SELECT S.sql_text
percentage of SQL executed that did FROM v$sql S
not incur an expensive hard parse. ,(select substr(sql_text,1,&&size)
sqltext
Literal SQL will always be fully ,count(*)
parsed, so a low percentage may from v$sql
group by
indicate a literal SQL or other SQL substr(sql_text,1,&&size)
sharing problem. hav ing count(* ) > 10
) D
WHERE substr(S.sql_text,1,&&size) =
SELECT 100 * (1 - D.sqltext;
A.hard_parses/B.executions)
noparse_ratio
FROM The SQL*Plus substitution variable
(select value hard_parses &&size can be adjusted to vary the
from v$sysstat
where name = 'parse count text length used to match
(hard)' ) A statements, as can the value 10 used
,(select value executions
from v$sysstat to filter by level of duplication. Note
where name = 'execute count' ) that this query is expensive and
B; should not be executed frequently on
production systems.
Again, when this ratio is high Oracle
is sparing CPU cycles by avoiding MEMORY FRAGMENTATION –
expensive parsing and when low
there may be a literal SQL problem. The primary problem that occurs is
that free memory in the shared pool
Latch Free Waiters
becomes fragmented into small
A telltale sign that the instance is pieces over time.
suffering library cache and shared Any attempt to allocate a large piece
pool problems is active latch of memory in the shared pool will
contention with sessions waiting on cause large amount of objects in the
the “latch free” wait event. The library cache to be flushed out and
following query will select all current may result in an ORA-4031 out of
sessions waiting for either the shared shared memory error.
pool or library cache latches.
DIAGNOSIS
i) ORA-4031 ERROR
SELECT sid, event, name latch
FROM v$session_wait w One way to diagnose that this is
,v$latch l happening is to look for ORA-4031
WHERE w.event = 'latch free'
AND l.latch# = w.p2 errors being returned from
AND l.name IN (‘shared applications. When an attempt is
pool’,’library cache’);
made to allocate a large contiguous
piece of shared memory, and not
enough contiguous memory can be There is a fixed table called
created in the shared pool, the X$KSMLRU that tracks allocations in
database will signal this error. the shared pool that cause other
Before this error is signalled, all objects in the shared pool to be aged
objects in the shared pool that are out. This fixed table can be used to
not currently pinned or in use will be identify what is causing the large
flushed from the shared pool, and allocation. The columns of this
their memory will be freed and fixed table are the following:
merged. This error only occurs when KSMLRCOM - allocation comment
there is still not a large enough that describes the type of allocation.
contiguous piece of free memory If this comment is something like
after this happens. There may be 'MPCODE' or 'PLSQL%' then there is a
very large amounts of total free large PL/SQL object being loaded into
memory in the shared pool, but just the shared pool. This PL/SQL object
not enough contiguous memory. will need to be 'kept' in the shared
Note: The compiled code for a pool.
package was split into more than If this comment is 'kgltbtab' then the
one-piece, each piece being only allocation is for a dependency table
about 12K in size. So, the 64K in the library cache. This is only a
restriction was lifted; however, problem when several hundred users
packages larger 100K still may have are logged on using distinct user ids.
problems compiling. Furthermore, The solution in this case is to use
with releases 7.2/2.3 of fully qualified names for all table
Oracle7/PLSQL, loading a library unit references. This problem will not
(package, function, and procedure) occur in 7.1.3 or later.
into the shared pool does NOT If you are running MTS and the
require one contiguous piece of comment is something like 'Fixed
memory in the shared pool. This UGA' then the problem is that the
means that chances of getting ORA- init.ora parameter
4031 is dramatically reduced. 'open_cursors' is set too high.
ii) INIT.ORA PARAMETER KSMLRSIZ - amount of contiguous
An init.ora parameter can be set so memory being allocated. Values over
that whenever an ORA-4031 error is around 5K start to be a problem,
signalled a dump will occur into a values over 10K are a serious
trace file. By looking for these trace problem, and values over 20K are
files, the DBA can determine that very serious problems. Anything less
these errors are occurring. This is then 5K should not be a problem.
useful when applications do not KSMLRNUM - number of objects that
always report errors signalled by were flushed from the shared pool in
oracle, or if users do not report the order allocate the memory.
errors to the DBAs. The parameter is KSMLRHON - The name of the object
the following: being loaded into the shared pool if
Event = "4031 trace name the object is a PL/SQL object or a
errorstack" cursor.
This will cause a dump of the oracle KSMLROHV - hash value of object
state objects to occur when this error being loaded
is signalled. By looking in the dump KSMLRSES - SADDR of the session
for that loaded the object.
'Load=X' and then looking up a few The advantage of X$KSMLRU is that
lines for 'name=' you can often tell it allows you to identify problems
whether an object was being loaded with fragmentation that are effecting
into the shared pool when this error performance,
occurred. If an object was being but that are not bad enough to be
loaded then it is likely that this load causing ORA-4031 errors to be
is the cause of the problem and the signalled. If a lot of objects are being
Object should be 'kept' in the shared periodically flushed from the shared
pool. The object being loaded is the pool then this will cause response
object printed after the 'name='. time problems and will likely cause
iii) X$KSMLRU library cache latch contention
Problems when the objects are blocks, then these will need to be put
reloaded into the shared pool. into packages and marked kept.
One unusual thing about the You can determine what large stored
X$KSMLRU fixed table is that the objects are in the shared pool by
contents of the fixed table are erased selecting from the
whenever someone selects from the V$DB_OBJECT_CACHE fixed view. This
fixed table. This is done since the will also tell you which objects have
fixed table stores only the largest been marked kept. This can be done
allocations that have occurred. The with the following query:
values are reset after being selected select * from V$DB_OBJECT_CACHE
so that subsequent large allocations where sharable_mem > 10000;
can be noted even if they were not Note that this query will not catch
quite as large as others that occurred PL/SQL objects that are only rarely
previously. Because of this resetting, used and therefore the PL/SQL object
the output of selecting from this is not currently
table should be carefully noted loaded in the shared pool.
Since it cannot be reselected if it is To determine what large PL/SQL
forgotten. Also you should take care objects are currently loaded in the
that there are not multiple people on shared pool, are not marked ‘kept’,
one database that select from this and therefore may cause a problem,
table because only one of them will execute the following:
select the real data.
Technical Reports Compendium, select name, sharable_mem
from V$DB_OBJECT_CACHE
Volume I, 1996 Shared Pool Internals where sharable_mem > 10000
To monitor this fixed table just runs and (type = 'PACKAGE' or type = 'PACKAGE
BODY' or type = 'FUNCTION'
the following: or type = 'PROCEDURE')
and kept = 'NO';
select * from X$KSMLRU where KSMLRSIZ > 5000;
ii) USE BIND VARIABLES
Another thing that can be done to
ACTION
reduce the amount of fragmentation
i) KEEPING OBJECTS
is to reduce or eliminate the number
The primary source of problems is
of SQL statements in the shared pool
large PL/SQL objects. The means of
that are duplicates of each other
correcting these errors is to 'keep”
except for a constant that is
large PL/SQL objects in the shared
embedded in the statement. The
pool at startup time. This will load
statements should be replaced with
the objects into the shared pool and
one statement that uses a bind
will make sure that the objects are
variable instead of a constant.
never aged out of the shared pool. If
For example:
the objects are never aged out then select * from emp where empno=1;
there will not be a problem with select * from emp where empno=2;
select * from emp where empno=3;
trying to load them and not having
enough memory. Should all be replaced with:
select * from emp where empno=:1;
Objects are 'kept' in the shared pool You can identify statements that
using the dbms_shared_pool package potentially fall into this class with a
that is defined in the dbmspool.sql query like the following:
file. For example: select substr(sql_text, 1, 30) sql, count(*)
copies
from v$sqlarea
exec dbms_shared_pool.keep('SYS.STANDARD');
group by substr(sql_text, 1, 30)
having count(*) > 3;
All large packages that are shipped iii) MAX BIND SIZE
should be 'kept' if the customer uses It is possible for a sql statement to
PL/SQL. This includes 'STANDARD', not be shared because the max bind
'DBMS_STANDARD', and 'DIUTIL'. variable lengths of the bind variables
All large customer packages should in the statement
also be marked 'kept'. do not match. This is automatically
One restriction on the 'keep' taken care of for precompiler
procedure is that it only works on programs and forms programs, but
packages. If the customer has large could be a problem for programs that
procedures or large anonymous directly use OCI. The bind call in OCI
takes two arguments, one is the max open anon;
loop
length of the value, and the other is fetch anon into addr, hash;
a pointer to the actual length. If the exit when anon%notfound;
dbms_shared_pool.keep(addr || ',' ||
current length is always passed in as to_char(hash), 'C');
the max length instead of the max end loop;
end;
possible length for the variable, then
this could cause the sql statement
not to be shared.
To identify statements that might Initialization Parameters
potentially have this problem
execute the following statement: The following Oracle initialization
select sql_text, version_count from v$sqlarea parameters have an important
where version_count > 5; impact on library cache and shared
iv) ELIMINATING LARGE ANONYMOUS pool performance.
PL/SQL
Large anonymous PL/SQL blocks  _KGL_BUCKET_COUNT
should be turned into small  _KGL_LATCH_COUNT
anonymous PL/SQL blocks that call
packaged functions. The  cursor_sharing
packages should be 'kept' in memory.  shared_pool_size
This includes anonymous PL/SQL
 shared_pool_reserved_size
blocks that are used for trigger
definitions. Large anonymous blocks  shared_pool_reserved_min_all
can be identified with the following oc
query:  large_pool_size
select sql_text from v$sqlarea
where command_type=47 -- command type for  large_pool_min_alloc
anonymous block
and length(sql_text) > 500;  parallel_min_message_pool
Note that this query will not catch  backup_io_slaves
PL/SQL blocks that are only rarely  temporary_table_locks
used and therefore the PL/SQL block
is not currently loaded in the shared  dml_locks
pool.  sequence_cache_entries
Another option that can be used
 row_cache_cursors
when an anonymous block cannot be
turned into a package is to mark the  max_enabled_roles
anonymous block with some string so  mts_dispatchers
that it can be identified in
 mts_max_dispatchers
v$sqlarea and marked 'kept'.
For example, instead of using  mts_servers
declare x number;
begin x := 5; end;  mts_max_servers
one can use:
declare /* KEEP_ME */ x number; begin x := 5;  cursor_space_for_time
end;

You can then use the following SUMMARY –


procedure to select these statements
out of the shared pool and mark Here I try to provide some general
them 'kept' using the information regarding shared pool
dbms_shared_pool.keep package. and some internal information
declare
regarding memory structure, I hope
/* DONT_KEEP_ME */ this information will useful for DBA’s,
addr varchar2(10); I also try to provide some information
hash number;
cursor anon is related to application user relation to
select address, hash_value application point of views.
from v$sqlarea
where command_type = 47 -- command type for
anonymous block References
and sql_text like '% KEEP_ME %'
and sql_text not like '%DONT_KEEP_ME%'; 1. "Oracle Internals" Stev Adams
begin 2. Metalink.oracle.com
3. Quest pipeline.

S-ar putea să vă placă și