DeepEdit!

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

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

PL/SQL против Oracle JVM: Сравнение скорости для математических операций

Oracle поставил виртуальную машину Java (JVM) как часть базы данных начиная с Oracle 8i. Несколько лет назад я слышал упоминание о том, что JVM Oracle была быстрее для математических операций чем PL/SQL, но никогда не обращал на это большого внимание. В этой статье я делаю сравнение скорости PL/SQL и JVM Oracle для некоторых основных математических операций.
Я - PL/SQL-программист и смотрю на все с этой точки зрения. Именно поэтому все тесты базируются вокруг операций, вызываемых из PL/SQL.
Сначала мы должны создать некоторый Java код в базе данных, чтобы выполнить наши математические операции. Следующий код Java определяет класс под названием "Mathematics", которая содержит пять статических функций для выполнения сравнения (+, - *,/, mod).
CREATE OR REPLACE AND COMPILE JAVA SOURCE NAMED "Mathematics" AS
import java.lang.*;
public class Mathematics
{
public static int addFn (int Number1, int Number2)
{
return Number1 + Number2;
}
public static int subtractFn (int Number1, int Number2)
{
return Number1 - Number2;
}
public static int multiplyFn (int Number1, int Number2)
{
return Number1 * Number2;
}
public static int divideFn (int Number1, int Number2)
{
return Number1 / Number2;
}
public static int modFn (int Number1, int Number2)
{
return Number1 % Number2;
}
};
/
Затем мы определяем заголовок пакета, содержащий спецификации вызова для этих пяти функций, определенных в Java ранее, чтобы фактически протестировать их.
CREATE OR REPLACE PACKAGE maths_test AS
FUNCTION addFn (p_number1 IN NUMBER, p_number2 IN NUMBER) RETURN NUMBER
AS LANGUAGE JAVA
NAME 'Mathematics.addFn (int, int) return int';
FUNCTION subtractFn (p_number1 IN NUMBER, p_number2 IN NUMBER) RETURN NUMBER
AS LANGUAGE JAVA
NAME 'Mathematics.subtractFn (int, int) return int';
FUNCTION multiplyFn (p_number1 IN NUMBER, p_number2 IN NUMBER) RETURN NUMBER
AS LANGUAGE JAVA
NAME 'Mathematics.multiplyFn (int, int) return int';
FUNCTION divideFn (p_number1 IN NUMBER, p_number2 IN NUMBER) RETURN NUMBER
AS LANGUAGE JAVA
NAME 'Mathematics.divideFn (int, int) return int';
FUNCTION modFn (p_number1 IN NUMBER, p_number2 IN NUMBER) RETURN NUMBER
AS LANGUAGE JAVA
NAME 'Mathematics.modFn (int, int) return int';
PROCEDURE test (p_operation IN VARCHAR2);
END maths_test;
/
Тело пакета только содержит определение "тестовой" процедуры, которая сравнивает скорость PL/SQL и Java.
CREATE OR REPLACE PACKAGE BODY maths_test AS
PROCEDURE test (p_operation IN VARCHAR2) AS
l_start SIMPLE_INTEGER := 0; -- Use PLS_INTEGER prior to 11g
l_val SIMPLE_INTEGER := 0; -- Use PLS_INTEGER prior to 11g
l_loops NUMBER := 1000000;
BEGIN
l_start := DBMS_UTILITY.get_time;
FOR i IN 1 .. l_loops LOOP
CASE LOWER(p_operation)
WHEN '+' THEN l_val := i + 2;
WHEN '-' THEN l_val := i - 2;
WHEN '*' THEN l_val := i * 2;
WHEN '/' THEN l_val := i / 2;
WHEN 'mod' THEN l_val := MOD(i, 2);
END CASE;
END LOOP;
DBMS_OUTPUT.put_line('PL/SQL (' || p_operation || '): ' || (DBMS_UTILITY.get_time - l_start) || ' hsecs');
l_start := DBMS_UTILITY.get_time;
FOR i IN 1 .. l_loops LOOP
CASE LOWER(p_operation)
WHEN '+' THEN l_val := addFn(i, 2);
WHEN '-' THEN l_val := subtractFn(i, 2);
WHEN '*' THEN l_val := multiplyFn(i, 2);
WHEN '/' THEN l_val := divideFn(i, 2);
WHEN 'mod' THEN l_val := modFn(i, 2);
END CASE;
END LOOP;
DBMS_OUTPUT.put_line('Java (' || p_operation || '): ' || (DBMS_UTILITY.get_time - l_start) || ' hsecs');
END test;
END maths_test;
/
Следующий вывод ясно показывает, что JVM Oracle - медленнее при выполнении математических операций чем PL/SQL.
SQL> SET SERVEROUTPUT ON
SQL> EXEC maths_test.test('+');
PL/SQL (+): 9 hsecs
Java (+): 2260 hsecs
PL/SQL procedure successfully completed.
SQL> EXEC maths_test.test('-');
PL/SQL (-): 12 hsecs
Java (-): 2314 hsecs
PL/SQL procedure successfully completed.
SQL> EXEC maths_test.test('*');
PL/SQL (*): 16 hsecs
Java (*): 2332 hsecs
PL/SQL procedure successfully completed.
SQL> EXEC maths_test.test('/');
PL/SQL (/): 53 hsecs
Java (/): 2417 hsecs
PL/SQL procedure successfully completed.
SQL> EXEC maths_test.test('mod');
PL/SQL (mod): 70 hsecs
Java (mod): 2360 hsecs
PL/SQL procedure successfully completed.
SQL>
Этот тест не справедлив для JVM. Что, если мы перепишем это так, чтобы весь тест Java был обработан в Java?
CREATE OR REPLACE AND COMPILE JAVA SOURCE NAMED "Mathematics" AS
import java.lang.*;
public class Mathematics
{
public static void testJava (int operation, int loops)
{
int val;
for (int i=1; i <= loops; i++) {
switch (operation) {
case 1: val = i + 2; break;
case 2: val = i - 2; break;
case 3: val = i * 2; break;
case 4: val = i / 2; break;
case 5: val = i % 2; break;
}
}
}
};
/
Заголовок пакета теперь нуждается только в единственной спецификации вызова Java.
CREATE OR REPLACE PACKAGE maths_test AS
PROCEDURE testjava (p_operation IN NUMBER, p_loops IN NUMBER)
AS LANGUAGE JAVA
NAME 'Mathematics.testJava (int, int)';
PROCEDURE test (p_operation IN VARCHAR2);
END maths_test;
/
У тела пакета есть несколько изменений. Во-первых, это преобразование параметра в число, таким образом его можно передать в Java и использовать в операторе переключения. Это выглядит немного глупым, но это добавляет немного скорости в Java. Во-вторых, есть единственный вызов кода java.
CREATE OR REPLACE PACKAGE BODY maths_test AS
PROCEDURE test (p_operation IN VARCHAR2) AS
l_start PLS_INTEGER := 0;
l_val PLS_INTEGER := 0;
l_loops NUMBER := 1000000;
l_operation NUMBER;
BEGIN
-- Translate the original operaton string to number so I can use switch in Java.
CASE LOWER(p_operation)
WHEN '+' THEN l_operation := 1;
WHEN '-' THEN l_operation := 2;
WHEN '*' THEN l_operation := 3;
WHEN '/' THEN l_operation := 4;
WHEN 'mod' THEN l_operation := 5;
END CASE;
l_start := DBMS_UTILITY.get_time;
FOR i IN 1 .. l_loops LOOP
CASE l_operation
WHEN 1 THEN l_val := i + 2;
WHEN 2 THEN l_val := i - 2;
WHEN 3 THEN l_val := i * 2;
WHEN 4 THEN l_val := i / 2;
WHEN 5 THEN l_val := MOD(i, 2);
END CASE;
END LOOP;
DBMS_OUTPUT.put_line('PL/SQL (' || p_operation || '): ' || (DBMS_UTILITY.get_time - l_start) || ' hsecs');
l_start := DBMS_UTILITY.get_time;
testJava(l_operation, l_loops);
DBMS_OUTPUT.put_line('Java (' || p_operation || '): ' || (DBMS_UTILITY.get_time - l_start) || ' hsecs');
END test;
END maths_test;
/
Тесты теперь показывают, что JVM Oracle выигрывает у PL/SQL для цикличного выполнения и математической обработки.
SQL> SET SERVEROUTPUT ON
SQL> EXEC maths_test.test('+');
PL/SQL (+): 7 hsecs
Java (+): 4 hsecs
PL/SQL procedure successfully completed.
SQL> EXEC maths_test.test('-');
PL/SQL (-): 10 hsecs
Java (-): 4 hsecs
PL/SQL procedure successfully completed.
SQL> EXEC maths_test.test('*');
PL/SQL (*): 15 hsecs
Java (*): 4 hsecs
PL/SQL procedure successfully completed.
SQL> EXEC maths_test.test('/');
PL/SQL (/): 40 hsecs
Java (/): 6 hsecs
PL/SQL procedure successfully completed.
SQL> EXEC maths_test.test('mod');
PL/SQL (mod): 62 hsecs
Java (mod): 5 hsecs
PL/SQL procedure successfully completed.
SQL>
Эти результаты являются непротиворечивыми для этого теста на версиях базы данных (9.2, 10.2, 11.1 и 11.2).
Это означает, что вы должны переписать весь ваш PL/SQL код на Java? Нет. Мы не приняли во внимание масштабируемость или воздействие многочисленных пользователей на JVM Oracle. Я избежал исследования собственной компиляции, так как и PL/SQL и Java может быть исходно скомпилирован. Я только подумал, что это было бы интересно.







jAntivirus
 


Мини колесные вездеходы видео Викинг . Более 12000 позиций,низкие цены - труборез. Гильотинные ножницы.