powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Delphi [игнор отключен] [закрыт для гостей] / Тонкости оптимизации для небольшой но очень часто используемой хранимой процедуры MSSQL
25 сообщений из 49, страница 1 из 2
Тонкости оптимизации для небольшой но очень часто используемой хранимой процедуры MSSQL
    #39632871
bilov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
У меня в проекте очень часто вызывается одна хранимая процедура. Все работает уже очень давно, но я решил сейчас её хоть как-нибудь оптимизировать по производительности. Эта процедура резервирования товара. Она прежде всего работает с двумя относительно не большими таблицами: Rezerved (7000записей)-резервы и несколько большей Ost(200000) записей. Записи в обоих таблицах очень часто меняются множеством пользователей одновременно в рамках транзакции на запись каждого документа. Она работает в 2-х режимах
1)В Rezerved больше чем в Ost. Нужно убрать резерв.
В этом случае делается курсор по некоторым записям Rezerved (которые для данного товара и для данного магазина)
Количество записей всегда >0, но практически в 99.999999% случаях очень мало, < 5. В среднем где-то 80% только 1 запись. Мы проходим по этому курсору и делаем UPDATE или DELETE записям ID которых нам дает этот курсор. Процедура работала уже лет 10 и все это время в ней был обычный курсор "cursor for" хотя от него было нужно только пройти по нему один раз в одном направлении (самое распространенное и элементарное использование) , только сегодня я поставил "cursor local fast_forward for". Надеюсь одно это уже должно улучшить ситуацию. И сейчас думаю как лучше дальше поступить? Сохранять запрос который сейчас идет в курсор в таблицу-переменную и создавать курсор только когда в ней больше чем одна запись, а если одна запись то делать все те же действия но без курсора? Прекрасно понимаю что курсор всегда вредит производительности, но будет ли выигрыш в данной ситуации? Создание таблицы-переменной специально для этого, это ведь мизер и не должно тут ухудшить производительность. Окончательный ответ может дать только непосредственная проверка, но с этим к сожалению не просто, ибо процедура эта работает вместе с множеством других сложных и довольно тормознутых операций и она меняет данные к тому же.
...
Рейтинг: 0 / 0
Тонкости оптимизации для небольшой но очень часто используемой хранимой процедуры MSSQL
    #39632872
bilov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Да забыл сказать. Использую Delphi 2010 и компоненты доступа к MSSQL - SDAC 6.11.23
...
Рейтинг: 0 / 0
Тонкости оптимизации для небольшой но очень часто используемой хранимой процедуры MSSQL
    #39632875
d7i
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Все состояния предмета (остаток,резерв,приход и т.д.) следует хранить в одной таблице.
Я сделал именно так и никаких проблем оптимизации по нескольким таблицам не возникает.
БД с указанной таблицей в составе системы торговли работает уже более 15 лет в сотнях мест...
...
Рейтинг: 0 / 0
Тонкости оптимизации для небольшой но очень часто используемой хранимой процедуры MSSQL
    #39632876
miksoft
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
bilovМы проходим по этому курсору и делаем UPDATE или DELETE записям ID которых нам дает этот курсор.Зачем делать медленный цикл? Почему не написать это одним запросом?
...
Рейтинг: 0 / 0
Тонкости оптимизации для небольшой но очень часто используемой хранимой процедуры MSSQL
    #39632933
DimaBr
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Обычно, количество товара определяется на любую дату как Ближайшая Инвентаризация + Приход (от Инвентаризации до нужной даты) - Расход (от инвентаризации до нужной даты).
Итого намечается ТРИ таблички, в которых не нужно ничего пересчитывать и удалять.
...
Рейтинг: 0 / 0
Тонкости оптимизации для небольшой но очень часто используемой хранимой процедуры MSSQL
    #39632941
bilov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Все это было определено за лет 7 до меня или ещё раньше. Ни времени, ни желания, ни полномочий то менять у меня нет.
...
Рейтинг: 0 / 0
Тонкости оптимизации для небольшой но очень часто используемой хранимой процедуры MSSQL
    #39632949
d7i
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
bilovВсе это было определено за лет 7 до меня или ещё раньше. Ни времени, ни желания, ни полномочий то менять у меня нет.
Структура БД неверная. Кто накосячил, пусть тот и исправляет.
Если нет полномочий менять структуру, тогда бесполезно возиться с оптимизацией.
Безногому костыли уже не помогут...
...
Рейтинг: 0 / 0
Тонкости оптимизации для небольшой но очень часто используемой хранимой процедуры MSSQL
    #39632951
bilov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
miksoft, Вы считаете что в моем случае курсор вида
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
		set @Delta =@K_Res-@K_Ost
		declare cursor1 cursor local fast_forward for 
		select RecID, Kol_vo from Rezerved  where C_Obj=@C_Obj and C_Tov=@C_Tov order by RecID DESC, D_Reg DESC, N_Reg DESC
		open cursor1
		declare @RecID int, @Kol_vo float, @Buf float
		fetch next from cursor1 into @RecID, @Kol_vo
		while (@@FETCH_STATUS = 0) and (@Delta>0)
		begin
		  set @Kol_vo = @Kol_vo-@Delta
		  if @Kol_vo>0.0005 --AI_DELTA
		  begin
			update Rezerved  set Kol_vo=@Kol_vo where RecID=@RecID
			set @Delta = 0
		  end
		  else begin
			delete from Rezerved  where RecID=@RecID
			set @Delta = -@Kol_vo
		  end
		  fetch next from cursor1 into @RecID, @Kol_vo
		end
		close cursor1 
		deallocate cursor1


возможно и имеет смысл (с учетом той статистики о которой я написал вначале) переделать как запрос? Как-то с использованием последних современных оконных функций типа
Код: sql
1.
SUM(Quantity) OVER (ORDER BY OrderId RANGE UNBOUNDED PRECEDING) 

?
...
Рейтинг: 0 / 0
Тонкости оптимизации для небольшой но очень часто используемой хранимой процедуры MSSQL
    #39632961
DimaBr
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Резервирование - это ЧЕТВЁРТАЯ табличка, которая появляется в цепочке
Количество на Дату = Ближайшая Инвентаризация + Приход - Расход - Резерв
И ничего пересчитывать не нужно
...
Рейтинг: 0 / 0
Тонкости оптимизации для небольшой но очень часто используемой хранимой процедуры MSSQL
    #39632968
L_argo
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Курсор вполне оптимальный, ИМХО.
По каким полям есть индексы и какие ?
Статистики обновляете ?

Как вариант - рассмотреть возможность вызывать процедуру как-нибудь реже или в отложенном режиме.

Таблица-переменная не поможет. Даже ухудшит ситуацию.

Структура БД неверная. Кто накосячил, пусть тот и исправляет.Отличный совет. Но дартаньянский...
...
Рейтинг: 0 / 0
Тонкости оптимизации для небольшой но очень часто используемой хранимой процедуры MSSQL
    #39632970
Дед-Папыхтет
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
bilov,

merge используй избавься от курсоров. А вообще текст скрипта таблиц с индексами, текст процедуры T-SQL и план запроса в студию
...
Рейтинг: 0 / 0
Тонкости оптимизации для небольшой но очень часто используемой хранимой процедуры MSSQL
    #39632972
Дед-Папыхтет
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
d7ibilovВсе это было определено за лет 7 до меня или ещё раньше. Ни времени, ни желания, ни полномочий то менять у меня нет.
Структура БД неверная. Кто накосячил, пусть тот и исправляет.
Если нет полномочий менять структуру, тогда бесполезно возиться с оптимизацией.
Безногому костыли уже не помогут...
Ога, все сломать и написать заново - так победим (с)
...
Рейтинг: 0 / 0
Тонкости оптимизации для небольшой но очень часто используемой хранимой процедуры MSSQL
    #39633105
bilov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
d7i, Я обязательно об этом заявлю после того как уволюсь и получу расчет.
...
Рейтинг: 0 / 0
Тонкости оптимизации для небольшой но очень часто используемой хранимой процедуры MSSQL
    #39633441
bilov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Дед-Папыхтет, Таблица резервов (меньшая из двух) у меня такая

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
/****** Object:  Table [dbo].[Reserved]    Script Date: 19.04.2018 22:06:21 ******/
SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

CREATE TABLE [dbo].[Reserved](
	[RecID] [int] IDENTITY(1,1) NOT NULL,
	[C_Obj] [smallint] NULL,
	[C_Tov] [int] NULL,
	[D_Reg] [datetime] NULL,
	[N_Reg] [smallint] NULL,
	[Kol_vo] [float] NULL,
 CONSTRAINT [PK_Reserved] PRIMARY KEY CLUSTERED 
(
	[RecID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]

GO

ALTER TABLE [dbo].[Reserved]  WITH CHECK ADD  CONSTRAINT [CK_Reserved] CHECK  (([Kol_vo]>=(0)))
GO

ALTER TABLE [dbo].[Reserved] CHECK CONSTRAINT [CK_Reserved]
GO

/****** Object:  Index [Ind_C_Tov_C_Obj]    Script Date: 19.04.2018 22:13:53 ******/
CREATE NONCLUSTERED INDEX [Ind_C_Tov_C_Obj] ON [dbo].[Reserveds]
(
	[C_Tov] ASC,
	[C_Obj] ASC
)
INCLUDE ( 	[D_Reg],
	[N_Reg],
	[Kol_vo],
	[RecID]) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
GO

/****** Object:  Index [Ind_D_Reg_N_Reg]    Script Date: 19.04.2018 22:15:50 ******/
CREATE NONCLUSTERED INDEX [Ind_D_Reg_N_Reg] ON [dbo].[Reserved]
(
	[D_Reg] ASC,
	[N_Reg] ASC
)
INCLUDE ( 	[RecID],
	[C_Obj],
	[C_Tov],
	[Kol_vo]) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
GO



Проблемы в ней видно сразу. По логике ни одно из полей не должно быть NULL никогда, а они имеют такую возможность. Наверное это тоже вредит чуть чуть. Надо будет на работе вопрос поднять.

Можно было бы и текст процедуры выложить, но он здоровый довольно, только логику вопроса затуманит. А курсор с которым сражаюсь я выкладывал, можно найти по "set @Delta =@K_Res-@K_Ost"
...
Рейтинг: 0 / 0
Тонкости оптимизации для небольшой но очень часто используемой хранимой процедуры MSSQL
    #39633507
Дед-Папыхтет
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
bilov,

А ты можешь словами сформировать задачу? В 1-2 абзаца
...
Рейтинг: 0 / 0
Тонкости оптимизации для небольшой но очень часто используемой хранимой процедуры MSSQL
    #39633509
Дед-Папыхтет
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Дед-Папыхтетbilov,

А ты можешь словами сформировать задачу? В 1-2 абзаца
Желательно сразу что бы было понятно что такое @K_Res, @K_Ost. Ну и Количество меньше дельта или больше дельта в коде виден апдейт делит, а вот смысл этого не ясен. Я к тому когда смысл понятен, можно эффективнее найти решение, а не подбивать существующий код
...
Рейтинг: 0 / 0
Тонкости оптимизации для небольшой но очень часто используемой хранимой процедуры MSSQL
    #39633535
энди
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Курсор сам по себе очень медленный функционал.
...
Рейтинг: 0 / 0
Тонкости оптимизации для небольшой но очень часто используемой хранимой процедуры MSSQL
    #39633540
L_argo
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
эндиКурсор сам по себе очень медленный функционал.Но иногда сильно выручает.
Н-р организовать привязку партий по ФИФО курсором выходит эффективнее, чем запросами. По моему опыту.
...
Рейтинг: 0 / 0
Тонкости оптимизации для небольшой но очень часто используемой хранимой процедуры MSSQL
    #39633567
Дед-Папыхтет
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
bilov,

и результат запроса плиз print @@version
...
Рейтинг: 0 / 0
Тонкости оптимизации для небольшой но очень часто используемой хранимой процедуры MSSQL
    #39633586
bilov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Дед-Папыхтет, Тут в этом всем хозяйстве смысл длиною в жизнь. Мня забанят сразу если я значительную часть этой портянки тут выложу. На данный момент решаю часть задачи связанную с этим курсором. Думаю поставить проверку типа такого
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
declare @RecID int,

Select top 1 @RecID = RecID, @Kol_vo = Kol_vo from Rezerved  where C_Obj=@C_Obj and C_Tov=@C_Tov order by RecID DESC

if @RecID =
( select top 1 RecID from Rezerved  where C_Obj=@C_Obj and C_Tov=@C_Tov order by RecID asc) 
begin
  --работаем без курсора
end
else
begin

  declare cursor1 cursor local fast_forward for 
  select RecID, Kol_vo from Rezerved  where C_Obj=@C_Obj and C_Tov=@C_Tov order by RecID DESC
  --тоже самое но с курсором
end


может что-то другое, более щадящее поставить?
например так
Код: sql
1.
2.
3.
DECLARE @tbD TABLE (RecID int, Kol_vo float)
insert @tbD(RecID , Kol_vo )
Select RecID, Kol_vo from Rezerved where C_Obj=@C_Obj and C_Tov=@C_Tov


, а потом к @tbD обращаться, но тут говорят многие что таблица-переменная это плохо. И вообще имеет ли смысл это делать учитывая
" Rezerved (7000записей)." И для данного курсора справедливо "Количество записей всегда >0, но практически в 99.999999% случаях очень мало, < 5. В среднем где-то 80% только 1 запись. Мы проходим по этому курсору и делаем UPDATE или DELETE записям ID которых нам дает этот курсор"
...
Рейтинг: 0 / 0
Тонкости оптимизации для небольшой но очень часто используемой хранимой процедуры MSSQL
    #39633588
bilov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Дед-Папыхтет, print @@version
Microsoft SQL Server 2012 - 11.0.2100.60 (X64)
Feb 10 2012 19:39:15
Copyright (c) Microsoft Corporation
Developer Edition (64-bit) on Windows NT 6.2 <X64> (Build 9200: ) (Hypervisor)
...
Рейтинг: 0 / 0
Тонкости оптимизации для небольшой но очень часто используемой хранимой процедуры MSSQL
    #39633615
goldmi45
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
У меня одного возник вопрос "а Delphi тут при чём"?
Кроме этого bilovИспользую Delphi 2010 и компоненты доступа к MSSQL - SDAC 6.11.23 нет ничего, относящегося к этому разделу форума. Может, лучше перенести в раздел по MSSQL?
...
Рейтинг: 0 / 0
Тонкости оптимизации для небольшой но очень часто используемой хранимой процедуры MSSQL
    #39633625
L_argo
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
goldmi45У меня одного возник вопрос "а Delphi тут при чём"?
Кроме этого bilovИспользую Delphi 2010 и компоненты доступа к MSSQL - SDAC 6.11.23 нет ничего, относящегося к этому разделу форума. Может, лучше перенести в раздел по MSSQL?пожалуй +1
...
Рейтинг: 0 / 0
Тонкости оптимизации для небольшой но очень часто используемой хранимой процедуры MSSQL
    #39633699
Дед-Папыхтет
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
bilov,

Я попытался воспроизвести
на случайных данных
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
/*
truncate table Reserved;
with cte (i) as
(
	select 1 union all
	select i+1 from cte
)
insert Reserved
select top(30)
	abs(convert(int,convert(binary(4),newid())))%10 as C_Obj,
	abs(convert(int,convert(binary(4),newid())))%50 as C_Tov,
	dateadd(second,-abs(convert(int,convert(binary(4),newid())))%1000,'20170101') as D_Reg,
	abs(convert(int,convert(binary(4),newid())))%50 as N_Reg,
	convert(money,(abs(convert(int,convert(binary(4),newid())))%10000))/100 as Kol_vo
from cte
option(maxrecursion 0)
*/
declare @C_Obj int=1,@C_Tov int=1
select top(1) @C_Obj = C_Obj, @C_Tov = C_Tov
from Reserved
order by count(*) over (partition by C_Obj, C_Tov) desc

declare @Delta money=0.1
declare cursor1 cursor local fast_forward for 
select RecID, Kol_vo from Reserved  where C_Obj=@C_Obj and C_Tov=@C_Tov order by RecID DESC, D_Reg DESC, N_Reg DESC
open cursor1
declare @RecID int, @Kol_vo money, @Buf money
fetch next from cursor1 into @RecID, @Kol_vo
while (@@FETCH_STATUS = 0) and (@Delta>0)
begin
	set @Kol_vo = @Kol_vo-@Delta
	if @Kol_vo>0.0005 --AI_DELTA
	begin
		update Reserved 
		set Kol_vo=@Kol_vo
		output 'upd' oper, inserted.*, deleted.*
		where RecID=@RecID
		
		set @Delta = 0
	end
	else begin
		delete from Reserved 
		output 'del' oper, deleted.*
		where RecID=@RecID
		
		set @Delta = -@Kol_vo
	end
	fetch next from cursor1 into @RecID, @Kol_vo
end
close cursor1 
deallocate cursor1


у меня чота сколько не пробовал выходит на апдейт списывает дельту и дельта обнуляется цикл заканчивается. Я в упор не понимаю пока что ты хочешь сделать в итоге. Или данные приведи какие то инсерт в таблицу в этот скрипт дополни что бы разные вариации изменений удалений были. Или как то поясни что делать то должен этот курсор?

PS: а зачем в сортировке - order by RecID DESC, D_Reg DESC, N_Reg DESC указаны D_Reg, N_Reg? у тебя сортировка стоит изначально по уникальному RecID, внутри уникальных строк сортировки не будет никакой - это на работу не влияет, но настораживает смысл этого кода.
...
Рейтинг: 0 / 0
Тонкости оптимизации для небольшой но очень часто используемой хранимой процедуры MSSQL
    #39633750
DimaBr
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Как можно оптимизировать кусок кода, если МЫ не понимаем что он делает ???
Объясняй смысл кода !!!
...
Рейтинг: 0 / 0
25 сообщений из 49, страница 1 из 2
Форумы / Delphi [игнор отключен] [закрыт для гостей] / Тонкости оптимизации для небольшой но очень часто используемой хранимой процедуры MSSQL
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]