Как стать автором
Обновить

Хранимые процедуры. Кто быстрее

Время на прочтение2 мин
Количество просмотров14K

О чем речь


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

А как насчет скорости? Понятно, что за скорость выборки отвечает ядро СУБД, составляющее план запроса, оптимизаторы, наличие индексов и т.д. Но речь пойдет не об этом.
Языки хранимых процедур современных СУБД обладают многими из свойств присущих классическим языкам программирования: наличие типов и переменных, циклов. Вот об их скорости и поговорим.

Если интересно как посчитать число Пи в трех разных СУБД или вспомнить курсовик по информатике за первый курс, то смотрите под кат.


Немного математики


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




Собственно, будем вычислять арктангенс, точность вычисления 10-7.

Firebird


create or alter procedure ARCTG (X double precision)
returns (S double precision, I integer)
as
declare variable U double precision;
begin
  S = X;
  U = X;
  I = 3;
  while (abs(U) >= 0.0000001) do
  begin
    U = -U*X*X*(I-2)/I;
    S = S + U;
    I = I + 2;
  end
  suspend;
end


Здесь S — значение арктангенса, I — количество итераций помноженное на 2 (приблизительно).
В процедурах других систем переменная I не выводилась, так как количество итераций будет везде одинаковым.
После программирования процедуры делаем

select 4*S,I from arctg(1)

Получаем наше число Пи и значение счетчика I=10 000 003, из чего делаем вывод, что для достижения требуемой точности нужно около 5 млн циклов. Время — 13,5 с.

MySQL


CREATE DEFINER = 'root'@'localhost'
FUNCTION ARCTG(X DOUBLE) RETURNS DOUBLE
BEGIN
  DECLARE U DOUBLE DEFAULT X;
  DECLARE S DOUBLE DEFAULT X;
  DECLARE I INT DEFAULT 3;
  WHILE (abs(U) >= 0.0000001) DO
    SET U = -U*X*X*(I-2)/I;
    SET S = S + U;
    SET I = I + 2;
  END WHILE;
  RETURN S;
END

Результат — 42,5 c

MsSQL


CREATE FUNCTION [ARCTG] (@X real=1) RETURNS real
WITH EXECUTE AS CALLER
AS
BEGIN
DECLARE @S AS REAL
DECLARE @U AS REAL
DECLARE @I AS INT
SET @S = @X
SET @U = @X
SET @I = 3
WHILE (abs(@U) >= 0.0000001)
BEGIN
  SET @U = -@U*@X*@X*(@I-2)/@I
  SET @S = @S + @U
  SET @I = @I + 2
END
RETURN @S;
END

Результат — 12 с

Итоги


1. MsSQL 2005 — 12 с
2. Firebird 2.5 — 13,5 с
3. MySQL 5.1 — 42,5 с

Все тесты проводились на машине Athlon 3200+, ОС — windows XP.
Результат с MySQL удивил. Возможно проблема была в том, что он шел в наборе Vertrigo и сконфигурирован не оптимальным образом. Если кто-то проведет аналогичные тесты, будет интересно узнать.
Ну напоследок

Время кода на С (компилятор Borland, код приводить не буду) составило порядка 200 тиков (функция GetTickCount), т.е. около 0,2 с. После этого была мысль перенести топик в «Ненормальное программирование», но все таки размещаю его здесь со следующими противоречащими друг другу выводами (кому какой нравится):
1. Не стоит выполнять большие и сложные вычисления с помощью механизмов СУБД, хоть они это и могут, а выносить логику за пределы СУБД.
или
2. Движкам СУБД есть к чему стремиться.
Теги:
Хабы:
Всего голосов 22: ↑11 и ↓110
Комментарии32

Публикации