PL/SQL Native Compilation - "разгон" выполнения хранимых процедур

Oracle Database версии 11g, помимо множества новых возможностей и улучшений, принесла еще одну замечательную технологию - PL/SQL Native Compilation.

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

Существует два варианта компиляции ваших хранимых процедур PL/SQL:
- interpreted (в результате из исходного кода процедуры получается интерпретируемый код виртуальной машины PL/SQL);
- native (в результате компиляции на выходе получается исполняемый код текущей платформы).



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

Возможность компиляции кода процедуры была доступна еще начиная с версии 9.2 , но она была реализована через генерацию промежуточного C-кода, с последующей его компиляцией в нативный код платформы. Это создавало массу неудобств:
- нужно лицензировать и устанавливать C-компилятор;
- после линковки объектного модуля на выходе получался большой по размеру файл разделяемой библиотеки (dll,so,sl, ...), потому-что линкер честно "запихивал" в каждый модуль runtime-библиотеку C.

С второй проблемой можно было бороться двумя способами: динамической линковкой стандартных runtime-библиотек C, либо "обезжириванием" этих библиотек через правку исходников (что требует серьезной "сишной" квалификации и в общем случае чревато проблемами).

Лично мой опыт показал, что для получения максимального выигрыша от этой технологии мне потребуется сделать редизайн и перегруппировку своего PL/SQL-кода, что было невозможно по временным и ресурсным ограничениям. Я использовал платформу Windows и компилятор Visual C. После компиляции получались dll-файлы неприличных размеров - выполняемый код "разбухал".
Вообщем: Native Compilation не пользовался успехом у разработчиков и администраторов.

Но теперь все это позади - начиная с 11-ой версии, компилятор PL/SQL может генерировать исполняемый код на "лету", - нет необходимости ставить и настраивать С-компилятор.
Все что для этого нужно: это установить параметр PLSQL_CODE_TYPE в значение NATIVE, и после этого перекомпилировать процедуры.

Какой выигрыш в скорости выполнения обеспечивает native-компиляция PL/SQL ?
Все зависит от вашего PL/SQL-кода: если в нем много логики, но мало обращения к БД (к SQL-движку), то скорость возрастает в разы! Если наоборот, весь код состоит из оператов SQL, то выигрыш конечно будет небольной, - обращения к СУБД "съедают" львиную долю времени выполнения.
В большинстве случаев код имеет смешанный характер, то есть состоит из вычислительной обработки и операторов SQL. Nаtive Compilation даже в этом случае дает существенный выигрыш в производительности. Конечно, реальный коэффициент ускорения может быть получен только после тестов на конкретном приложении.

В случае принятия решения об использовании PL/SQL Native Complilation рекомендуется целиком перекомпилировать весь PL/SQL в СУБД. В документации по PL/SQL приведена подробная инструкция как это сделать: Compiling the Entire Database for PL/SQL Native or Interpreted Compilation


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

По результатам тестов - скорость выполнения увеличилась примерно в три раза !

Хочу поделиться некоторыми наблюдениями:
- время компиляции в Native-режиме сильно замедляется (на моем 2-хпроцессорном сервере с 2 Xeon Nehalem перекомпиляция всей СУБД заняла около 4 чаcов!), поэтому ее не рекомендуется включать на development-среде;
- возрастают требования к памяти - выполняемый код больше по объему, чем код PL/SQL VM (в моем случае процентов на 10-15, но скорее всего это из-за inline-подстановки);
- при выполнении native-скомпилированных процедур возрастает утилизация процессоров, поэтому при переходе в этом режим нужно иметь запас в CPU, на мой взгляд - минимум процентов на 20-30.

По-моему PL/SQL native compilation очень интересная возможность Oracle Database 11g - почему бы ее не использовать ?

P.S. Поделилтесь, пожалуйста, в комментариях к этому посту о своем опыте использования этой технологии.

9 комментариев:

  1. Я пробовал нативно компилить PL/SQL Web Toolkit (aka OWA), получилось не слишком заметно - порядка +10% RPS на генерации статической странички через htp.p(). Другое дело, что на Xeon 5345 (HP DL 360G5) в абсолютных цифрах это было порядка и так 8000 RPS, если стрелять по Apache + mod_owa.

    ОтветитьУдалить
  2. Мы протестировали и использовали указанную возможность (выполнение внешней процедуры на языке С)
    на Оракл 9.2.х, 10.1.х, 10.2.х. для ускорения процедуры расчета, написанной сначала на PL\SQL
    и выполняемой в цикле многократно (сотни тысяч раз). Как недостаток – наличие больших сложностей
    при компилировании «сишным» компилятором DLL-библиотеки под различные платформы Windows (x86, x64)
    и процессоры (Itanium, AMD). Тут стоит сказать о намного более «легком» получении shared object
    под Linux платформу (Red Hat) - создать нужный make файл оказалось намного проще.
    (Тестировали на 11g при дефолтовом значении параметра PLSQL_OPTIMIZE_LEVEL=2.)

    Проведенные тесты показали различную скорость выполнения одной и той же процедуры на языках С,
    Java (как вызываемых внешних процедур) и PL\SQL для разных версий БД и режимов компиляции.

    Скорость выполнения внешней процедуры на C и Java ориентировочно
    в два раза выше, чем процедуры на PL\SQL для БД Oracle 9iR2.
    В случае БД Оракл 10gR2, 11gR1, 11gR2 время выполнения кода на PL\SQL сократилось в 2.5-3 раза,
    относительно времени, затраченного на выполнения внешних процедур на языках C и Java.
    При этом режим Nаtive Compilation быстрее приблизительно на 25-30% от режима INterpreted Compilation
    для версий БД 10gR2, 11gR1, 11gR2. Процедуры, написанные на C и Java, практически близкие по времени
    выполнения между собой, это время практически не зависит от режима компиляции Nаtive или INterpreted.

    Отсюда выводы (для данного конкретного случая):
    1) выполнение PL\SQL кода значительно ускорено в версиях 10g и 11g по сравнению с 9i (в 5-10 раз);
    2) внешние процедуры на C и Java проигрывают по скорости PL\SQL в 2 и более раза на 10gR2, 11g(R1,R2);
    3) при включении режима Nаtive Compilation на сессию скорость тестируемой процедуры на PL\SQL увеличилась
    приблизительно на одну треть относительно режима Interpreted Compilation.

    ОтветитьУдалить
  3. Данные сведены в две таблицы:
    Табл.1 - Oracle DB: INterpreted Compilation
    Табл.2 - Oracle DB: Nаtive Compilation

    Сокращения ОС:
    L - Linux RHAS rel.4 Nehalem 64-bit;
    W - Windows XP SP3 32-bit.

    Табл.1. INTERPRETED COMPILATION (ORACLE DB)
    -------------------------------------------------------------------
    Cycles 5000 50000 500000 5000000
    (times in seconds)
    -------------------------------------------------------------------
    Oracle DB 9iR2 (L): - PL\SQL 0.953 8.656 87.282 835.531
    - Java 0.500 4.594 44.109 437.984
    - C 0.500 4.641 48.453 457.125

    Oracle DB 10gR2 (L):- PL\SQL 0.203 1.656 16.484 165.500
    - Java 0.422 4.094 40.235 410.895
    - C 1.938 4.890 51.265 529.219

    Oracle DB 11gR1 (W):- PL\SQL 0.125 1.031 10.203 102.187
    - Java 0.125 1.328 13.203 131.266

    Oracle DB 11gR2 (L):- PL\SQL 0.359 1.735 12.391 109.859
    - Java 0.484 1.844 18.766 178.484
    - C 0.562 5.500 50.703 406.985
    -------------------------------------------------------------------


    Табл.2. NATIVE COMPILATION (ORACLE DB)
    -------------------------------------------------------------------
    Cycles 5000 50000 500000 5000000
    Program (times in seconds)
    -------------------------------------------------------------------
    Oracle DB 10gR2 (L):- PL\SQL 0.156 1.531 15.360 153.109
    - Java 0.422 4.140 41.963 415.719
    - C 0.500 4.875 52.735 513.407

    Oracle DB 11gR1 (W):- PL\SQL 0.094 0.688 6.790 67.828
    - Java 0.203 1.313 13.219 132.219

    Oracle DB 11gR2 (L):- PL\SQL 0.172 1.172 8.500 71.891
    - Java 0.344 2.297 18.125 179.976
    - C 0.672 5.547 44.141 385.125
    -------------------------------------------------------------------

    ОтветитьУдалить
  4. К выводам вдобавок (к выполнению конкретной процедуры на PL\SQL):
    4) Interpreted Compilation в 11g (оказался в этом случае) быстрее чем в 10g в 1.5 раза.
    5) Native Compilation в 11g оказался быстрее чем в 10g в 2.1 раза.

    ОтветитьУдалить
  5. Игорь, а можете опубликовать исходный код, от которого данные Ваших тестов? Смущает медленное выполнение на C. Первое, что приходит в голову - тормозит в extproc IPC передачей большого объёма параметров туда/обратно.

    ОтветитьУдалить
  6. > Oracle Database версии 11g, помимо множества новых возможностей и улучшений, принесла еще одну замечательную технологию - PL/SQL Native Compilation.

    Не скажу точно на счет 9-й версии, но в 10g Native Compilation точно есть. Поэтому, фича хорошая, нужная, но никак не новая.

    ОтветитьУдалить
  7. >>Игорь, а можете опубликовать исходный код, от которого данные Ваших тестов?

    Как таковых отдельных тестов не было.
    Это было воспроизведение реальной нагрузки с помощью RAT (Real Application Testing) на копии большой производственной БД заказчика.

    Да действительно: External Library медленнее, поскольку нужно передавать параметры отдельному процессу.
    Еще конечно нужно "поколдовать" с опциями C-компилятора (убрать ненужные runtime-проверки и включить оптимизацию).

    ОтветитьУдалить
  8. >>Не скажу точно на счет 9-й версии, но в 10g Native Compilation точно есть.

    Да - технология не новая. Но теперь реализована по другому, и избавлена от недостатков старых версий.

    ОтветитьУдалить
  9. Анонимный31/8/10 6:22 PM

    вместе с OLS получается баг 9869915

    ОтветитьУдалить