Как запретить Oracle использовать кешированный план запросов?

Я использую Oracle Database 11g Enterprise Edition Release 11.2.0.3.0 — 64-битное производство в Linux. У меня есть простой запрос, который объединяет 4 таблицы. Как правило, он запускается сначала после того, как несколько строк тестовых данных вставлены в таблицы, и выполняется за ‹ 0,1 секунды. Если я затем вставлю 50 000 строк в 2 таблицы, выполнение запроса займет> 10 минут. Если я каким-либо образом изменю запрос, он будет выполняться через несколько десятых долей секунды.

Похоже, что план выполнения запроса кэшируется, и оптимизатор использует тот, который он сгенерировал, когда в каждой из 4 таблиц было всего несколько строк. Я попытался обновить статистику для схемы (используя сбор статистики схемы в sql-разработчике), и это не ускоряет медленную версию запроса. Единственное решение, которое я нашел, это запустить

    ALTER SYSTEM FLUSH shared_pool;

Затем при следующем запуске медленного запроса он выполняется за ‹ 1 секунды.

Очищать shared_pool каждый раз, когда вы вставляете какие-то данные, явно не очень хорошая идея. Как правильно поступить в этой ситуации? Будет ли адаптивная оптимизация запросов в Oracle 12 решать такую ​​проблему?

Вот запрос. Когда он работает медленно, даже простой смены псевдонима с abc на abcd (или любого другого) достаточно, чтобы он работал примерно в 1000 раз быстрее.

SELECT
  COUNT (*) cnt_
FROM 
(
    SELECT
     tg.name group_name ,
     tot.obj_type object_type ,
     tgol.test_access access_type,
     count (*) test_object_count
    FROM test_group tg
    , test_group_object_link tgol
    , test_object tobj
    , test_object_type tot
    WHERE tgol.test_group_id=tg.id
    AND tgol.test_object_id=tobj.id
    AND tobj.test_object_type_id=tot.id
    AND tg.isvalid='Y'
    AND tgol.isvalid='Y'
    AND tobj.isvalid='Y'
    AND tot.isvalid='Y'
    GROUP BY tg.name , tot.obj_type , tgol.test_access
    ORDER BY tg.name , tot.obj_type , tgol.test_access
)
abc

person Keith Crews    schedule 15.09.2017    source источник
comment
сбор статистики после того, как были вставлены важные данные, является здесь хорошим решением, обычно это должно решить вашу проблему. Если нет, соберите план объяснения, чтобы проверить, почему он не работает. Вы также можете аннулировать план в кеше при сборе статистики, используя: BEGIN dbms_stats.gather_schema_stats(ownname=›'USER',no_invalidate=›false); КОНЕЦ;   -  person Cyrille MODIANO    schedule 15.09.2017
comment
Сбор статистики может сделать план выполнения запроса недействительным, а может и нет (это означает, что он будет снова анализироваться при следующем запуске). user35... правильно: если вы установите no_invalidate в false при вызове gather_schema_stats, это сработает. Обычно вам не нужно этого делать; по умолчанию Oracle решает, должны ли новые статистические данные сделать план недействительным. Возможно, это значение по умолчанию было изменено в вашей БД или схеме. См. ссылки, когда вы читаете о no_invalidate в документации Oracle.   -  person mathguy    schedule 15.09.2017
comment
Спасибо за ссылку на другой вопрос и информацию о no_invalidate. Настройка для no_invalidate — auto_invalidate. Но даже на следующий день используется тот же плохой план.   -  person Keith Crews    schedule 15.09.2017