12.02.2020 13:50
OlegON
 
Несколько табличек выросли достаточно значительно по отношению к ресурсам сервера, чтобы DBMS_STATS.GATHER_DATABASE_STATS успевало отработать на них в период регламентных работ. Соответственно, встала задача, каким образом исключить эти таблицы из списка таблиц, по которым в DBMS_STATS.GATHER_DATABASE_STATS статистика собирается автоматически.

Предложенный Oracle вариант достаточно простой
SQL код:
DBMS_STATS.LOCK_TABLE_STATS ('ПОЛЬЗОВАТЕЛЬ','ТАБЛИЦА'
в принципе - вариант, если у вас собственный софт на базе. Но мне этот вариант не подошел, поскольку некоторый ... софт... пытался собирать статистику по этим таблицам сам, лишая работы администратора, и, мало того, что делал это зверски долго и неправильно, так еще и при блокировке статистики падал, хороня длительную процедуру целиком.

Последователи Тома Кайта предлагали еще один вариант, немного странный
SQL код:
DBMS_STATS.SET_TABLE_PREFS('ПОЛЬЗОВАТЕЛЬ''ТАБЛИЦА''PUBLISH''FALSE'); 
Дело в том, что это не отключает автоматический сбор статистики, а просто прячет ее. Т.е. мою задачу не решало вообще никак. Но, зато навели меня на другую мысль.

Остановился я пока на варианте
SQL код:
DBMS_STATS.SET_TABLE_PREFS('ПОЛЬЗОВАТЕЛЬ''ТАБЛИЦА''STALE_PERCENT''99'); 
т.е. не пересобирать статистику автоматически, пока данные в ней не изменятся на 99%. Если администратор доведет ее до такого состояния, то уже повод будет попробовать собрать статистику автоматически. Зато без ошибок при попытках сделать что-то кривософтом, и статистика на месте...

SQL код:
begin
  sys
.dbms_scheduler.create_job(job_name            => 'SYS.OK_STATS_JOB',
                                
job_type            => 'PLSQL_BLOCK',
                                
job_action          => 'begin dbms_stats.gather_database_stats(estimate_percent=>DBMS_STATS.AUTO_SAMPLE_SIZE,block_sample=>true,method_opt=>''FOR ALL COLUMNS SIZE AUTO'',degree=>1,cascade=>DBMS_STATS.AUTO_CASCADE,no_invalidate=>false,granularity=>''ALL'',options=>''GATHER STALE''); begin FOR tmp IN (SELECT owner,table_name FROM dba_tables WHERE temporary = ''Y'' and owner not in (''SYS'',''SYSTEM'')) LOOP DBMS_STATS.DELETE_TABLE_STATS(ownname=>tmp.owner,tabname=>tmp.table_name,no_invalidate=>false);END LOOP;end;end;',
                                
start_date          => to_date('14-07-2023 23:59:57''dd-mm-yyyy hh24:mi:ss'),
                                
repeat_interval     => 'Freq=DAILY;ByHour=8,23;ByMinute=0',
                                
end_date            => to_date(null),
                                
job_class           => 'DEFAULT_JOB_CLASS',
                                
enabled             => true,
                                
auto_drop           => true,
                                
comments            => 'Job to gather database statistics');
end;

Часовой пояс GMT +3, время: 04:41.

Форум на базе vBulletin®
Copyright © Jelsoft Enterprises Ltd.
В случае заимствования информации гипертекстовая индексируемая ссылка на Форум обязательна.