Събиране на статистики.

Тази статия е на моя приятел и колега Евгени Балабанов, който е от хората ностъпвали досто "мотики" и за моя радост написа една малка статийка за този сайт.

Събирането на статистики е досадна, но необходима дейност. Вършим я обикновено в "извънработно време", каквото и да означава това. При наличие на много схеми и на много таблици стандартните средства губят доста време, защото работят последователно върху обектите (таблици и техни индекси). С цел ускоряване на процеса и по-плътно натоварване на ресурсите можем да пуснем събиране на статистики от няколко схеми паралелно. Следният скрипт създава множество от nohup ... & команди, които стартират паралелно събиране на статистики.

#
#  Скрипт за паралелно събиране на статистики от различни схеми
#
#  Last update:
#      2009-04-05 Evgueni Balabanov
#              Created

sqlplus -s / as sysdba << EOF
set feed off
set head off
set lines 300
set newpage none
set pages 2000
set trimspool on
SCRIT_DIR=/home/oracle/admin
LOG_DIR=${SCRIT_DIR}/logs
spool ${SCRIT_DIR}/gsps.sh

select distinct
  'nohup ${SCRIT_DIR}/Gather_schema_statistics.sh' f1
  , owner f2
  , ' > ${LOG_DIR}/Gather_schema_statistics_for_'||owner||'.log &' f3
  from dba_tables t -- от тук, а не от dba_users, 
  --защото може някои user-и да си нямат таблици
-- where owner [not] in ('AAAA','BBBB')
/
spool off
exit;
EOF

chmod u+x ${SCRIT_DIR}/gsps.sh 
${SCRIT_DIR}/gsps.sh
exit

		

Следва скрипт за събиране на статистики от дадена схема.

===================================
#- Gather_schema_statistics.sh
===================================
#
#  Скрипт за събиране на статистики от дадена схема
if [ $# -ne 1 ]
then
  echo " Proper usage is: $0 < schema > "
  exit 8
fi

#  Установяване на обкръжение
. /home/oracle/.profile

#  Или някакво друго насочване към 
#  ORACLE_HOME ORACLE_HOME/bin и ORACLE_SID
SCRIT_DIR=/home/oracle/admin
LOG_DIR=${SCRIT_DIR}/logs

sqlplus / as sysdba << EOF
set timing on
spool ${LOG_DIR}/Gather_schema_statistics_for_${1}
prompt Gathering statistics for $1
begin
 -- Малко пълнеж за v$session, да си разпознаваме обработките
    DBMS_APPLICATION_INFO.SET_CLIENT_INFO ('Statistics gatherer');
    DBMS_APPLICATION_INFO.SET_MODULE ('${0}','');
    dbms_application_info.set_action('Gather stats for schema ${1}');
    dbms_stats.gather_schema_stats 
       ( OWNNAME=>upper('$1'),
        ESTIMATE_PERCENT=>NULL,
        METHOD_OPT=>'FOR ALL COLUMNS SIZE 1',
        OPTIONS => 'GATHER',
        DEGREE=>16, -- тук може да се играе допълнително с 
	               -- паралелизъм, в зависимост от броя процесори
        granularity=>'ALL');
end;
/
spool off
exit;
EOF

					

Този пример е подходящ за малък брой схеми или за мощни сървъри. При 2х16 процесора и съответното количество RAM много успешно се справя с 336 схеми за около 2 часа. При по-скромни ресурси големият брой паралелни процеси може да ни позадръсти. Затова следващият пример ще бъде с контролиран паралелизъм...