Доступ к последовательностям в PL/SQL 11g

В PL/SQL 11g появилась возможность выбирать следующее значение из последовательности (sequence) напрямую, не используя выборку значения через системную таблицу dual. Старый привычный синтаксис:

SELECT MY_SEQ.NEXTVAL INTO n FROM dual;

Новый синтаксис в PL/SQL 11g:

n:=MY_SEQ.NEXTVAL;

Заявляемые особенности нового синтаксиса:

– Можно обращаться к последовательности напрямую в выражении, код проще, короче и понятнее. 

– Повышение производительности при выборке нового значения, так как не используется обработка курсора при обращении к dual.  

– Однако переключение контекста при выборке значения из последовательности все равно требуется, так как последовательность находится в SGA

– Также можно использовать прямое обращение к currval, но только если перед этим в этой же сессии была выборка по nextvalВсе это замечательно, работать с последовательностями в PL/SQL коде действительно становится удобнее, но основной вопрос в том, насколько увеличивается производительность выборки значений из последовательности при помощи нового синтаксиса. Попробуем это выяснить. Создадим тестовую последовательность:

CREATE SEQUENCE TEST_SEQ;

Загрузим sql*plus, включим измерение времени выполнения командой set timing on, и выполним выборку ста тысяч значений из последовательности старым способом:

DECLARE
  n NUMBER;
BEGIN
  FOR i IN 1..100000 LOOP
    SELECT TEST_SEQ.NEXTVAL INTO n FROM dual;
  END LOOP;
END;
/
Elapsed: 00:00:05.29

Теперь используем новый синтаксис PL/SQL 11g:

DECLARE
  n NUMBER;
BEGIN
  FOR i IN 1..100000 LOOP
    n:=TEST_SEQ.NEXTVAL;
  END LOOP;
END;
/
Elapsed: 00:00:05.28

Мы не получили никакого выигрыша в скорости выборки значений из последовательности новым способом. Странно, заявления о том, что не надо обрабатывать курсор и это приведет к повышению производительности не оправдались. Здесь два варианта, или новый синтаксис просто маскирует выборку через dual, либо в новой версии PL/SQL 11g оптимизирован механизм работы с последовательностями на уровне ядра системы, поэтому мы получаем одинаковые результаты. Чтобы это проверить, выполним тест со старым синтаксисом в версии Oracle Database 10g, установленной на этой же машине:

Elapsed: 00:00:03.89

Еще более странно. На предыдущей версии базы данных 10g стандартный код выполняется заметно быстрее! Обе базы данных автора установлены со стандартными настройками, сравнение версий баз данных выполняется корректно, но деградация производительности налицо. Новый синтаксис выборки из последовательности не увеличил производительность этой операции, а скорость выборки из последовательности заметно упала в новой версии базы данных по равнению с предыдущей вне зависимости от синтаксиса. В чем же дело? Становится понятно, что новый синтаксис это просто более удобная форма записи, и ничего более. Может быть переключение контекстов в 11g происходит теперь дольше, чем в 10g? Может быть…

Ссылка на основную публикацию