Oracle для профессионалов

       

Области PGA и UGA


Как уже было сказано, PGA — это область памяти процесса. Эта область памяти используется одним процессом или одним потоком. Она недоступна ни одному из остальных процессов/потоков в системе. Область PGA обычно выделяется с помощью библиотечного вызова malloc() языка C и со временем может расти (или уменьшаться). Область PGA никогда не входит в состав области SGA — она всегда локально выделяется процессом или потоком.

Область памяти UGA хранит состояние сеанса, поэтому всегда должна быть ему доступна. Местонахождение области UGA зависит исключительно от конфигурации сервера Oracle. Если сконфигурирован режим MTS, область UGA должна находиться в структуре памяти, доступной всем процессам, следовательно, в SGA. В этом случае сеанс сможет использовать любой разделяемый сервер, так как каждый из них сможет прочитать и записать данные сеанса. При подключении к выделенному серверу это требование общего доступа к информации о состоянии сеанса снимается, и область UGA становится почти синонимом PGA, — именно там информация о состоянии сеанса и будет располагаться. Просматривая статистическую информацию о системе, можно обнаружить, что при работе в режиме выделенного сервера область UGA входит в PGA (размер области PGA будет больше или равен размеру используемой памяти UGA — размер UGA будет учитываться при определении размера области PGA).

Размер области PGA/UGA определяют параметры уровня сеанса в файле init.ora: SORT_AREA_SIZE и SORT_AREA_RETAINED_SIZE. Эти два параметра управляют объемом пространства, используемым сервером Oracle для сортировки данных перед сбросом на диск, и определяют объем сегмента памяти, который не будет освобожден по завершении сортировки. SORT_AREA_SIZE обычно выделяется в области PGA, а SORT_AREA_RETAINED_SIZE — в UGA. Управлять размером областей UGA/PGA можно с помощью запроса к специальному представлению V$ сервера Oracle. Эти представления называют также представлениями динамической производительности. Подробнее эти представления V$

рассматриваются в главе 10. С помощью представлений V$ можно определить текущее использование памяти под области PGA и UGA. Например, запущен небольшой тестовый пример, требующий сортировки большого объема данных. Просмотрев несколько первых строк данных, я решил не извлекать остальное результирующее множество. После этого можно сравнить использование памяти "до" и "после":


tkyte@TKYTE816> select a.name, b.value 2 from v$statname a, v$mystat b 3 where a.statistic# = b.statistic# 4 and a.name like '%ga %' 5 /

NAME VALUE ------------------------------ ---------- session uga memory 67532 session uga memory max 71972 session pga memory 144688 session pga memory max 144688

4 rows selected.

Итак, перед началом сортировки в области UGA было около 70 Кбайт данных, а в PGA — порядка 140 Кбайт. Первый вопрос: сколько памяти используется в области PGA помимо UGA? Вопрос нетривиальный и на него нельзя ответить, не зная, подключен ли сеанс к выделенному или к разделяемому серверу; но даже зная это нельзя ответить однозначно. В режиме выделенного сервера область UGA входит в состав PGA. В этом случае порядка 140 Кбайт выделено в области памяти процесса или потока. В режиме MTS область UGA выделяется из SGA, а область PGA относится к разделяемому серверу. Поэтому при работе в режиме MTS к моменту получения последней строки из представленного выше запроса разделяемый серверный процесс уже может использоваться другим сеансом. Соответственно, область PGA уже не принадлежит нам, так что мы используем всего 70 Кбайт памяти (если только не находимся в процессе выполнения запроса, когда областями PGA и UGA суммарно используется 210 Кбайт памяти).

Теперь разберемся, что происходит в областях PGA/UGA нашего сеанса:

tkyte@TKYTE816> show parameter sort_area

NAME TYPE VALUE ------------------------------------ ------- -------------------------- sort_area_retained_size integer 65536 sort_area_size integer 65536

tkyte@TKYTE816> set pagesize 10 tkyte@TKYTE816> set pause on tkyte@TKYTE816> select * from all_objects order by 1, 2, 3, 4;

...(Нажмите Control-C после первой страницы данных) ...

tkyte@TKYTE816> set pause off

tkyte@TKYTE816> select a.name, b.value 2 from v$statname a, v$mystat b 3 where a.statistic# = b.statistic# 4 and a.name like '%ga %' 5 /



NAME VALUE ------------------------------ ---------- session uga memory 67524 session uga memory max 174968 session pga memory 291336 session pga memory max 291336



4 rows selected.

Как видите, памяти использовано больше, поскольку данные сортировались. Область UGA временно увеличилась примерно на размер SORT_AREA_RETAINED_SIZE, а область PGA — немного больше. Для выполнения запроса и сортировки сервер Oracle выделил дополнительные структуры, которые оставлены в памяти сеанса для других запросов. Давайте выполним ту же операцию, изменив значение SORT_AREA_SIZE:

tkyte@TKYTE816> alter session set sort_area_size=1000000;

Session altered.

tkyte@TKYTE816> select a.name, b.value 2 from v$statname a, v$mystat b 3 where a.statistic# = b.statistic# 4 and a.name like '%ga %' 5 /

NAME VALUE ------------------------------ ---------- session uga memory 63288 session uga memory max 174968 session pga memory 291336 session pga memory max 291336

4 rows selected.

tkyte@TKYTE816> show parameter sort_area

NAME TYPE VALUE ------------------------------------ ------- -------------------------- sort_area_retained_size integer 65536 sort_area_size integer 1000000

tkyte@TKYTE816> select * from all_objects order by 1, 2, 3, 4;

...(Нажмите Control-C после первой страницы данных) ...

tkyte@TKYTE816> set pause off

tkyte@TKYTE816> select a.name, b.value 2 from v$statname a, v$mystat b 3 where a.statistic# = b.statistic# 4 and a.name like '%ga %' 5 / NAME VALUE ------------------------------ ---------- session uga memory 67528 session uga memory max 174968 session pga memory 1307580 session pga memory max 1307580

4 rows selected.

Как видите, в этот раз область PGA увеличилась существенно. Примерно на 1000000 байт, в соответствии с заданным значением SORT_AREA_SIZE. Интересно отметить, что в этот раз размер области UGA вообще не изменился. Для ее изменения надо задать другое значение SORT_AREA_RETAINED_SIZE, как показано ниже:

tkyte@TKYTE816> alter session set sort_area_retained_size=1000000; Session altered.

tkyte@TKYTE816> select a.name, b.value 2 from v$statname a, v$mystat b 3 where a.statistic# = b.statistic# 4 and a.name like '%ga %' 5 /



NAME VALUE ------------------------------ ---------- session uga memory 63288 session uga memory max 174968 session pga memory 1307580 session pga memory max 1307580

4 rows selected.

tkyte@TKYTE816> show parameter sort_area

NAME TYPE VALUE ------------------------------------ ------- -------------------------- sort_area_retained_size integer 1000000 sort_area_size integer 1000000

tkyte@TKYTE816> select * from all_objects order by 1, 2, 3, 4;

...(Нажмите Control-C после первой страницы данных) ...

tkyte@TKYTE816> select a.name, b.value 2 from v$statname a, v$mystat b 3 where a.statistic# = b.statistic# 4 and a.name like '%ga %' 5 /

NAME VALUE ------------------------------ ---------- session uga memory 66344 session uga memory max 1086120 session pga memory 1469192 session pga memory max 1469192

4 rows selected.

Теперь мы видим, что существенное увеличение размера области UGA связано с необходимостью дополнительно принять данные размером SORT_AREA_RETAINED_SIZE. В ходе обработки запроса 1 Мбайт сортируемых данных "кеширован в памяти". Остальные данные были на диске (где-то во временном сегменте). По завершении выполнения запроса это дисковое пространство возвращено для использования другими сеансами. Обратите внимание, что область PGA не уменьшилась до прежнего размера. Этого следовало ожидать, поскольку область PGA используется как "куча" и состоит из фрагментов, выделенных с помощью вызовов malloc(). Некоторые процессы в сервере Oracle явно освобождают память PGA, другие же оставляют выделенную память в куче (область для сортировки, например, остается в куче). Сжатие кучи при этом обычно ничего не дает (размер используемой процессами памяти только растет). Поскольку область UGA является своего рода "подкучей" (ее "родительской" кучей является область PGA либо SGA), она может сжиматься. При необходимости можно принудительно сжать область PGA:

tkyte@TKYTE816> exec dbms_session.free_unused_user_memory;

PL/SQL procedure successfully completed.



tkyte@TKYTE816> select a.name, b.value 2 from v$statname a, v$mystat b 3 where a.statistic# = b.statistic# 4 and a.name like '%ga %' 5 /

NAME VALUE ------------------------------ ---------- session uga memory 73748 session uga memory max 1086120 session pga memory 183360 session pga memory max 1469192

Учтите, однако, что в большинстве систем это действие — пустая трата времени. Можно уменьшить размер кучи PGA в рамках экземпляра Oracle, но память при этом операционной системе не возвращается. В зависимости от принятого в ОС метода управления памятью, суммарное количество используемой памяти даже увеличится. Все зависит от того, как на данной платформе реализованы функции malloc(), free(), realloc(), brk() и sbrk() (стандартные функции управления памятью в языке C).

Итак, мы рассмотрели две структуры памяти, области PGA и UGA. Теперь понятно, что область PGA принадлежит процессу. Она представляет собой набор переменных, необходимых выделенному или разделяемому серверному процессу Oracle для поддержки сеанса. Область PGA — это "куча" памяти, в которой могут выделяться другие структуры. Область UGA также является кучей, в которой определяются связанные с сеансом структуры. Область UGA выделяется из PGA при подключении к выделенному серверу Oracle и — из области SGA при подключении в режиме MTS. Это означает, что при работе в режиме MTS необходимо задать такой размер области SGA, чтобы в ней хватило места под области UGA для предполагаемого максимального количества одновременно подключенных к базе данных пользователей. Поэтому область SGA в экземпляре, работающем в режиме MTS, обычно намного больше, чем область SGA аналогично сконфигурированного экземпляра, работающего в режиме выделенного сервера.


Содержание раздела