DeepEdit!

Программирование баз данных на Oracle, техническая документация, литература, статьи и публикации

  • Увеличить размер шрифта
  • Размер шрифта по умолчанию
  • Уменьшить размер шрифта

Параметры курсора

Как уже говорилось в этой главе, параметризация курсоров помогает повысить степень их повторного использования. Вот простой пример процедуры получения даты заказа с параметризованным курсором:

Если далее в этой программе нам понадобятся данные о заказах с номерами 200, 300 и 500, достаточно будет еще раз открыть этот же курсор. Такой подход способствует повторному использованию курсоров как в самой PL/SQL-программе, так и в разделяемом пуле.
Несовпадение в разделяемом пуле
Явные и неявные курсоры в разделяемом пуле не совпадают. Поясним на примере, что имеется в виду.

Несмотря на то что эти курсоры выглядят одинаково и оба находятся в разделяемом пуле, с точки зрения Oracle у них достаточно отличий (может быть, предложение INTO?), чтобы хранить их отдельно. Поэтому не следует надеяться, что явный и неявный курсоры совпадут в разделяемом пуле. Лучше придерживаться какого-то одного способа.
Мягкое закрытие курсора
При разработке приложений я всегда стараюсь использовать любые возможности, приводящие к повышению производительности. Я всегда задаю себе вопросы - например, если функция многократно вызывается в течение одного сеанса Oracle, почему бы мне не кэшировать какие-то общие данные вместо того, чтобы каждый раз запрашивать их? Или, если мне известно, что базовые данные меняются один раз в час, почему бы не сохранить результаты запроса и тем самым избежать повторных запросов в течение последующих 60 минут?
Одно из предположений Oracle заключается в том, что если курсор был однажды использован в сеансе, то он когда-нибудь будет использован повторно (даже если был явно закрыт). Прием, реализующий это предположение, называется мягким закрытием, или, как я это называю, «закрытием без закрытия».
Рассмотрим простой пример с неявным курсором.

Неявный курсор был создан, открыт, использован для выборки и закрыт - все в одном операторе SELECT. Теперь он должен быть отсоединен от сеанса, в котором выполнялся, правильно? Не торопитесь. Для того чтобы воспользоваться преимуществами возможного повторного использования, выполняется лишь мягкое закрытие курсора, которое позволяет ускорить его повторное выполнение в этом сеансе.
Курсоры, связанные с определенным сеансом, перечислены в представлении V$OPEN_CURSOR. Здесь содержатся как открытые в данный момент курсоры, так и те, которые были мягко закрыты. Вот что находится в этом представлении для сеанса, выполняющего запрос к DUAL:

Такое мягкое закрытие происходит при явном закрытии курсора оператором CLOSE или при неявном закрытии в момент выхода из области видимости.
Для того чтобы все курсоры не остались навечно в состоянии мягкого закрытия, можно установить в параметре инициализации базы данных OPEN_CURSORS предельное количество курсоров для сеанса. При за-
полнении списка наиболее долго не использовавшийся закрытый курсор выбрасывается, а на его место записывается новый. Однако если сеанс попытается явно открыть больше курсоров, чем указано в этом параметре, он получит ошибку ORA-01000: maximum open cursors exceeded (превышено максимальное число открытых курсоров).
Открытие явных и неявных курсоров
Еще одно место, где явные и неявные курсоры трактуются по-разному, - это список открытых курсоров. Рассмотрим это на примере, где значение параметра OPEN_CURSORS равно 20. Сначала выполним несколько неявных курсоров:


SELECT
' n'
FROM
ORDERS
SELECT
' z'
FROM
ORDERS
SELECT
'o'
FROM
ORDERS
SELECT
'q'
FROM
ORDERS
SELECT
'x'
FROM
ORDERS
SELECT
T
FROM
ORDERS
SELECT
'v'
FROM
ORDERS
SELECT
' s'
FROM
ORDERS
SELECT
'p'
FROM
ORDERS
SELECT
'w'
FROM
ORDERS
SELECT
'm'
FROM
ORDERS
SELECT
' u'
FROM
ORDERS
SELECT
'k'
FROM
ORDERS
SELECT
j '
FROM
ORDERS
SELECT
' i'
FROM
ORDERS
SELECT
'y'
FROM
ORDERS
SELECT
' r'
FROM
ORDERS
SELECT
't'
FROM
ORDERS


Только последние курсоры остались в состоянии мягкого закрытия. Остальные были удалены, чтобы освободить место для новых курсоров.
Теперь выполним несколько явных курсоров, открывая и закрывая каждый из них.

В результате получим список связанных с сеансом курсоров, очень похожий на тот, который мы видели в случае с неявными курсорами. Но представьте, что будет, если мы поленимся и не закроем все явные курсоры, как в следующем примере.

Где-то на 20-м курсоре мы получим ошибку, так как сеанс попытается выйти за отведенное для него ограничение в 20 открытых курсоров.

Это одна из причин, по которым так важно всегда закрывать явные курсоры.
Так каким же должно быть разумное значение параметра OPEN_CURSORS? Ответ прост: столько, сколько нужно, плюс один. На первый взгляд от
такого ответа мало пользы, но для установки этого параметра нет других практических рекомендаций. Если значение слишком мало, программа не выполнится из-за ошибки 0RA-1000. Если значение слишком велико, курсоры (явные и неявные) могут навсегда остаться в состоянии мягкого закрытия. Хорошая новость в том, что при задании параметра пространство не резервируется, поэтому установка большого значения не приводит к перерасходу памяти.
Приведенный далее запрос возвращает подходящее значение, подсчитывая полное количество курсоров (открытых и мягко закрытых) для текущего сеанса. Я регулярно запускаю его на ранних этапах разработки приложения.

Затем я устанавливаю параметр OPEN_CURSORS равным максимальному полученному значению с запасом в 10 или 20.
 









jAntivirus