Известно, что сервер Oracle способен выполнять Java код, что может добавить определенные преимущества вашему приложению. Однако многие разработчики не используют эту возможность по разным причинам. Одним из основных является то обстоятельство, что PL/SQL это очень развитый язык программирования и, самое главное, он напрямую поддерживает доступ к данным через встроенный SQL. В этой связи применение Java на стороне сервера не выглядит очень оправданным. Однако, если требуется выполнение большого количества математических операций, то наш взор может быть обращен в сторону Java с вопросом, а не позволит ли код на Java выполнять математические и другие операции, не связанные с обращением напрямую к базе данных, быстрее, чем аналогичный код на PL/SQL? Если это так, то некоторые вычислительные функции есть смысл переписать на Java, ускорив выполнение критичных участков кода наших приложений.
Попробуем это выяснить, создав соответствующий тест производительности.
Для такого теста выберем вычисление экспоненты в цикле, заполнение обычных и
индексных массивов (
ассоциативных массивов), а также поиск по индексным массивам, и затем сравним время выполнения одинаковых алгоритмов на
PL/SQL и
Java. Работа с индексными массивами нами уже обсуждалась в статье "
Индексные массивы в Oracle PL/SQL"
Код для тестирования на PL/SQL и Java
Для тестирования Java кода создадим такой класс:
CREATE OR REPLACE AND RESOLVE JAVA SOURCE NAMED "java_test" AS
import JAVA.lang.*;
import JAVA.util.*;
PUBLIC class java_test
{
static HashMap Map=NEW HashMap();
PUBLIC static void exp_test()
{
double n;
FOR (int i=1; i<=1000000; i++)
n=Math.EXP(1/(double)i);
}
PUBLIC static void array_add_test()
{
double[] arr=NEW double[5000000];
FOR (int i=0; i<5000000; i++)
arr[i]=1/(double)i;
}
PUBLIC static void hashmap_add_test()
{
double n;
FOR (int i=1; i<=1000000; i++)
Map.put(NEW INTEGER(i),NEW Double(1/(double)i));
}
PUBLIC static void hashmap_search_test()
{
FOR (int i=1; i<=1000000; i++)
Map.get(NEW INTEGER(i));
}
}
/
Для загрузки класса на сервер Oracle просто выполните приведенный выше код в SQL*Plus.
Для тестирования PL/SQL кода и вызова методов на Java создадим PL/SQL пакет plsql_java_test:
Код спецификации пакета:
CREATE OR REPLACE
PACKAGE plsql_java_test
IS
TYPE ttMAP_P IS TABLE OF NUMBER INDEX BY PLS_INTEGER;
TYPE ttMAP_V IS TABLE OF NUMBER INDEX BY VARCHAR2(48);
gtMAP_P ttMAP_P;
gtMAP_V ttMAP_V;
PROCEDURE plsql_exp_test;
PROCEDURE java_exp_test;
PROCEDURE plsql_array_add_test;
PROCEDURE java_array_add_test;
PROCEDURE plsql_hashmap_int_add_test;
PROCEDURE plsql_hashmap_varchar_add_test;
PROCEDURE java_hashmap_add_test;
PROCEDURE plsql_hashmap_int_search;
PROCEDURE plsql_hashmap_varchar_search;
PROCEDURE java_hashmap_search;
END plsql_java_test;
/
Код тела пакета:
CREATE OR REPLACE
PACKAGE BODY plsql_java_test
IS
PROCEDURE plsql_exp_test
IS
n NUMBER;
BEGIN
FOR i IN 1..1000000
LOOP
n:=1/i;
n:=EXP(n);
END LOOP;
END plsql_exp_test;
PROCEDURE java_exp_test
AS language JAVA
name 'java_test.exp_test()';
PROCEDURE plsql_array_add_test
IS
TYPE ttARR IS varray(5000000) OF NUMBER;
ltARR ttARR:=ttARR();
n NUMBER;
BEGIN
ltARR.extend(5000000);
FOR i IN 1..5000000
LOOP
n:=1/i;
ltARR(i):=n;
END LOOP;
END plsql_array_add_test;
PROCEDURE java_array_add_test
AS language JAVA
name 'java_test.array_add_test()';
PROCEDURE plsql_hashmap_int_add_test
IS
n NUMBER;
BEGIN
gtMAP_P.DELETE;
FOR i IN 1..1000000
LOOP
n:=1/i;
gtMAP_P(i):=n;
END LOOP;
END plsql_hashmap_int_add_test;
PROCEDURE plsql_hashmap_varchar_add_test
IS
n NUMBER;
BEGIN
gtMAP_V.DELETE;
FOR i IN 1..1000000
LOOP
n:=1/i;
gtMAP_V(i):=n;
END LOOP;
END plsql_hashmap_varchar_add_test;
PROCEDURE java_hashmap_add_test
AS language JAVA
name 'java_test.hashmap_add_test()';
PROCEDURE plsql_hashmap_int_search
IS
n NUMBER;
BEGIN
IF gtMAP_P.COUNT=0
THEN
plsql_hashmap_int_add_test;
END IF;
FOR i IN 1..1000000
LOOP
n:=gtMAP_P(i);
END LOOP;
END plsql_hashmap_int_search;
PROCEDURE plsql_hashmap_varchar_search
IS
n NUMBER;
BEGIN
IF gtMAP_V.COUNT=0
THEN
plsql_hashmap_varchar_add_test;
END IF;
FOR i IN 1..1000000
LOOP
n:=gtMAP_V(i);
END LOOP;
END plsql_hashmap_varchar_search;
PROCEDURE java_hashmap_search
AS language JAVA
name 'java_test.hashmap_search_test()';
END plsql_java_test;
/
После этого начнем выполнение тестов. Приведенные ниже показатели были получены на ноутбуке Lenovo SL500 c Intel Core Duo 2GHz, 3Gb RAM, Windows XP, Oracle Server 10g
После запуска SQL*Plus не забудьте включить измерение времени выполнения функций, выполнив команду
Выполним первый тест, который будет вычислять в цикле экспоненту числа.
Для PL/SQL:
EXEC plsql_java_test.plsql_exp_test
Elapsed: 00:00:08.50
Для Java:
EXEC plsql_java_test.java_exp_test
Elapsed: 00:00:00.70
Как мы видим, при выполнении математических операций Java быстрее PL/SQL в 12 раз.
Второй тест будет заполнять массив чисел в Java и коллекцию VARRAY в PL/SQL.
Для PL/SQL:
EXEC plsql_java_test.plsql_array_add_test
Elapsed: 00:00:04.10
Для Java:
EXEC plsql_java_test.java_array_add_test
Elapsed: 00:00:00.48
Здесь выигрыш Java более чем в 8 раз.
Третий тест будет заполнять ассоциативный массив в PL/SQL и HashMap в Java:
Для PL/SQL (для индекса в массиве
pls_integer):
EXEC plsql_java_test.plsql_hashmap_int_add_test
Elapsed: 00:00:00.84
Для PL/SQL (для индекса в массиве
varchar2):
EXEC plsql_java_test.plsql_hashmap_varchar_add_test
Elapsed: 00:00:02.12
Для Java:
EXEC plsql_java_test.java_hashmap_add_test
Elapsed: 00:00:08.18
А здесь все наоборот, выигрывает PL/SQL. Для ассоциативного массива с индексом pls_integer выигрыш PL/SQL составляет почти 10 раз, а для массива с индексом varchar2 почти в 4 раза.
Последний четвертый тест будет выполнять индексный поиск по ранее заполненным предыдущими процедурами индексным массивам:
Для PL/SQL (для индекса в массиве
pls_integer):
EXEC plsql_java_test.plsql_hashmap_int_search
Elapsed: 00:00:00.09
Для PL/SQL (для индекса в массиве
varchar2):
EXEC plsql_java_test.plsql_hashmap_varchar_search
Elapsed: 00:00:01.14
Для Java:
EXEC plsql_java_test.java_hashmap_search
Elapsed: 00:00:04.14
Индексный поиск также выигрывает PL/SQL примерно с теми же показателями.
Попробуем осмыслить полученные результаты. Для чисто математических операций и операций с обычными массивами использование Javа более чем предпочтительно, Java код выполняется в среднем в 10 раз быстрее. При работе с ассоциативными (индексными) массивами PL/SQL выигрывает у Java минимум в 4 раза перед HashMap в Java. Попутно заметим, что скорость заполнения PL/SQL индексного массива с индексом varchar2 медленнее аналогичного массива с индексом pls_integer в 2,5 раза, что не так уж и много. Можно также сделать вывод о великолепной внутренней организации индексных массивов PL/SQL, скорость работы с которыми достаточно впечатляет.
Что в итоге?
Общий итог выполненных сравнительных тестов на взгляд автора состоит в том, что не требуется без действительной необходимости использовать Java код на стороне сервера вместо PL/SQL кода, который в целом очень неплохо оптимизирован. Однако могут возникать задачи, требующие большого количества математических операций и работы с обычными массивами. В этом случае при грамотном подходе скорость работы Java кода впечатляет и Java код может быть с успехом использован для оптимизации ваших приложений.
Для ускорения кода в PL/SQL также может использоваться технология PL/SQL Native Compilation (NCOMP). Мы рассмотрим эту технологию в следующих статьях и попробуем ответить на вопрос, сможет ли конкурировать PL/SQL c Java во всех аспектах при использовании NCOMP.
Смотрите также:
Оставьте свой комментарий
Вы должны быть авторизированны, чтобы оставить комментарий.