Существует реальная опасность в запросах, предложенных Джимом и Алексом.
Предположим, у вас есть данные за 20 лет, поэтому запрос по YEAR = возвращает 5% блоков.Я говорю блоки, а не строки, потому что я предполагаю, что данные добавляются в эту дату, поэтому коэффициент кластеризации высокий.
Если вы хотите 1 год, вы хотите, чтобы оптимизатор использовал индекс по годам, чтобы найти эти 5% строк.
Если вы хотите все годы, вы хотите, чтобы оптимизатор использовал полное сканирование таблицы для получения каждой строки.
Пока все хорошо?
Один развы запускаете его в производство, когда Oracle в первый раз загружает пиковый запрос в переменную связывания и на основе этого формулирует план.
Итак, скажем, первая загрузка - «Все».
Отлично, план представляет собой сканирование полной таблицы (FTS), и этот план кэшируется, и вы возвращаете все строки через 5 минут.Ничего страшного.
При следующем запуске вы говорите 1999 год. Но план кэшируется, и поэтому он использует FTS, чтобы получить только 5% строк, и это занимает 5 минут.«Хммм ... пользователь говорит, что было намного меньше строк и в то же время».Но это нормально ... это всего лишь 5-минутный отчет ... жизнь немного медленнее, когда этого не нужно, но никто не кричит.
Той ночью пакетные задания выбивают этот запрос изкеш, а утром первый пользователь запрашивает 2001 год. Oracle проверяет кеш, а не там, заглядывает в переменную 2001 года. Ах, лучший план для этого - сканирование индекса.и этот план кэшируется.Результаты возвращаются через 10 секунд и поражают пользователя.Следующий человек, обычно первый, делает утренний отчет «ВСЕ», и запрос никогда не возвращается.
ПОЧЕМУ?
Поскольку он просматривает каждую строку, просматривая индекс ...ужасные вложенные петли.5-минутный отчет теперь на 30 и считается.
Ваш оригинальный пост имеет лучший ответ.Два запроса, так что оба всегда ВСЕГДА получат наилучший план, просмотр переменной привязки не убьет вас.
Проблема, с которой вы столкнулись, является просто фундаментальной проблемой Oracle.Вы запускаете запрос из инструмента и получаете результаты обратно в инструмент.Если вы помещаете оператор select в блок pl / sql, вы должны что-то с ним сделать.Вы должны загрузить его в курсор, или массив, или переменную.Это не имеет ничего общего с тем, что вы не правы, а они правы ... это просто отсутствие навыков pl / sql.