Oracle DB: Управление памятью

Материал из sysadm
Перейти к навигации Перейти к поиску

Ссылки по теме:

Linux HugePages

Ссылки по теме


Размер обычной страницы памяти 4 Кб, это создает большие накладные расходы, снижает производительность и значительный объем памяти тратится на огромные таблицы страниц памяти. Ядро линукс поддерживает работу с HudgePages, размер которых может быть 2 Мб, а с аппаратной поддержкой размер страницы может быть 1 ГБ.

Важные факты

  • Automatic Memory Management (AMM) - не совместим с Linux HugePages, не может управлять памятью более 4ГБ, поэтому этот режим можно применять только на очень мелких и не важных базах
  • Automatic Shared Memory Management (ASMM) и Automatic PGA Management - совместимы с HugePages.
  • Паять связанная с HudgePages не может быть выгружена в swap, поэтому SGA вынуждена постоянно находиться в памяти
  • Использование HudgePages значительно повышает производительность Oracle 11g и выше, поэтому использовать это практически обязательно

Сам по себе большой SGA не создает проблем, но в сочетании с большим количеством сессий, размер таблицы памяти может стать слишком большим, что значительно снизит производительность

# определение размера таблиц памяти
grep PageTables /proc/meminfo

# проверка использования HudgePages
grep Huge /proc/meminfo

Параметры инстанции

use_large_pages = TRUE | FALSE
# по умолчанию TRUE
# TRUE применимо только к платформе Linux, хотя FALSE может привести к деградации производительности и на других платформах


Скрипт для вычисления определения оптимальной конфигурации

  • скрипт использует команду ipcs -m, которая выводит список сегментов разделяемой памяти и их размеры
  • определяет количество HudgePages страниц необходимых для размещения каждого сегмента и суммирует их
#!/bin/bash
#
# hugepages_setting.sh
#
# Linux bash script to compute values for the
# recommended HugePages/HugeTLB configuration
#
# Note: This script does calculation for all shared memory
# segments available when the script is run, no matter it
# is an Oracle RDBMS shared memory segment or not.
# Check for the kernel version
KERN=`uname -r | awk -F. '{ printf("%d.%d\n",$1,$2); }'`
# Find out the HugePage size
HPG_SZ=`grep Hugepagesize /proc/meminfo | awk {'print $2'}`
# Start from 1 pages to be on the safe side and guarantee 1 free HugePage
NUM_PG=1
# Cumulative number of pages required to handle the running shared memory segments
for SEG_BYTES in `ipcs -m | awk {'print $5'} | grep "[0-9][0-9]*"`
do
   MIN_PG=`echo "$SEG_BYTES/($HPG_SZ*1024)" | bc -q`
   if [ $MIN_PG -gt 0 ]; then
      NUM_PG=`echo "$NUM_PG+$MIN_PG+1" | bc -q`
   fi
done
# Finish with results
case $KERN in
   '2.4') HUGETLB_POOL=`echo "$NUM_PG*$HPG_SZ/1024" | bc -q`;
          echo "Recommended setting: vm.hugetlb_pool = $HUGETLB_POOL" ;;
   '2.6' | '3.8' | '3.10' | '4.1' | '4.14' ) echo "Recommended setting: vm.nr_hugepages = $NUM_PG" ;;
    *) echo "Unrecognized kernel version $KERN. Exiting." ;;
esac
# End

AMM (Automatic Memory Management)

AMM (Automatic Memory Management) - автоматическое управление памятью

Механизм AMM используют статистики, поэтому параметр инициализации STATISTIC_LEVEL должен быть установлен в значение TYPICAL или ALL.

  • memory_target - задает общий размер выделяемой для Oracle DB памяти в рамках которой AMM её автоматически распределяет. Данный параметр можно изменять динамически без остановки инстанции.
  • memory_max_target - задает верхний предел для memory_target. Данный параметр нельзя изменить динамически, необходим перезапуск инстанции.
alter system set memory_target      = 2G scope=both;    # можно менять динамически
alter system set memory_max_target  = 4G scope=spfile;

AMM включается только если задан параметр memory_target.

alter system set memory_target        = 2G  scope=spfile;
alter system set sga_target           = 0   scope=spfile;
alter system set pga_aggregate_target = 0   scope=spfile;

-- дополнительно можно задать верхний лимит, если не задан, то считается равным memory_target
alter system set memory_max_target    = 4G scope=spfile;

-- поскольку область применения spfile, то изменения вступят в силу только после перезапуска инстанции

Назначение параметров управления памятью при включенном AMM

  • sga_target - определяет границу ниже которой AMM не может задавать размер SGA
  • pga_aggregate_target - определяет границу ниже которой AMM не может задавать размер PGA
  • sga_max_size - определяет границу выше которой AMM не должен задавать размер SGA

Чтобы рост SGA не приводил к снижению PGA можно зафиксировать размер SGA задав одинаковые значения для sga_target и sga_max_size.

ASMM (Automatic Shared Memory Management)

ASMM (Automatic Shared Memory Management) - автоматическое управление разделяемой памятью

Механизм ASMM используют статистики, поэтому параметр инициализации STATISTICS_LEVEL должен быть установлен в значение TYPICAL или ALL.

ASMM включается заданием параметра sga_target.

ASMM автоматически управляет параметрами

  • SHARED_POOL_SIZE
  • LARGE_POOL_SIZE
  • JAVA_POOL_SIZE
  • DB_CACHE_SIZE
  • STREAMS_POOL_SIZE

Если включен ASMM, то значения данных параметров заданных вручную определяют нижнюю границу выделения памяти для соответствующих областей.

Параметры, которые не управляются автоматически, необходимо задавать вручную

  • LOG_BUFFER
  • DB_KEEP_CACHE_SIZE
  • DB_RECYCLE_CACHE_SIZE
  • DB_nK_CACHE_SIZE

Сумма значений данных параметров вычитается из sga_target.

Automatic PGA Management

Параметры

  • pga_aggregate_limit - предел, выше которого не может вырасти суммарный PGA инстанции (отсутствует в 11.2.0.4, нужно уточнить в какой версии появился)
  • pga_aggregate_target - целевое значение суммарного PGA инстанции к которому будет стремиться Automatic PGA Management, динамически управляя персональными областями PGA серверных процессов сессий и фоновых процессов

Реальный размер суммарного PGA (PGA Allocated) может значительно отличаться от pga_aggregate_target как в большую так и в меньшую сторону, т.к. зависит не только от размеров PGA отдельных процессов, но и от их количества.

Для ручного управления PGA необходимо определять размеры PGA для каждого типа запроса, это поддерживается, но не рекомендуется.

System Global Area (SGA)

SGA - это общая область памяти, которую используют все процессы инстанции

Program Global Area (PGA)

PGA - это совокупность областей памяти, выделяемых серверным процессам сессий и фоновым процессам инстанции, которые принадлежат только своим процессам и не разделяются между ними.

Типы приложений

Типы приложений

  • OLTP (Online Transaction Processing) - приоритет на онлайн транзакции
  • DWH (Data Warehouse) - хранилище данных, приоритет на обработку больших объемов данных

Общие рекомендации

Для OLTP приложения:

  • 60% SGA_TARGET
  • 40% PGA_AGGREGATE_TARGET

Для DWH приложения:

  • 40% SGA_TARGET
  • 60% PGA_AGGREGATE_TARGET

Системные таблицы и представления

  • sys.v$parameter - текущие параметры
  • sys.v$osstat - ресурсы ОС
  • sys.v$sga_dynamic_components - текущее распределение памяти назначенное AMM
-- история динамического изменения параметров памяти
sys.V$MEMORY_RESIZE_OPS

-- история динамического изменения параметров памяти
sys.V$SGA_RESIZE_OPS

Параметры с префиксом "__" определяют текущее значение и могут отличаться от аналогичного параметра без этого префикса, который задает значение при старте инстанции

__db_cache_size - текущее значение
db_cache_size - начальное значение заданное в spfile/pfile

Пример скрипта для расчета значений параметров

DECLARE
    os_memory            number;
    granule_size         number;
    memory_target        number;
    sga_target           number;
    pga_aggregate_target number;
    iname                varchar2(16);
BEGIN
 
    SELECT VALUE/1024/1024/1024 into os_memory
    FROM   v$osstat
    WHERE  stat_name = 'PHYSICAL_MEMORY_BYTES';
    os_memory := ceil(os_memory) * 1024;
      
    -- for os_memory  <  10GB set only memory_target  
    -- os_memory :=  10*1024;   --  10GB
    -- os_memory :=  12*1024;   --  12GB
    -- os_memory :=  16*1024;   --  16GB
    -- os_memory :=  18*1024;   --  18GB
    -- os_memory :=  20*1024;   --  20GB
    -- os_memory :=  24*1024;   --  24GB
    -- os_memory :=  32*1024;   --  32GB
    -- os_memory :=  48*1024;   --  48GB
    -- os_memory :=  64*1024;   --  64GB
    -- os_memory := 100*1024;   -- 100GB
    -- os_memory := 128*1024;   -- 128GB
    -- os_memory := 192*1024;   -- 192GB
    -- os_memory := 256*1024;   -- 256GB

    select granule_size/1024/1024 into granule_size
    from v$sga_dynamic_components
    where component='DEFAULT buffer cache';
  
    select instance_name into iname from v$instance;

    if os_memory > 16384 then
       memory_target := os_memory - 4096;
    else
       memory_target := os_memory * 0.8;
    end if;

    sga_target := (memory_target * 0.6);
    sga_target := ceil(sga_target/granule_size)*granule_size;

    memory_target := ceil(memory_target/granule_size)*granule_size;

    pga_aggregate_target := memory_target - sga_target;

    DBMS_OUTPUT.PUT_LINE( '--'||os_memory/1024||'GB' );
    DBMS_OUTPUT.PUT_LINE( 'alter system reset "__db_cache_size"         scope=spfile sid='''||iname||''';' );
    DBMS_OUTPUT.PUT_LINE( 'alter system reset "__java_pool_size"        scope=spfile sid='''||iname||''';' );
    DBMS_OUTPUT.PUT_LINE( 'alter system reset "__large_pool_size"       scope=spfile sid='''||iname||''';' );
    DBMS_OUTPUT.PUT_LINE( 'alter system reset "__pga_aggregate_target"  scope=spfile sid='''||iname||''';' );
    DBMS_OUTPUT.PUT_LINE( 'alter system reset "__sga_target"            scope=spfile sid='''||iname||''';' );
    DBMS_OUTPUT.PUT_LINE( 'alter system reset "__shared_io_pool_size"   scope=spfile sid='''||iname||''';' );
    DBMS_OUTPUT.PUT_LINE( 'alter system reset "__shared_pool_size"      scope=spfile sid='''||iname||''';' );
    DBMS_OUTPUT.PUT_LINE( 'alter system reset "__streams_pool_size"     scope=spfile sid='''||iname||''';' );
    DBMS_OUTPUT.PUT_LINE( 'alter system set memory_max_target    = ' ||memory_target||'M scope=spfile sid=''*'';' );
    DBMS_OUTPUT.PUT_LINE( 'alter system set memory_target        = ' ||memory_target||'M scope=spfile sid=''*'';' );
    DBMS_OUTPUT.PUT_LINE( 'alter system set sga_max_size         = ' ||sga_target||'M scope=spfile sid=''*'';' );
    DBMS_OUTPUT.PUT_LINE( 'alter system set sga_target           = ' ||sga_target||'M scope=spfile sid=''*'';' );
    DBMS_OUTPUT.PUT_LINE( 'alter system set pga_aggregate_target = ' ||pga_aggregate_target||'M scope=spfile sid=''*'';' );
    DBMS_OUTPUT.PUT_LINE( '--alter system reset pga_aggregate_target scope=spfile sid=''*'';' );
    DBMS_OUTPUT.PUT_LINE( '--alter system set db_cache_size      = 512M scope=spfile sid=''*'';' );
    DBMS_OUTPUT.PUT_LINE( '--alter system set shared_pool_size   = 512M scope=spfile sid=''*'';' );
    DBMS_OUTPUT.PUT_LINE( '--alter system set java_pool_size     = 128M scope=spfile sid=''*'';' );
    DBMS_OUTPUT.PUT_LINE( '--alter system set large_pool_size    =  64M scope=spfile sid=''*'';' );
    DBMS_OUTPUT.PUT_LINE( '--alter system set streams_pool_size  =  64M scope=spfile sid=''*'';' );
END;
/

Разобраться

Смотрим значения параметров:

select     name || '=' || decode(type, 2, '''') || value
    || decode(type, 2, '''') parameter
from    v$parameter
where    isdefault = 'FALSE'
and    value is not null
order    by name
/


Распределение памяти экземпляра в режиме AMM:

col component format a20
break on report
compute sum of current_size_mb on report
select component, round(current_size/1024/1024,1) as current_size_mb
from v$memory_dynamic_components
where component like '%Target%';


Потребление памяти на уровне сессии

select *
from (
select
    p.spid,
    p.pid,
    s.sid,
    s.serial#,
    substr(trim(s.machine),1,32) machine,
    s.username,
    s.osuser,
    round(p.pga_used_mem/1024/1024,2) pga_used_mb,
    round(p.pga_alloc_mem/1024/1024,2) pga_alloc_mb,
    round(p.pga_max_mem/1024/1024,2) pga_max_mb,
    row_number() over (order by round(p.pga_max_mem/1024/1024,2) desc) as rn
from
   v$process p,
   v$session s
where p.addr = s.paddr
) where rn < 21
order by pga_max_mb desc;


Чтобы понять, является ли текущий размер SGA оптимальным, изучите следующие представления:

select * from V$SGA_DYNAMIC_COMPONENTS
select * from V$SGA_CURRENT_RESIZE_OPS
select * from V$SGA_RESIZE_OPS
select * from V$SGA_DYNAMIC_FREE_MEMORY


SELECT  component,
        current_size/1024/1024,
        min_size/1024/1024,
        max_size/1024/1024
FROM    v$memory_dynamic_components
WHERE   current_size != 0;


Для точной настройки значений механизма AMM можно использовать:

select * from V$MEMORY_TARGET_ADVICE

SELECT * FROM v$memory_target_advice ORDER BY memory_size;


Для настройки значений параметров SGA и PGA:

select * from V$SGA_TARGET_ADVICE
select * from V$PGA_TARGET_ADVICE



Примечание для OS Solaris:

Настройка AMM или ASMM на ОС Solaris заставит ОС использовать Dynamic Intimate Shared Memory (DISM).
Это позволяет динамически изменять размер shared memory segments.
Динамические свойства SGA используют DISM при включенном AMM или ASMM.
Начиная с Oracle 9i и выше, если SGA_MAX_SIZE  >  SGA_TARGET (или суммы sga compenents), тогда используется DISM.
В 11g DISM также используется, если установлен MEMORY_TARGET или MEMORY_MAX_TARGET.
В противном случае используется ISM (если DISM не включен).
DISM (в отличие от ISM) требует резервирования swap для всех страниц, независимо от того, выделены они или нет.
Это означает, что вам нужно будет настроить swap размером не менее чем сумма размеров SGA для экземпляров, использующих DISM.
Иначе получим memory errors при старте экземпляра.

Используется ли DISM для экземпляра Oracle, можно узнать так:

$ ps -aef | grep dis

должен быть процесс:
ora_dism_$ORACLE_SID

Избежать использования DISM и большого размера swap можно используя manual memory management.