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


Собственно, будем вычислять арктангенс, точность вычисления 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. Движкам СУБД есть к чему стремиться.
