Monitoring PGA Usage by Username in Oracle Database
Monitoring PGA Usage by Username in Oracle Database
Purpose
V$SESSTAT is the view that holds one statistic value per session, and two of its statistics describe how much Program Global Area (PGA) memory a session uses right now and the most it has used. The script below joins V$SESSTAT to V$STATNAME, filters the sessions of one database user, and keeps only the PGA statistics. The result is a short list: one pair of rows for each session that user has open.
The PGA is the memory that sits behind work such as sorts and hash joins. When a server is short of memory, the first practical question is often "which connections are holding it, and who owns them?" This query answers that question for one user at a time. It does not rank users against each other and it does not apply a threshold. It shows you the numbers, and you decide whether they look normal for that workload.
This guide explains what the PGA is, what each line of the query does, how to read the two rows per session, and what to check next when a value looks too large.
Code
1select
2 st.sid "SID",
3 sn.name "TYPE",
4 ceil(st.value / 1024 / 1024) "MB"
5from v$sesstat st,
6 v$statname sn
7where st.statistic# = sn.statistic#
8 and sid in (
9 select sid
10 from v$session
11 where username like '&user'
12 )
13 and upper(sn.name) like '%PGA%'
14order by st.sid, st.value desc;
15/
Code Breakdown
Columns selected
st.sidis the session identifier. Oracle's reference describes theSIDcolumn ofV$SESSTATas the "Session identifier".sn.nameis the name of the statistic, shown under the headingTYPE.V$STATNAMEholds the name for each statistic number, and Oracle states that the names in theNAMEcolumn "remain stable across Oracle Database releases, and they can be relied on by customer scripts". That is why the script filters on the name and not on a statistic number.ceil(st.value / 1024 / 1024)turns bytes into megabytes and rounds up to the next whole number. The statistic descriptions give both PGA values in bytes, so the division by 1024 twice is correct. Because ofceil, a small non-zero value shows as 1 MB, so the column does not show fine detail for tiny sessions.
Views used
v$sesstatdisplays user session statistics. Its columns areSID,STATISTIC#andVALUE.v$statnamedisplays decoded statistic names for the statistics shown inV$SESSTATandV$SYSSTAT. The joinst.statistic# = sn.statistic#attaches a name to each number.v$sessiondisplays session information for each current session. The script uses it only to turn a user name into a list of session IDs.
Filters
sid in (select sid from v$session where username like '&user')limits the output to the sessions of the user you name. The&userplaceholder is filled in with the value you supply before the query runs. Because the test islike, you can also give a pattern with the%wildcard, so the filter is not strictly limited to a single user.upper(sn.name) like '%PGA%'keeps only statistics whose name contains "PGA". In Oracle's 19c statistic descriptions, two names match:session pga memoryandsession pga memory max.
Ordering
order by st.sid, st.value desc groups the rows by session and puts the larger value first within each session.
What the Output Looks Like
Every session returns two rows. Oracle describes the two statistics this way:
session pga memory: "Current PGA size for the session (in bytes)."session pga memory max: "Peak PGA size for the session (in bytes)."
The peak value is never smaller than the current value, so with the descending sort the session pga memory max row normally comes first for each SID, and the session pga memory row follows. If the two rows are close, the session is near its highest use now. If the current row is much smaller than the peak row, the session grew once and then gave memory back, or at least stopped using it.
Oracle also notes that these two statistics are useful only in V$SESSTAT. They have no meaning in V$SYSSTAT, so do not look for an instance-wide total there.
What the PGA Is
Oracle's Concepts guide defines the PGA as "memory specific to an operating process or thread that is not shared by other processes or threads on the system." The same page adds that "Because the PGA is process-specific, it is never allocated in the SGA." One PGA exists for each server process and background process, and the total of all of them is the instance PGA.
Inside the PGA are work areas. Oracle calls a work area "a private allocation of PGA memory used for memory-intensive operations." A sort operator uses a sort area to sort a set of rows, and a hash join uses a hash area to build a hash table. These are the operations that most often make one session larger than another.
PGA, UGA and sessions
This script reports per-session numbers, so the link between a session and the PGA matters. Oracle defines the User Global Area (UGA) as session memory: "memory allocated for session variables, such as logon information, and other information required by a database session." Where the UGA lives depends on the connection type. With a dedicated server connection, the UGA is stored in the PGA. With a shared server connection, Oracle stores the UGA in the SGA, because the PGA belongs to one process and the session must stay available to any shared server process.
So the PGA is tied to a server process, not to a session as such. On a dedicated server connection the two line up one to one, and the statistic is a direct reading of that session's process. On a shared server system, the session statistic should be read with care, and the process view (see below) is the better place to look for process memory.
Key Points
- The numbers are bytes, converted to MB. Both PGA statistics are reported in bytes. The
ceilcall rounds every value up. - Two rows per session. One row is current use and one is the peak since the session started. Read them as a pair.
- The filter is a pattern.
like '&user'accepts wildcards. If you type a user name with%in it, you may match more than one user. - Only sessions that exist now appear.
V$SESSIONshows each current session, including idle ones. A session that has already ended is gone, and so is its peak value. - No ranking and no limit. The script lists one user's sessions. It does not sort users by memory, and it does not flag anything as too high.
- The view is dynamic.
V$views are the dynamic performance views. They show current instance state, so a result is a snapshot of one moment.
Insights and Best Practices
Run it for the user you already suspect
The query needs a user name, so it fits best after another signal has pointed at an account: an application service user, a batch user, a reporting user. Run it for that user and compare the sessions with each other. One session far above its siblings is a better lead than a high number alone.
Compare current with peak
A large peak with a small current value says the session had a heavy moment and released the memory. A large current value that sits close to the peak says the memory is still in use. The first case points to a past event, such as one big sort. The second points to something happening now, so look at what the session is running.
Look at the instance-wide picture too
Oracle's PGA_AGGREGATE_TARGET parameter "specifies the target aggregate PGA memory available to all server processes attached to the instance." Its documented default is 10 MB or 20% of the size of the SGA, whichever is greater, and you can change it with ALTER SYSTEM. The Concepts guide says individual PGAs can grow as needed up to a target size you set with an initialization parameter, and that the database tunes work area sizes automatically when automatic PGA memory management is enabled. Comparing the sum of your per-session values with this target tells you whether the per-session picture is part of a larger pressure.
Check the work area policy
The WORKAREA_SIZE_POLICY parameter controls how work areas are sized. Its default is AUTO. With AUTO, work areas used by memory-intensive operators are sized automatically from the PGA memory in use, the target in PGA_AGGREGATE_TARGET, and what each operator needs. With MANUAL, sizing follows the *_AREA_SIZE parameters, and Oracle warns that this "may result in sub-optimal performance and poor PGA memory utilization." If a system shows odd PGA behavior, confirm the setting first.
Use the process view for process-level numbers
V$PROCESS displays information about the currently active processes. It has columns PGA_USED_MEM ("PGA memory currently used by the process (in bytes)"), PGA_ALLOC_MEM (memory currently allocated by the process, including free PGA memory not yet released to the operating system) and PGA_MAX_MEM ("Maximum PGA memory ever allocated by the process (in bytes)"). Because the PGA belongs to a process, this view is the natural cross-check for the numbers the script returns.
Repeat the query to see a trend
One run shows one moment. If a session looks large, run the query again after a few minutes and compare. Rising current values for the same SID mean growth. Flat values mean the session has settled.
When to Run This
- When an application user complains about slowness and you want to see how much PGA that user's sessions hold.
- When operating-system memory looks high on the database server and you want to link the load to a database account.
- When you are checking a batch job that runs large sorts or hash joins and want its peak PGA.
- After changing
PGA_AGGREGATE_TARGETorWORKAREA_SIZE_POLICY, to see how the sessions of a key user behave. - When you need a quick answer for one user and do not need a full report.
Troubleshooting Common Issues
The query returns no rows. The user name in &user may be wrong, or that user has no session open right now. Check the spelling against the USERNAME column of V$SESSION, or use % with part of the name.
You see rows for more users than expected. The like test accepts wildcards. A pattern such as APP% matches every user whose name starts with those letters. Use the exact name to match one account.
Values look like 0 or 1. The ceil call rounds up, and small values are shown as 1 MB. For finer detail, remove the division and read the raw byte value from the VALUE column.
Only one of the two rows appears for a session. Check that the join and the %PGA% filter are unchanged. Both statistics have "pga" in the name and both should match.
The numbers do not add up to what the operating system reports. The PGA statistics cover PGA memory only. The V$PROCESS columns PGA_ALLOC_MEM and PGA_USED_MEM differ because allocated memory can include free PGA memory not yet returned to the operating system. Use the process view for the comparison.
The session list changes between runs. V$SESSION shows each current session, so new connections appear and ended ones vanish. Use the SID and compare only sessions present in both runs.
References
- Database Memory Architecture - Oracle Database Concepts 19c - Defines the PGA, the work areas for sorts and hash joins, the UGA, and where the UGA lives for dedicated and shared server connections.
- V$SESSTAT - Oracle Database Reference 19c - Describes the view of user session statistics and its SID, STATISTIC# and VALUE columns.
- V$STATNAME - Oracle Database Reference 19c - Explains that the NAME column holds stable statistic names that scripts can rely on.
- V$SESSION - Oracle Database Reference 19c - Describes the view as session information for each current session and defines the USERNAME column.
- Database Statistics Descriptions - Oracle Database Reference 19c - Defines "session pga memory" and "session pga memory max" and states that both are in bytes.
- V$PROCESS - Oracle Database Reference 19c - Lists the per-process PGA columns PGA_USED_MEM, PGA_ALLOC_MEM and PGA_MAX_MEM.
- PGA_AGGREGATE_TARGET - Oracle Database Reference 19c - Documents the instance-wide PGA target parameter, its default and how to change it.
- WORKAREA_SIZE_POLICY - Oracle Database Reference 19c - Documents the AUTO and MANUAL work area sizing policies.
- Automatic Memory Management (AMM) in Oracle Database 11g Release 1 - oracle-base.com - Notes that Oracle 9i automated PGA management by introducing the PGA_AGGREGATE_TARGET parameter.