Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Microsoft SQL Server Новый топик    Ответить
 Кеширование функции???  [new]
hosTuk
Member

Откуда:
Сообщений: 455
Здравствуйте.
Наверное задаю вопрос, который неоднократно поднимался.
Вид запроса примерно такой:

SELECT
(
SELECT SUM(AOT.r_sum_pred)
FROM OT07_DBF_MAIN.dbo.AOTSCHT AS AOT
WHERE (AOT.N_SCHETA=W.N_SCHETA)AND(AOT.d_pred_sch=W.d_pred_sch)
AND((AOT.dpl_n=W.dpl_n) OR ((W.dpl_n IS NULL) AND (AOT.dpl_n IS NULL)))AND
(AOT.N_SERTIF = W.N_SERTIF)
)
AS SumRealForSert
FROM OT07_DBF_MAIN.dbo.AOTSCHP_WORK AS W
LEFT JOIN OT07_DBF_MAIN.dbo.AOTSCHT AS T
ON (W.N_SCHETA=T.N_SCHETA)AND(W.d_pred_sch=T.d_pred_sch)
AND((W.dpl_n=T.dpl_n) OR ((W.dpl_n IS NULL) AND (T.dpl_n IS NULL)))
GROUP BY W.n_scheta, W.d_pred_sch, W.dpl_n,W.n_sertif
ORDER BY W.n_scheta, W.d_pred_sch, W.dpl_n,W.n_sertif

Меняю подзарпос на функцию вида:

CREATE FUNCTION dbo.SumRealForSertif
(@N_SCHETA float,
@d_pred_sch float,
@dpl_n nvarchar(1),
@N_SERTIF float)
RETURNS float
AS
BEGIN
DECLARE @Res float;

-- Получили сумму реализации по конкретному сертификату
SELECT @Res=SUM(AOT.r_sum_pred)
FROM OT07_DBF_MAIN.dbo.AOTSCHT AS AOT
WHERE (AOT.N_SCHETA=@N_SCHETA)AND(AOT.d_pred_sch=@d_pred_sch)
AND((AOT.dpl_n=@dpl_n) OR ((@dpl_n IS NULL) AND (AOT.dpl_n IS NULL)))AND
(AOT.N_SERTIF = @N_SERTIF)

RETURN @RES
END

Вызов:

SELECT dbo.SumRealForSertif(W.N_SCHETA, W.d_pred_sch, W.dpl_n, W.N_SERTIF)
FROM OT07_DBF_MAIN.dbo.AOTSCHP_WORK AS W
LEFT JOIN OT07_DBF_MAIN.dbo.AOTSCHT AS T
ON (W.N_SCHETA=T.N_SCHETA)AND(W.d_pred_sch=T.d_pred_sch)
AND((W.dpl_n=T.dpl_n) OR ((W.dpl_n IS NULL) AND (T.dpl_n IS NULL)))
GROUP BY W.n_scheta, W.d_pred_sch, W.dpl_n,W.n_sertif
ORDER BY W.n_scheta, W.d_pred_sch, W.dpl_n,W.n_sertif

Т.к. при каждом вызове функции происходит просмотр таблицы OT07_DBF_MAIN.dbo.AOTSCHT
кот. имеет 800 тыс. записей.
Как сделать подсчет суммы в функции, но чтобы быстродействие от этого не пострадало.

Можете отправлять на маны;)
29 июл 09, 11:08    [7472528]     Ответить | Цитировать Сообщить модератору
 Re: Кеширование функции???  [new]
Glory
Member

Откуда:
Сообщений: 104760
hosTuk

Как сделать подсчет суммы в функции, но чтобы быстродействие от этого не пострадало.


Не использовать функцию
29 июл 09, 11:11    [7472544]     Ответить | Цитировать Сообщить модератору
 Re: Кеширование функции???  [new]
hosTuk
Member

Откуда:
Сообщений: 455
Не использовать функцию.
Это писать все подзапросами или есть другой путь решения?
29 июл 09, 11:14    [7472576]     Ответить | Цитировать Сообщить модератору
 Re: Кеширование функции???  [new]
Glory
Member

Откуда:
Сообщений: 104760
hosTuk
Не использовать функцию.
Это писать все подзапросами или есть другой путь решения?

Не использовать функцию в данном случае, не означает писать все подзапросами.
В данном случае функция по сравнению с подзапросом только дает дополнительные накладные расходы для ее вызова для каждой записи запроса.
29 июл 09, 11:16    [7472597]     Ответить | Цитировать Сообщить модератору
 Re: Кеширование функции???  [new]
vino
Member

Откуда:
Сообщений: 1191
hosTuk, судя по теме вам нужно представление по редко меняющейся таблице
29 июл 09, 11:18    [7472610]     Ответить | Цитировать Сообщить модератору
 Re: Кеширование функции???  [new]
hosTuk
Member

Откуда:
Сообщений: 455
Имел ввиду в данном случае, только подзапросом?
29 июл 09, 11:19    [7472617]     Ответить | Цитировать Сообщить модератору
 Re: Кеширование функции???  [new]
Glory
Member

Откуда:
Сообщений: 104760
hosTuk
Имел ввиду в данном случае, только подзапросом?

Ну есть еще derived table
29 июл 09, 11:23    [7472650]     Ответить | Цитировать Сообщить модератору
 Re: Кеширование функции???  [new]
vino
Member

Откуда:
Сообщений: 1191
если так, то сделайте вьюшку типа такой
CREATE VIEW dbo.vSumRealForSertif AS
	SELECT SUM(AOT.r_sum_pred), AOT.N_SCHETA, AOT.d_pred_sch, AOT.N_SERTIF, AOT.dpl_n
	FROM OT07_DBF_MAIN.dbo.AOTSCHT AS AOT
	GROUP BY AOT.N_SCHETA, AOT.d_pred_sch, AOT.N_SERTIF, AOT.dpl_n
29 июл 09, 11:26    [7472671]     Ответить | Цитировать Сообщить модератору
 Re: Кеширование функции???  [new]
hosTuk
Member

Откуда:
Сообщений: 455
Затем это представление использовать в подзапросе?
Не совсем понял дальнейшее использование преставления в запросе
Выигрыш только за счет суммирования? если делать в той же функции
29 июл 09, 11:38    [7472773]     Ответить | Цитировать Сообщить модератору
 Re: Кеширование функции???  [new]
Glory
Member

Откуда:
Сообщений: 104760
hosTuk
Затем это представление использовать в подзапросе?
Не совсем понял дальнейшее использование преставления в запросе
Выигрыш только за счет суммирования? если делать в той же функции

Вы знакомы с разными вариантами соединений ?
Кроме выполнения подзапроса для каждой строки запроса (nested loops) можно еще сразу подсчитать все агрегаты в промежуточную таблицу и сделать соединение наборов(merge/hash join)
Прежде, чем засовывать часть логики в функцию, убедитесь, что ваш запрос вообще оптимален
29 июл 09, 11:42    [7472805]     Ответить | Цитировать Сообщить модератору
 Re: Кеширование функции???  [new]
aleks2
Guest
vino
если так, то сделайте вьюшку типа такой
CREATE VIEW dbo.vSumRealForSertif AS
	SELECT SUM(AOT.r_sum_pred), AOT.N_SCHETA, AOT.d_pred_sch, AOT.N_SERTIF, AOT.dpl_n
	FROM OT07_DBF_MAIN.dbo.AOTSCHT AS AOT
	GROUP BY AOT.N_SCHETA, AOT.d_pred_sch, AOT.N_SERTIF, AOT.dpl_n


А ежели его еще и материализовать, то будет еще быстрее.

Тредстартеру: см. BOL Indexed View.
29 июл 09, 11:44    [7472816]     Ответить | Цитировать Сообщить модератору
 Re: Кеширование функции???  [new]
vino
Member

Откуда:
Сообщений: 1191
hosTuk
Затем это представление использовать в подзапросе?
Не совсем понял дальнейшее использование преставления в запросе
Выигрыш только за счет суммирования? если делать в той же функции
у вас вопрос начался с кеширования - это и есть кеширование вычислений сумм с помощью представления.
К моменту итогового запроса уже все будет вычислено, оставется только соединяться примерно так
SELECT T.SumRealForSert
FROM OT07_DBF_MAIN.dbo.AOTSCHP_WORK AS W
LEFT JOIN vSumRealForSert AS T
ON (W.N_SCHETA=T.N_SCHETA)AND(W.d_pred_sch=T.d_pred_sch)
AND((W.dpl_n=T.dpl_n) OR ((W.dpl_n IS NULL) AND (T.dpl_n IS NULL)))
GROUP BY W.n_scheta, W.d_pred_sch, W.dpl_n,W.n_sertif
ORDER BY W.n_scheta, W.d_pred_sch, W.dpl_n,W.n_sertif
где
CREATE VIEW dbo.vSumRealForSertif AS
	SELECT SUM(AOT.r_sum_pred) AS SumRealForSert, AOT.N_SCHETA, AOT.d_pred_sch, AOT.N_SERTIF, AOT.dpl_n
	FROM OT07_DBF_MAIN.dbo.AOTSCHT AS AOT
	GROUP BY AOT.N_SCHETA, AOT.d_pred_sch, AOT.N_SERTIF, AOT.dpl_n
29 июл 09, 11:44    [7472821]     Ответить | Цитировать Сообщить модератору
 Re: Кеширование функции???  [new]
hosTuk
Member

Откуда:
Сообщений: 455
Ок, всем ответившим спасибо за помощь.
Теперь знаю куда смотреть, почитаем.
29 июл 09, 11:49    [7472851]     Ответить | Цитировать Сообщить модератору
Все форумы / Microsoft SQL Server Ответить