Как уже говорилось в этой главе, параметризация курсоров помогает повысить степень их повторного использования. Вот простой пример процедуры получения даты заказа с параметризованным курсором:
Если далее в этой программе нам понадобятся данные о заказах с номерами 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.
< Предыдущая | Следующая > |
---|