Я использую 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
no_invalidate
вfalse
при вызовеgather_schema_stats
, это сработает. Обычно вам не нужно этого делать; по умолчанию Oracle решает, должны ли новые статистические данные сделать план недействительным. Возможно, это значение по умолчанию было изменено в вашей БД или схеме. См. ссылки, когда вы читаете оno_invalidate
в документации Oracle. - person mathguy   schedule 15.09.2017