Без названия и без подзаголовка

Повышение производительности PL/SQL приложений

Every day, in every way, I am getting better and better.
Emile Coue *

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

В этой главе затрагиваются следующие вопросы:

Причины проблем с производительностью PL/SQL
Выявление проблем с производительностью PL/SQL
Возможности PL/SQL для повышения производительности


Причины проблем с производительностью PL/SQL

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

Неправильные SQL запросы в PL/SQL приложении

PL/SQL программы смотрятся относительно простыми потому что вся их сложность спрятана внутри SQL запросов, которые выполняют большую часть работы. Поэтому плохо написанные SQL запросы являются главной причиной увеличения времени выполнения. Если же программа содержит большое число плохо написанных SQL запросов, то уже никакое количество хорошо написанных PL/SQL инструкций уже не поможет.

Если некачественные SQL запросы замедляют вашу программу, проанализируйте их план выполнения и производительность при помощи перечисленных здесь методов. Затем перепишите SQL запросы. Например, указания оптимизатору (hints) могут устранить проблему ненужного сканирования всей таблицы.

Подробнее об этих методах читайте в » Oracle9i Database Performance Planning.

Некачественные практики программирования

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

Вне зависимости от того, насколько подходит выбранный язык программирования к данной задаче, плохо написанные подпрограммы (например, медленная сортировка или функция поиска) могут нанести ущерб производительности. Представьте, что подпрограмма, которая чаще всего вызывается приложением, – это функция поиска с сотнями возможных результатов. Она может быть написана, используя хэш или алгоритм бинарного поиска, но вместо этого она реализует алгоритм линейного поиска. В итоге пострадает производительность.

Остальные популярные неправильные подходы включают объявления переменных, которые никогда не используются; передачу ненужных параметров в функции и процедуры; неоправданные инициализации или вычисления внутри цикла и так далее.

Дублирование встроенных функций

PL/SQL предоставляет множество прекрасно оптимизированных функций: REPLACE, TRANSLATE, SUBSTR, INSTR, RPAD и LTRIM. Не нужно писать собственные версии этих функций. Встроенные реализации более эффективны. Даже если встроенная функция более мощная, чем нужно, лучше используйте ее, чем написанную вручную, но реализующую только необходимую функциональность.

Неэффективные условные операторы

Вычисляя значение логического выражения, PL/SQL работает по принципу неполного вычисления условия. Это значит, что PL/SQL прекращает вычисление значения выражения как только результат может быть определен. Например, в следующем OR выражении, когда значение sal меньше 1500, левый операнд принимает значение TRUE, поэтому PL/SQL не нужно вычислять значение правого операнда (потому что OR возвращает TRUE если хотя бы один из его операндов является истинным):

IF (sal < 1500) OR (comm IS NULL) THEN
    ...
END IF;

Теперь обратите внимание на следующее выражение с использование AND:

IF credit_ok(cust_id) AND (loan < 5000) THEN
    ...
END IF;

Булева функция credit_ok вызывается всегда. Однако, если вы поменяете местами операнды AND следующим образом:

IF (loan < 5000) AND credit_ok(cust_id) THEN
    ...
END IF;

функция будет вызвана только если выражение loan < 5000 истинно (так как оператор AND возвращает TRUE только если оба операнда истинны).

Та же идея применима к операторам EXIT-WHEN.

Неявные преобразования типов

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

Избегая неявного преобразования типов можно улучшить производительность. Посмотрите на следующий пример. Целое значение 15 представляется знаковой 4-х байтной величиной, так что PL/SQL должен преобразовать его в число, понятное Oracle перед сложением. Однако вещественный литерал 15.0 представлен так же как и 22-байтное Oracle число и его преобразование не требуется.

DECLARE
   n NUMBER;
   c CHAR(5);
BEGIN
   n := n + 15;    -- с преобразованием типов
   n := n + 15.0;  -- без преобразования
   ...
END;

Другой пример:

DECLARE
   c CHAR(5);
BEGIN
   c := 25;    -- с преобразованием типов
   c := '25';  -- без преобразования
   ...
END;
Нецелесообразные объявления числовых типов

Тип NUMBER и его подтипы это 22-байтные числа в формате, ориентированном не на производительность, а на хранение в базе данных с указанием размерности/точности. Когда вам требуется объявить целочисленную переменную, используйте тип PLS_INTEGER - наиболее эффектвный числовой тип. Это обусловлено тем, что значения типа PLS_INTEGER требуют меньше места, чем значения типа INTEGER или NUMBER. Кроме того, операции с PLS_INTEGER используют низкоуровневую арифметику, поэтому они быстрее, чем операции с типами BINARY_INTEGER, INTEGER, или NUMBER, действия с которыми реализованы через библиотеки.

Кроме того, INTEGER, NATURAL, NATURALN, POSITIVE, POSITIVEN, и SIGNTYPE - подтипы с ограничениями. Их значения требуют проверки точности во время выполнения, что негативно сказывается на производительности.

Необязательные NOT NULL ограничения

В PL/SQL, использование ограничения NOT NULL увеличивает затраты на выполнение. Рассмотрим следующий пример:

PROCEDURE calc_m IS
   m NUMBER NOT NULL := 0;
   a NUMBER;
   b NUMBER;
BEGIN
   ...
   m := a + b;
   ...
END;

Из-за того, что переменная m объявлена, как NOT NULL, значение выражения a + b помещается во временную переменную, которая проверяется на NULL. Если эта переменная не NULL, то её значение помещается в переменную m. Иначе возникает исключительная ситуация. Однако, если бы m была объявлена без ограничений, значение выражения было бы помещено в m напрямую.

Более эффективный вариант предыдущего примера выглядит так:

PROCEDURE calc_m IS
   m NUMBER;  -- нет ограничений
   a NUMBER;
   b NUMBER;
BEGIN
   ...
   m := a + b;
   IF m IS NULL THEN  -- обработать ограничение программно
      ...
   END IF;
END;

Отмечу, что подтипы NATURALN и POSITIVEN определены, как NOT NULL. Поэтому их использование увеличивает затраты на выполнение.

Указание размера переменных VARCHAR2

Тип VARCHAR2 подразумевает компромисс между использованием памяти и эффективностью. Для переменных типа VARCHAR2(>=2000) PL/SQL выделяет ровно столько памяти, сколько требуется. Однако, для переменных VARCHAR2(<2000) PL/SQL резервирует память для хранения максимально возможного значения. Таким образом, при помещении 500-байтного значения в переменные типа VARCHAR2(2000) и VARCHAR2(1999), второй вариант использует на 1499 байт памяти больше.

Неправильное использование разделяемой памяти в PL/SQL программах

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

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

Зафиксированные пакеты

Другой способ улучшить производительность - зафиксировать часто используемые пакеты в разделяемой памяти. Когда пакет зафиксирован, он не вытесняется другим в соответствии с алгоритмом LRU - Least Recently Used (вытеснение редкоиспользуемых элементов), который обычно применяет Oracle. Пакет остается в памяти независимо от того, насколько заполнена память и как часто вы обращаетесь к пакету.

Вы можете зафиксировать пакеты с помощью поставляемого с Oracle пакета DBMS_SHARED_POOL.

Подробности вы можете узнать в " Oracle9i Supplied PL/SQL Packages and Types Reference.

Периодически используемые пакеты

Для помощи в управлении использованием памяти, PL/SQL предлагает директиву компилятора SERIALLY_REUSABLE, которая позволяет помечать пакеты как повторно используемые. Так вы можете пометить пакет, если его состояние необходимо только во время выполнения одного запроса к серверу (например, OCI-запрос к серверу, или межсерверная команда RPC).

Память для таких пакетов берется из System Global Area (SGA) - системной глобальной области, т.е. не выделяется каждому отдельному пользователю в его User Global Area (UGA) - пользовательской глобальной области. Таким образом рабочая область пакета может быть использована повторно. Когда запрос к серверу завершается, память освобождается. Каждый раз когда пакет используется повторно, его переменные, доступные для общего использования, инициализируются значениями по умолчанию или значением NULL.

Максимальное число рабочих областей, необходимых пакету - это число пользователей, параллельно работающих с этим пакетом, которое обычно намного меньше числа пользователей установивших соединение с сервером. Увеличение использования SGA памяти сильно компенсируется уменьшением использования UGA памяти. Также, Oracle освобождает память занимаемую неиспользуемыми рабочими областями если требуется восстановить SGA память.

Для пакетов без тела (body), необходимо указать директиву компилятора в спецификации пакета, используя следующий синтаксис:

PRAGMA SERIALLY_REUSABLE;

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

CREATE PACKAGE pkg1 IS
   PRAGMA SERIALLY_REUSABLE;
   num NUMBER := 0;
   PROCEDURE init_pkg_state(n NUMBER);
   PROCEDURE print_pkg_state;
END pkg1;
/
CREATE PACKAGE BODY pkg1 IS
   PRAGMA SERIALLY_REUSABLE;
   PROCEDURE init_pkg_state (n NUMBER) IS
   BEGIN
      pkg1.num := n;
   END;
   PROCEDURE print_pkg_state IS
   BEGIN
      dbms_output.put_line('Num: ' || pkg1.num);
   END;
END pkg1;
/
BEGIN
   /* Инициализируем состояние пакета. */
   pkg1.init_pkg_state(4);
   /* В том же обращении к серверу печатаем состояние пакета. */
   pkg1.print_pkg_state;  -- напечатает 4
END;
/
-- следующее обращение к серверу
BEGIN
   -- общая переменная пакета автоматически инициализирована
   -- значением по умолчанию
   pkg1.print_pkg_state;  -- напечатает 0
END;

Для более полной информации, обратитесь к Oracle9i Application Developer's Guide - Fundamentals.


Выявление проблем с производительностью PL/SQL

Когда Вы разрабатываете все более и более масштабные PL/SQL приложения, становится все труднее выделять проблемы производительности. PL/SQL предоставляет интерфейс Profile API для профилирования приложения во время выполнения, а также для выявления слабых мест в производительности. Наряду с профилировщиком, PL/SQL предоставляет интерфейс Trace API для трассировки выполнения программ на сервере. Вы можете использовать Trace для отслеживания выполнения подпрограмм или обработки исключений.

Profiler API: пакет DBMS_PROFILER

Интерфейс Profiler API реализован в пакете DBMS_PROFILER и предоставляет сервисы по сборке и хранению статистики времени выполнения. Собранная информация хранится в таблицах базы данных, и её можно запросить позднее. Например, вы можете узнать, сколько времени было потрачено на выполнение каждой строки PL/SQL или процедуры.

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

  1. Запустить профилировщик процедурой start_profiler из пакета DBMS_PROFILER, указав при этом комментарий для профилируемой сессии.
  2. Запустить исследуемое приложение.
  3. Периодически вызывать процедуру flush_data для сохранения очередной порции данных и освобождения памяти, выделенной под структуры данных.
  4. Завершить профилирование вызовом процедуры stop_profiler.

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

Более подробно о пакете DBMS_PROFILER, читайте в Oracle9i Supplied PL/SQL Packages and Types Reference.

Анализ собранных данных

На следующем шаге необходимо определить, почему тратится много времени на выполнение отдельных сегментов кода или на доступ к определенным структурам данных. Найдите проблемные участки, просматривая данные о производительности. Сфокусируйтесь на подпрограммах и пакетах, которые выполняются дольше остальных. Исследуйте потенциально узкие места в производительности, такие как SQL выражения, циклы и рекурсивные вызовы функций.

Использование данных трассировки для улучшения производительности

Используйте результаты анализа для улучшения медленных алгоритмов. Например, из-за экспоненциального роста объема данных, может понадобится заменить линейный поиск бинарным поиском. Также, обратите внимание на неэффективное использование неподходящих структур данных, и по мере необходимости, замените их.

Trace API: пакет DBMS_TRACE

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

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

  1. Выбираете определенные подпрограммы для сбора данных во время трассировки (необязательно).
  2. Начинаете трассировку, вызывая процедуру set_plsql_trace в пакете DBMS_TRACE.
  3. Запускаете отслеживаемое приложение.
  4. Завершаете трассировку, вызывая процедуру clear_plsql_trace.

Подробнее о пакете DBMS_TRACE смотрите в Oracle9i Supplied PL/SQL Packages and Types Reference.

Управление трассировкой

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

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


Возможности PL/SQL для повышения производительности

После устранения недостатков, которые тормозят работу приложения, вы можете использовать следующие функциональные возможности и методы PL/SQL :

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


Настройка производительности PL/SQL с помощью Native Dynamic SQL

Некоторые программы (например, универсальный составитель отчетов) должны строить и обрабатывать множество SQL запросов в режиме реального времени. Таким образом, их полный код неизвестен до конца. Такие запросы могут, и по всей вероятности будут, изменяться от запуска к запуску. Поэтому они называются динамическими SQL запросами.

Раньше для того, чтобы выполнить динамический SQL запрос вам приходилось использовать встроенный пакет DBMS_SQL. Теперь, в PL/SQL, вы можете выполнять любые динамические SQL запросы при помощи интерфейса Native Dynamic SQL.

Native dynamic SQL проще в использовании и намного быстрее, чем пакет DBMS_SQL. В следующем примере вы объявляете переменную типа курсор, затем ассоциируете ее с динамическим SELECT запросом, который возвращает записи из таблицы emp:

DECLARE
   TYPE EmpCurTyp IS REF CURSOR;
   emp_cv   EmpCurTyp;
   my_ename VARCHAR2(15);
   my_sal   NUMBER := 1000;
BEGIN
   OPEN emp_cv FOR
     'SELECT ename, sal FROM emp
         WHERE sal > :s' USING my_sal;
   ...
END;

Более подробно читайте в Главе 11.


Настройка производительности PL/SQL с помощью массового связывания (Bulk Binds)

Когда SQL запросы выполняются в цикле и используют коллекции элементов как связанные переменные, контекстное переключение между системами PL/SQL и SQL может замедлить работу приложения. Например, следующий UPDATE запрос отправляется SQL-машине на каждой итерации цикла FOR:

DECLARE
   TYPE NumList IS VARRAY(20) OF NUMBER;
   depts NumList := NumList(10, 30, 70, ...);  -- номера департаментов
BEGIN
   ...
   FOR i IN depts.FIRST..depts.LAST LOOP
      ...
      UPDATE emp SET sal = sal * 1.10 WHERE deptno = depts(i);
   END LOOP;
END;

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

FORALL i IN depts.FIRST..depts.LAST
   UPDATE emp SET sal = sal * 1.10 WHERE deptno = depts(i);

Для максимальной производительности перепишите ваши программы следующим образом:

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

Подробнее о массовом связывании смотрите "Reducing Loop Overhead for Collections with Bulk Binds".


Настройка производительности PL/SQL с помощью подсказки компилятору NOCOPY

По умолчанию параметры OUT и IN OUT передаются по значению. Т.е. значение актуального параметра IN OUT копируется в соответствующий формальный параметр. Затем, если подпрограмма выполняется успешно, значения, присвоенные формальным параметрам OUT и IN OUT копируются в соответствующие актуальные параметры.

Когда параметры содержат объемные структуры данных, например, такие как коллекции, записи, экземпляры объектных типов, то все эти процессы копирования замедляют выполнение приложения и расходуют дополнительную память. Чтобы предотвратить это вы можете указать подсказку NOCOPY, которая позволяет компилятору PL/SQL передавать параметры OUT и IN OUT по ссылке. В следующем примере Вы указываете компилятору, что IN OUT параметр my_unit нужно передавать по ссылке, а не по значению.

DECLARE
   TYPE Platoon IS VARRAY(200) OF Soldier;
   PROCEDURE reorganize (my_unit IN OUT NOCOPY Platoon) IS ...
BEGIN
   ...
END;

Подробнее смотрите "Passing Large Data Structures with the NOCOPY Compiler Hint".


Настройка производительности PL/SQL с помощью условия RETURNING

Часто приложениям необходима информация о записях, участвующих в операциях SQL, например, для того чтобы сгенерировать отчет или выполнить последующее действие. Запросы INSERT, UPDATE и DELETE могут содержать оператор RETURNING, который возвращает значения атрибутов из обрабатываемых записей в переменные PL/SQL или хост-переменные. Этот подход избавляет от необходимости выбирать запись снова после запросов на вставку или изменение, или перед запросом на удаление. Как результат - требуется меньше пересылок по сети, меньше процессорного времени, меньше курсоров и меньше памяти сервера.

В следующем примере вы изменяете зарплату сотрудника и одновременно с этим возвращаете имя сотрудника и новую зарплату в переменные PL/SQL.

PROCEDURE update_salary (emp_id NUMBER) IS
   name    VARCHAR2(15);
   new_sal NUMBER;
BEGIN
   UPDATE emp SET sal = sal * 1.1
      WHERE empno = emp_id
      RETURNING ename, sal INTO name, new_sal;
-- Здесь выполняем вычисления, используя name и new_sal
END;


Настройка производительности PL/SQL с помощью внешних процедур

PL/SQL имеет интерфейс для вызова процедур, написанных на других языках. Стандартные библиотеки уже написанные и доступные на других языках, могут быть вызваны из программ PL/SQL. Это дает возможность повторного использования, повышает эффективность и модульность.

PL/SQL приспособлен для обработки SQL-транзакций. Некоторые задачи выполняются быстрее на языках низкого уровня, таких как С, например, который является очень эффективным в расчетах с машинной точностью.

Чтобы ускорить выполнение, вы можете переписать процессорозависимые вычисления на С. Кроме того, вы можете переместить такие программы с клиента на сервер, где они будут исполняться быстрее благодаря мощности сервера и уменьшенному сетевому взаимодействию.

Например, вы можете написать методы для объектного типа, описывающего изображения, на C, сохранить их в виде динамической библиотеки (DLL), зарегистрировать эту библиотеку в PL/SQL, а затем обращаться к ней из ваших приложений. Во время выполнения, библиотеки загружаются динамически, и, для безопасности, запускается в отдельном адресном пространстве (выполняются как отдельный процесс).

Подробнее смотрите в "Oracle9i Application Developer's Guide - Fundamentals".


Повышение производительности PL/SQL с помощью объектных типов и коллекций

Типы-коллекции (см. Главу 5) и объектные типа (см. Главу 10) повышают вашу продуктивность, позволяя строить реалистичные модели данных. Сложные сущности реального мира и взаимосвязи отображаются прямо в объектные типы. Также, хорошо спроектированная объектная модель может улучшить производительность приложения избавляясь от объединения таблиц, сокращая круговые пересылки и тому подобное.

Клиентские программы, в том числе PL/SQL программы, могут объявлять объекты и коллекции, передавать их в качестве параметров, хранить их в базе данных, извлекать их, и так далее. Также, инкапсулируя методы обработки данных, объектные типы позволяют вам переместить код, зависимый от данных, из SQL скриптов и блоков PL/SQL в методы объектных типов.

Объекты и коллекции более эффективны для хранения и извлечения данных, так как все манипуляции осуществляются с ними как с единым целым. Также, поддержка объектов встроена в архитектуру базы данных, поэтому она имеет преимущество перед многими расширениями и улучшениями производительности, встроенных в каждый релиз Oracle.


Компиляция PL/SQL кода для Native-выполнения

Вы можете ускорить PL/SQL процедуры, компилируя их в native-код, размещаемый в разделяемых библиотеках. Процедуры переводятся в код на языке С, потом компилируются обычным С-компилятором и линкуются с процессом Oracle. Такой прием можно использовать как для стандартных пакетов Oracle, так и для написанных вами. Процедуры, скомпилированные таким образом, будут работать в различных серверных окружениях, таких как конфигурация разделяемого сервера (ранее известной как многопоточный (multi-threaded) сервер).

Из-за того, что этот прием не дает значительного прироста в скорости выполнения SQL выражений, вызываемых из PL/SQL, наиболее эффективным является его использование для интенсивных вычислительных PL/SQL процедур, в основном не занимающихся выполнением SQL.

Чтобы ускорить одну или более процедур используют следующий подход:

  1. Обновите поставляемый с Oracle make-файл и добавьте соответствующие пути и другие параметры, характерные для вашей системы. Файл находится по пути $ORACLE_HOME/plsql/spnc_makefile.mk.
  2. Используя команды ALTER SYSTEM или ALTER SESSION или обновляя инициализационный файл, установите параметр PLSQL_COMPILER_FLAGS, чтобы добавить значение NATIVE. По умолчанию, установки включают значение INTERPRETED, и вам нужно удалить это ключевое слово из значения параметра.
  3. Скомпилируйте одну или несколько процедур, используя один из методов:
    • Используйте команду ALTER PROCEDURE или ALTER PACKAGE для перекомпиляции процедуры или содержимого пакета.
    • Удалите процедуру и создайте ее заново.
    • Используйте CREATE OR REPLACE для компиляции процедуры.
    • Запустите один из скриптов SQL*Plus, который устанавливает набор стандартных Oracle пакетов.
    • Создайте базу данных, используя предварительно подготовленный файл параметров с PLSQL_COMPILER_FLAGS=NATIVE. Во время создания базы данных скрипт UTLIRP запускается для компиляции всех стандартных пакетов Oracle.
  4. Чтобы убедиться, что процесс отработал, можно запросить данные из словаря, по которым будет видно, что процедура скомпилирована для native-выполнения. Для проверки того, скомпилирована ли существующая процедура для native-выполнения или нет, можно запросить словарные представления USER_STORED_SETTINGS, DBA_STORED_SETTINGS, and ALL_STORED_SETTINGS. Например, для проверки статуса процедуры MY_PROC нужно ввести:
    SELECT param_value FROM user_stored_settings WHERE
      param_name = 'PLSQL_COMPILER_FLAGS'
      and object_name = 'MY_PROC';

    Столбец PARAM_VALUE имеет значение NATIVE для процедур, скомпилированных для native-выполнения, и INTERPRETED в другом случае.

После компиляции процедур и помещения их в разделяемые библиотеки, они автоматически линкуются с процессом Oracle. Не нужно перезапускать базу данных или перемещать разделяемые библиотеки в другое место. Вы можете беспрепятственно вызывать хранимые процедуры независимо от того, скомпилированы они все для режима по-умолчанию (interpreted), для native-выполнения или имеют разные режимы компиляции.

Так как значение PLSQL_COMPILER_FLAGS внутри библиотечного модуля хранится для каждой процедуры, то native-выполняемые процедуры при повторной автоматической перекомпиляции (когда объект становится поврежденным, например, из-за пересоздания таблицы, от которой зависит процедура), компилируются с первоначальными установками.

Вы можете контролировать выполнение native-компиляции через команды ALTER SYSTEM или ALTER SESSION или добавляя/изменяя следующие параметры в инициализационном файле:

Смотрите Oracle9i Database Reference для полного описания инициализионных параметров и представлений словаря данных.

Пример компиляции PL/SQL процедуры для естественного выполнения
connect scott/tiger;
set serveroutput on;
alter session set plsql_native_library_dir='/home/orauser/lib';
alter session set plsql_native_make_utility='gmake';
alter session set plsql_native_make_file_name='/home/orauser/spnc_makefile.mk';
alter session set plsql_compiler_flags='NATIVE';
create or replace procedure hello_native_compilation
as
begin
  dbms_output.put_line('Hello world');
  select sysdate from dual;
end;

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

Ограничения native-компиляции
      

* С каждым днем мне во всех отношениях становиться лучше и лучше. - Эмиль Куэ