Должно ли создание индекса мгновенно обновлять план запросов Oracle?

Если у вас есть неэффективный запрос, и вы добавляете индекс, чтобы повысить производительность, должен ли запрос «мгновенно» начать использовать индекс?

Или вам нужно очистить «кеш» Oracle (я полагаю, v$sql) с помощью работает alter system flush shared_pool;?


person Marcus Leon    schedule 22.07.2010    source источник


Ответы (3)


Как любит отвечать администратор базы данных, «это зависит».

Это зависит от того, считает ли Oracle, что индекс поможет производительности. Если Oracle считает, что индекс не лучший выбор для запроса, Oracle все равно его не использует.

Это зависит от того, используете ли вы подготовленные операторы. Подготовленный оператор не подвергается повторному анализу в течение срока его действия, поэтому, если работающее приложение использует подготовленный оператор, который вы пытаетесь исправить, вам потребуется перезапустить приложение.

Очистка общего пула заставит Oracle повторно анализировать и повторно оптимизировать все операторы (жесткий анализ), поэтому, если Oracle считает, что индекс улучшит производительность, очистка общего пула поможет. Однако это также может иметь далеко идущие последствия в действующей производственной системе, вызывая «шторм синтаксического анализа», поскольку каждый используемый оператор должен быть повторно проанализирован и повторно оптимизирован, и его следует применять только в крайнем случае.

person Adam Musch    schedule 22.07.2010
comment
Почему перезапуск приложения может привести к повторному анализу подготовленных операторов (и обновлению плана объяснения)? - person Marcus Leon; 22.07.2010
comment
Потому что подготовленныйстатемент является курсором в Oracle, и Oracle знает, что ваше приложение удерживает этот курсор, пока вы не закроете подготовленныйстатемент или не завершится сеанс. Завершение сеанса путем закрытия приложения обычно является единственным доступным методом контроля. Как только вы перестанете удерживать этот курсор (после перезапуска приложения), Oracle заметит, что новый индекс сделал оператор недействительным в общем пуле, и повторно проанализирует/повторно оптимизирует оператор. См. блок-схему на странице 3 здесь: oracle.com/technology/books/pdfs/ jdbc_ch5.pdf - person Adam Musch; 22.07.2010
comment
Удалил мой последний комментарий .. Хорошо .. кажется, что происходит, я запускаю приложение, и запрос выполняется быстро .. но затем он замедляется и больше не использует индекс. С чего бы это? Не было добавлено данных? - person Marcus Leon; 22.07.2010

Вам следует заново собрать статистику в таблице. Вы можете вычислить или оценить статистику. Пример использования

Вычислить

BEGIN
  SYS.DBMS_STATS.GATHER_TABLE_STATS (
      OwnName        => 'ENROLLMENT'
     ,TabName        => 'STUDENTS'
    ,Estimate_Percent  => 0
    ,Degree            => 4
    ,Cascade           => TRUE
    ,No_Invalidate     => FALSE);
END;
/

Обратите внимание, что каскадный аргумент говорит оракулу также собирать статистику по любым индексам в таблице.

Оценка

BEGIN
  SYS.DBMS_STATS.GATHER_TABLE_STATS (
      OwnName        => 'ENROLLMENT'
     ,TabName        => 'STUDENTS'
    ,Estimate_Percent  => DBMS_STATS.AUTO_SAMPLE_SIZE
    ,Degree            => 4
    ,Cascade           => TRUE
    ,No_Invalidate     => FALSE);
END;
/

документы GATHER_TABLE_STATS

person Brian    schedule 22.07.2010
comment
Спасибо, это работает... что именно означает сбор статистики? Зачем нужно это делать в моем случае? - person Marcus Leon; 22.07.2010
comment
+1 Брайану, я только сегодня столкнулся с этим! Был в бешенстве, что мой потрясающий новый индекс не использовался :/ Запустил статистику по таблице и индексу, и это сработало. Маркус, статистика таблиц и индексов помогают оптимизатору смоделировать наилучший способ выполнения вашего запроса. Обычно задание выполняется вечером для обновления статистики (10 г, 11 г), но вы хотите повторно собрать как можно скорее, чтобы оптимизатор немедленно получил информацию. Этому посвящены целые книги, поэтому я не буду описывать здесь все свои 500 символов. «Основы Oracle на основе затрат» Джонатана Льюиса, пожалуй, лучшее место для углубленного изучения. - person David Mann; 22.07.2010
comment
Вероятно, причина, по которой это меняет производительность запроса, заключается в том, что он делает курсор недействительным, а не потому, что новый индекс в противном случае был бы невидим для оптимизатора. Статистика по таблице не должна была измениться, а наличие статистики по новому индексу больше всего повлияло бы на выбор среди других индексов в таблице. - person dpbradley; 23.07.2010
comment
Возможно немного того и другого. Зависит от того, какие параметры используются для сбора состояний. Если статистика для столбцов в новом индексе ранее не собиралась (например, вы используете FOR ALL INDEXED COLUMNS), то в базе данных может быть недостаточно данных, чтобы решить, когда лучше всего использовать индекс. Повторный сбор статистики может это исправить. По крайней мере, если вы создаете индекс, выполните GATHER_INDEX_STATS. - person Gary Myers; 23.07.2010

Общий пул не используется для кэширования данных.

Oracle Server имеет два измерения производительности: логическое чтение и физическое чтение. Физическое чтение — это измерение производительности чтения с диска. Логическое чтение — это измерение считанных данных из памяти.

В любом методе чтения (индекс, полное сканирование таблицы или что-то еще) строки в блоках должны быть извлечены в буферный кеш. Это действие физического чтения.

Логическое чтение — это результат возврата из кеша при попадании, если вы используете индекс для повышения производительности SQL, это улучшение логического чтения.

Так что короче не надо.

person Community    schedule 22.07.2010
comment
Да, общий пул не кэширует данные; но в этом случае проблема заключается в том, что план запроса кэшируется, а этот находится в общем пуле. - person Jeffrey Kemp; 23.07.2010