Pull to refresh

Comments 7

CURSOR_SHARING выставлен в FORCE
Чтобы потом героически преодолевать трудности?
Есть вещи, над которыми разработчик не властен. Как автор перевода я не знаю иных подробностей подопытной системы, могу только заметить, что если бы разработчики и администраторы БД всегда находили общий язык, то мир лишился бы очень многих технологий.
Менять параметры БД в угоду тривиального решения одной из задач системы — верный способ нарваться на неприятности в других бизнес-модулях. И хорошо, если все скелеты сразу выпадут из шкафов, а могут и спустя годы…
CURSOR_SHARING = force, да еще и установленный на уровне системы, а не сессии, уже давно вызывает больше боли, чем дает пользы. Его по-моему давно убрали из основных тестов и поэтому кол-во багов с ним очень высоко. Есть у меня один клиент, который до сих пор продолжает упорно жрать кактус, постоянно ловя всякие неожиданные баги из версии в версию…
Виктор добрый день! На какой версии выполнялись эти упражнения?
Виктор сейчас в Польше, там праздничные дни, и он мне пока не ответил. Вроде даже у него нет профиля на Хабре, поэтому будем благодарны за инвайт.
Насчет версии у меня есть предположение, что это Oracle 12, впрочем, в 11 тоже скорее всего сработает, насчет 10 и ниже есть сомнения (хотя VPD еще в Oracle 8.1 появился). Программный код выше я не воспроизводил. А какая версия у Вас?
У меня пара замечаний по сабжу:
1. Для решения этой проблемы есть Adaptive cursor sharing, и он делает именно то, что нужно: на основе гистограмм создает подходящие дочерние курсоры. Если у них это не работало, значит надо было разбираться с причиной почему ACS не работал. Игорь Усольцев делал отличную подробную презентацию в российской юзергруппе оракл (RuOUG). Вообще, советую посещать наши мероприятия.

2. Раз на базе стоит cursor_sharing=force, то можно было просто создать профиль с одним единственным хинтом BIND_AWARE на любом из этих запросов, с указанием параметра force_match=>true.

3. Насчет динамики:
Понятно, что исправление приложения и использование параметров как литералов в запросе – это самый подходящий способ решения проблемы, но он ведет к динамическому SQL с его известными недостатками.

Я еще на 10-ке использовал несколько разных вариантов в зависимости от условий:
3.1 Если был возможен PL/SQL то просто разбивал через IF на пару разных вариантов, грубо говоря: IF cardinality>N then query1 else query2
A cardinality получал одним из быстрых способов.
3.2. Разбиение на union all с доп.подзапросом, например:
select/*+ index(t1 (a,b)) */ * 
from t1 
where ...
 and (select count(*) from t1 where ... and rownum<=X)<X
union all
select/*+ full(t1) или index_ffs(t1) */ * 
from t1 
where ...
 and (select count(*) from t1 where ... and rownum<=X)=X

И если данные уже промаркированы как в статье(отдельная таблица где помечены «большие/средние/маленькие»), то этот вариант был бы намного проще

4. Здесь неверно:
Другой путь – отключение запроса связанных переменных (ALTER SESSION SET "_OPTIM_PEEK_USER_BINDS" = FALSE) или удаление гистограмм (ссылка).

Это решение абсолютно для противоположной цели: отключение _OPTIM_PEEK_USER_BINDS и удаление гистограм делают в случае, если оракл плодит разные планы, а хочется строго одного и того же для любых биндов.

5. Существует и еще один подход: секционирование с учетом data skew. Тут вариантов много, одним из простейших является интервальное секционирование по «перекошенному» столбцу основного ACCESS предиката. А для статьи из примера удобно было бы секционировать как раз по SMALL/MIDDLE/LARGE, то есть три разные секции, каждая со своей статистикой(причем заработает даже без гистограмм, т.к. достаточно (num_rows-num_nulls)/num_distinct статистик по секции), что дает оптимизатору легко понять селективность столбца в данной секции.

ЗЫ. Надо было Виктору ко мне обратиться, вместе бы посмотрели почему ACS у них не работал.
Sign up to leave a comment.