|
| 1 | +--- |
| 2 | +layout: post |
| 3 | +title: "Demystifying Oracle Memory Management: A Practical Guide to Optimizing SGA and PGA" |
| 4 | +excerpt: "This article tackles a core pain point for many DBAs: the confusion surrounding SGA and PGA tuning, which often leads to wasted resources or critical errors like ORA-04031. We will demystify the internal workings of SGA and PGA and provide a systematic, data-driven methodology for optimization, moving you from guesswork to precise configuration." |
| 5 | +date: 2025-08-28 09:30:00 +0800 |
| 6 | +categories: [Oracle, Performance Tuning, Memory Management] |
| 7 | +tags: [Oracle, DBA, SGA, PGA, ORA-04031, Performance Tuning, v$sga_target_advice, v$pga_target_advice, AMM, ASMM] |
| 8 | +author: Shane |
| 9 | +image: /assets/images/posts/oracle_execution_plan_overview.svg |
| 10 | +--- |
| 11 | + |
| 12 | +The performance of an Oracle database is heavily dependent on its memory configuration. However, the SGA and PGA often feel like a black box—tune it too large, and you risk wasting resources; tune it too small, and you risk a crash. Have you ever been stumped by an `ORA-04031` error? Don't worry, this journey into memory exploration will guide you out of the confusion. This article will start from the internal principles of SGA and PGA, culminating in a quantifiable, data-driven optimization methodology to end the guesswork in memory tuning. |
| 13 | + |
| 14 | +### I. SGA and PGA: The Heart and Brain of the Database |
| 15 | + |
| 16 | +In the world of Oracle, memory is the lifeline of performance. All data processing, SQL parsing, and transaction recording rely on memory. The two most important players in this arena are the SGA (System Global Area) and the PGA (Program Global Area). |
| 17 | + |
| 18 | +#### 1. SGA (System Global Area): The Shared Central Hub |
| 19 | + |
| 20 | +The SGA is a large block of shared memory allocated when an Oracle instance starts up, accessible to all database processes. You can think of it as a company's central operations hall, where various departments (processes) share resources and work together. |
| 21 | + |
| 22 | +* **Concept Deep Dive -> Principle Analysis** |
| 23 | + * **Database Buffer Cache**: This is the largest and most crucial component of the SGA. It's the busiest "public reading room" in our operations hall analogy. When a user needs to read data, Oracle first checks here. If the data is found (a cache hit), it's returned directly from memory, avoiding costly disk I/O. If not found, the data is read from disk and placed into the Buffer Cache for future use. A well-configured Buffer Cache can significantly improve read/write performance. |
| 24 | + * **Shared Pool**: This is the company's "central conference room and archive." It primarily caches two things: execution plans for SQL and PL/SQL code (Library Cache) and data dictionary information (Data Dictionary Cache). When an SQL statement is submitted, Oracle first looks in the Shared Pool for an identical execution plan. If one exists, it's reused, saving the cost of reparsing and optimization—a process known as a "soft parse." A heavily fragmented or undersized Shared Pool can lead to numerous "hard parses," which severely consume CPU. |
| 25 | + * **Log Buffer**: This is the company's "outgoing mail tray." Redo information generated by all DML operations (INSERT, UPDATE, DELETE) is quickly written to this buffer and then written in batches to the redo log files by the LGWR process. It generally doesn't need to be very large, but an appropriately sized Log Buffer is vital for high-concurrency DML systems. |
| 26 | + * **Large Pool**: This is an optional "multi-purpose hall" reserved for operations that require large, contiguous chunks of memory, such as RMAN backups and parallel queries. Separating it from the Shared Pool helps prevent fragmentation. |
| 27 | + |
| 28 | +* **Tuning Practice / Problem Diagnosis** |
| 29 | + A common misconception is that a larger SGA always equals better performance. However, an oversized SGA can not only waste physical memory but also introduce negative effects due to management overhead. We need data to guide our decisions. |
| 30 | + |
| 31 | +#### 2. PGA (Program Global Area): The Private Office |
| 32 | + |
| 33 | +Unlike the "shared" nature of the SGA, the PGA is a private memory area allocated for each server process, and they do not interfere with each other. You can imagine it as a private office assigned to each employee in the company. |
| 34 | + |
| 35 | +* **Concept Deep Dive -> Principle Analysis** |
| 36 | + When your SQL needs to perform sorting (`ORDER BY`, `GROUP BY`) or hash joins, these operations can be completed efficiently in memory (Optimal Execution) if enough PGA memory is allocated. If the PGA is insufficient, Oracle must use the temporary tablespace on disk, leading to "one-pass" or even "multi-pass" executions, which drastically degrade performance. |
| 37 | + |
| 38 | +* **Tuning Practice / Problem Diagnosis** |
| 39 | + Another common mistake is to think that the bigger the PGA, the better. But remember, the total PGA consumption is `pga_aggregate_target` multiplied by the number of concurrent processes. An out-of-control PGA configuration can easily exhaust all server memory. We need to find a balance between performance and resource consumption. |
| 40 | + |
| 41 | +### II. Automatic or Manual? AMM vs. ASMM |
| 42 | + |
| 43 | +Oracle provides two main automatic memory management mechanisms to free DBAs from tedious manual parameter tuning. |
| 44 | + |
| 45 | +* **Automatic Memory Management (AMM)**: Enabled by setting the `MEMORY_TARGET` and `MEMORY_MAX_TARGET` parameters. Oracle dynamically adjusts memory allocation between the SGA and PGA. It's like "full self-driving"—simple and convenient, suitable for systems with relatively stable workloads. |
| 46 | +* **Automatic Shared Memory Management (ASMM)**: Enabled by setting `SGA_TARGET` and `PGA_AGGREGATE_TARGET`. Oracle only dynamically adjusts memory among the internal components of the SGA (like Buffer Cache, Shared Pool), while the PGA size is controlled independently by `PGA_AGGREGATE_TARGET`. This is more like "assisted driving," giving the DBA more control over the total SGA and PGA sizes. |
| 47 | + |
| 48 | +**In my personal experience, I recommend using ASMM in the vast majority of production environments.** It strikes a better balance between stability and flexibility, avoiding the intense memory "contention" between SGA and PGA that can occur under extreme loads with AMM, thus providing more predictable performance. |
| 49 | + |
| 50 | +* **Practical Demo**: How to check the current memory management mode? |
| 51 | + |
| 52 | +```sql |
| 53 | +-- Oracle 19c |
| 54 | +-- Check the values of MEMORY_TARGET, SGA_TARGET, and PGA_AGGREGATE_TARGET |
| 55 | +SHOW PARAMETER TARGET; |
| 56 | + |
| 57 | +NAME TYPE VALUE |
| 58 | +------------------------------------ ----------- ------------------------------ |
| 59 | +archive_lag_target integer 0 |
| 60 | +db_big_table_cache_percent_target string 0 |
| 61 | +db_flashback_retention_target integer 720 |
| 62 | +fast_start_io_target integer 0 |
| 63 | +fast_start_mttr_target integer 0 |
| 64 | +memory_max_target big integer 0 |
| 65 | +memory_target big integer 0 |
| 66 | +parallel_servers_target integer 768 |
| 67 | +pga_aggregate_target big integer 10G |
| 68 | +sga_target big integer 40G |
| 69 | +target_pdbs integer 0 |
| 70 | + |
| 71 | +-- Logical check: |
| 72 | +-- 1. If MEMORY_TARGET is set to a non-zero value, it's in AMM mode. |
| 73 | +-- 2. If MEMORY_TARGET is 0 and SGA_TARGET is non-zero, it's in ASMM mode. |
| 74 | +-- 3. If all three are 0, it's in manual management mode (highly discouraged). |
| 75 | +``` |
| 76 | + |
| 77 | +### III. Data-Driven Decisions: Let the Advisor Views Guide You |
| 78 | + |
| 79 | +Guesswork has no place in database optimization. Oracle provides a series of powerful "Advisor Views" that offer precise tuning recommendations based on real workload data collected since the instance started. |
| 80 | + |
| 81 | +#### 1. SGA Target Advisor (`v$sga_target_advice`) |
| 82 | + |
| 83 | +This view predicts the impact of different `SGA_TARGET` sizes on the database's total physical reads (and consequently, DB Time). |
| 84 | + |
| 85 | +* **Practical Demo** |
| 86 | + |
| 87 | +```sql |
| 88 | +-- Predict the benefit of adjusting SGA size |
| 89 | +-- ESTD_DB_TIME is the estimated DB Time, ESTD_PHYSICAL_READS are estimated physical reads |
| 90 | +SELECT |
| 91 | + sga_size, |
| 92 | + sga_size_factor, |
| 93 | + estd_db_time, |
| 94 | + estd_physical_reads |
| 95 | +FROM |
| 96 | + v$sga_target_advice |
| 97 | +ORDER BY |
| 98 | + sga_size_factor; |
| 99 | + |
| 100 | + SGA_SIZE SGA_SIZE_FACTOR ESTD_DB_TIME ESTD_PHYSICAL_READS |
| 101 | +---------- --------------- ------------ ------------------- |
| 102 | + 15360 .375 57884978 9.8523E+10 |
| 103 | + 20480 .5 40363977 4.5410E+10 |
| 104 | + 25600 .625 31660469 1.8920E+10 |
| 105 | + 30720 .75 29475772 1.2152E+10 |
| 106 | + 35840 .875 28610035 9647829746 |
| 107 | + 40960 1 27139096 5163132691 |
| 108 | + 46080 1.125 26354776 2766922809 |
| 109 | + 51200 1.25 26270645 2397242508 |
| 110 | + 56320 1.375 26251648 2397242508 |
| 111 | + 61440 1.5 26248934 2162836284 |
| 112 | + 66560 1.625 26248934 1770438200 |
| 113 | + 71680 1.75 26246220 1345512379 |
| 114 | + 76800 1.875 26243506 1181324760 |
| 115 | + 81920 2 26243506 1181324760 |
| 116 | + |
| 117 | +14 rows selected. |
| 118 | + |
| 119 | +``` |
| 120 | +**Interpreting the Results**: Focus on the row where `SGA_SIZE_FACTOR` is 1; this is your current configuration. See if increasing `SGA_SIZE` (`SGA_SIZE_FACTOR` > 1) significantly reduces `ESTD_DB_TIME`. If doubling the SGA only decreases DB Time by 1%, the return on investment is low. Conversely, if reducing the SGA by 20% causes DB Time to spike, your current SGA configuration may be insufficient. |
| 121 | + |
| 122 | +#### 2. PGA Target Advisor (`v$pga_target_advice`) |
| 123 | + |
| 124 | +This view helps assess whether the `PGA_AGGREGATE_TARGET` is set appropriately. |
| 125 | + |
| 126 | +* **Practical Demo** |
| 127 | + |
| 128 | +```sql |
| 129 | +-- Evaluate PGA size setting |
| 130 | +-- ESTD_PGA_CACHE_HIT_PERCENTAGE: Estimated PGA cache hit percentage |
| 131 | +-- ESTD_OVERALLOC_COUNT: Estimated number of PGA overallocations |
| 132 | +SELECT |
| 133 | + pga_target_for_estimate / 1024 / 1024 AS target_mb, |
| 134 | + pga_target_factor, |
| 135 | + advice_status, |
| 136 | + estd_pga_cache_hit_percentage, |
| 137 | + estd_overalloc_count |
| 138 | +FROM |
| 139 | + v$pga_target_advice; |
| 140 | + |
| 141 | + TARGET_MB PGA_TARGET_FACTOR ADV ESTD_PGA_CACHE_HIT_PERCENTAGE ESTD_OVERALLOC_COUNT |
| 142 | +---------- ----------------- --- ----------------------------- -------------------- |
| 143 | + 1280 .125 ON 53 1694600 |
| 144 | + 2560 .25 ON 53 1694587 |
| 145 | + 5120 .5 ON 55 1521626 |
| 146 | + 7680 .75 ON 66 1036977 |
| 147 | + 10240 1 ON 99 127685 |
| 148 | + 12288 1.2 ON 100 461 |
| 149 | + 14336 1.4 ON 100 141 |
| 150 | + 16384 1.6 ON 100 4 |
| 151 | + 18432 1.8 ON 100 0 |
| 152 | + 20480 2 ON 100 0 |
| 153 | + 30720 3 ON 100 0 |
| 154 | + 40960 4 ON 100 0 |
| 155 | + 61440 6 ON 100 0 |
| 156 | + 81920 8 ON 100 0 |
| 157 | + |
| 158 | +14 rows selected. |
| 159 | + |
| 160 | +``` |
| 161 | + |
| 162 | +**Interpreting the Results**: The goal is to get `ESTD_PGA_CACHE_HIT_PERCENTAGE` as close to 100% as possible, while keeping `ESTD_OVERALLOC_COUNT` (PGA memory overallocation, which can cause system instability) at 0. If the hit percentage for your current configuration (`PGA_TARGET_FACTOR`=1) is low, consider increasing `PGA_AGGREGATE_TARGET` based on the recommendations for rows with a larger factor. |
| 163 | + |
| 164 | +#### 3. Other Key Views |
| 165 | + |
| 166 | +* **`v$pgastat`**: Provides a snapshot of current PGA memory usage. |
| 167 | + |
| 168 | +```sql |
| 169 | +-- Check PGA memory usage statistics |
| 170 | +SELECT name, value/1024/1024 as value_mb, unit FROM v$pgastat; |
| 171 | + |
| 172 | +NAME VALUE_MB UNIT |
| 173 | +--------------------------------------- ---------- ------- |
| 174 | +aggregate PGA target parameter 10240 bytes |
| 175 | +aggregate PGA auto target 640 bytes |
| 176 | +global memory bound 1023.99414 bytes |
| 177 | +total PGA inuse 11122.7998 bytes |
| 178 | +total PGA allocated 11959.834 bytes |
| 179 | +maximum PGA allocated 18023.3662 bytes |
| 180 | +total freeable PGA memory 501.375 bytes |
| 181 | +MGA allocated (under PGA) 1236 bytes |
| 182 | +maximum MGA allocated 1236 bytes |
| 183 | +process count .00057888 |
| 184 | +max processes count .000677109 |
| 185 | +PGA memory freed back to OS 716819546 bytes |
| 186 | +total PGA used for auto workareas .96875 bytes |
| 187 | +maximum PGA used for auto workareas 6710.36914 bytes |
| 188 | +total PGA used for manual workareas 0 bytes |
| 189 | +maximum PGA used for manual workareas 28.21875 bytes |
| 190 | +over allocation count .401830673 |
| 191 | +bytes processed 294570439 bytes |
| 192 | +extra bytes read/written 3046394.24 bytes |
| 193 | +cache hit percentage .000094385 percent |
| 194 | +recompute count (total) 6.36017418 |
| 195 | + |
| 196 | +21 rows selected. |
| 197 | + |
| 198 | +-- Key Metrics: |
| 199 | +-- 'aggregate PGA target parameter': Current PGA_AGGREGATE_TARGET setting |
| 200 | +-- 'total PGA allocated': Total PGA currently allocated |
| 201 | +-- 'maximum PGA allocated': Peak PGA allocation since instance startup |
| 202 | +``` |
| 203 | +This view helps you determine if the peak PGA usage is approaching or exceeding your target value. |
| 204 | + |
| 205 | +* **`v$sga_dynamic_components`**: Shows how the sizes of SGA components have changed under ASMM. |
| 206 | + |
| 207 | +```sql |
| 208 | +-- View dynamic resizing of SGA components |
| 209 | +SELECT |
| 210 | + component, |
| 211 | + current_size / 1024 / 1024 AS current_size_mb, |
| 212 | + min_size / 1024 / 1024 AS min_size_mb, |
| 213 | + max_size / 1024 / 1024 AS max_size_mb, |
| 214 | + last_oper_type || ' ' || last_oper_mode AS last_operation |
| 215 | +FROM |
| 216 | + v$sga_dynamic_components |
| 217 | +WHERE |
| 218 | + current_size > 0; |
| 219 | + |
| 220 | + |
| 221 | +COMPONENT CURRENT_SIZE_MB MIN_SIZE_MB MAX_SIZE_MB LAST_OPERATION |
| 222 | +------------------------ --------------- ----------- ----------- ---------------- |
| 223 | +shared pool 7680 6912 8704 GROW DEFERRED |
| 224 | +large pool 640 640 640 STATIC |
| 225 | +java pool 128 128 128 STATIC |
| 226 | +streams pool 128 128 256 SHRINK DEFERRED |
| 227 | +DEFAULT buffer cache 32128 30976 32896 SHRINK DEFERRED |
| 228 | +Shared IO Pool 128 128 128 STATIC |
| 229 | + |
| 230 | +6 rows selected. |
| 231 | +``` |
| 232 | +This helps you understand how ASMM is reallocating memory internally. |
| 233 | + |
| 234 | +### IV. Classic Troubleshooting: Dissecting ORA-04031 |
| 235 | + |
| 236 | +`ORA-04031: unable to allocate X bytes of shared memory` is one of the most dreaded errors for a DBA. It typically points to insufficient space or severe fragmentation in the Shared Pool. |
| 237 | + |
| 238 | +* **Root Cause Analysis**: |
| 239 | + 1. **Shared Pool is too small**: An improperly set `SGA_TARGET` leaves the Shared Pool with insufficient memory for current SQL parsing and data dictionary caching needs. |
| 240 | + 2. **Severe Fragmentation**: A large volume of SQL without bind variables (leading to hard parses) creates many non-shareable execution plans. These quickly fill up and fragment the Shared Pool, making it impossible to find a large enough *contiguous* block of memory for new requests, even if the total free space is adequate. |
| 241 | + 3. **Bugs or Memory Leaks**: In rare cases, it could be an Oracle bug. |
| 242 | + |
| 243 | +* **Troubleshooting and Resolution**: |
| 244 | + 1. **Immediate Fix**: `ALTER SYSTEM FLUSH SHARED_POOL;` can provide temporary relief, but it's a bandage solution. It clears all cached execution plans, causing performance fluctuations as they are rebuilt. |
| 245 | + 2. **Permanent Solution**: |
| 246 | + * **Promote Bind Variables**: This is paramount. Review application code to ensure all SQL uses bind variables, reducing hard parses at the source. You can query `v$sqlarea` to find SQL with low `EXECUTIONS` but high `VERSION_COUNT`. |
| 247 | + * **Proper Configuration**: Increase `SGA_TARGET` based on recommendations from `v$sga_target_advice`. |
| 248 | + * **Use Cursor Caching**: Setting the `SESSION_CACHED_CURSORS` parameter can cache session-level cursors, reducing the overhead of soft parses. |
| 249 | + |
| 250 | +### Conclusion |
| 251 | + |
| 252 | +Oracle memory management is not arcane magic. The key lies in understanding the synergy between SGA and PGA and shifting from experience-based tuning to a data-driven approach. |
| 253 | + |
| 254 | +* **Understanding is Fundamental**: Knowing the roles of the Buffer Cache, Shared Pool, and PGA is the prerequisite for making sound decisions. |
| 255 | +* **Advisors are the Scientific Method**: Stop guessing. Learn to use views like `v$sga_target_advice` and `v$pga_target_advice` to let Oracle provide data-backed tuning suggestions. |
| 256 | +* **Solving Problems is the Goal**: Use typical issues like `ORA-04031` as a starting point to trace back and identify bottlenecks and inefficiencies in your system's memory usage. |
| 257 | + |
| 258 | +Memory optimization is a continuous cycle of monitoring, analysis, and adjustment, not a one-time task. Incorporate the methods from this article into your daily operations, and your database will reward you with more stable and robust performance. |
0 commit comments