AXForum  
Вернуться   AXForum > Microsoft Dynamics NAV > NAV: Программирование
All
Забыли пароль?
Зарегистрироваться Правила Справка Пользователи Сообщения за день Поиск Все разделы прочитаны

 
 
Опции темы Поиск в этой теме Опции просмотра
Старый 16.10.2008, 09:27   #1  
Nataly_imported is offline
Nataly_imported
Участник
 
13 / 10 (1) +
Регистрация: 27.07.2005
Есть ли какие-то тонкости работы с темп-таблицами в плане быстродействия?

У меня довольно простой код выполняется достаточно долго, как мне кажется. Вот такая вот у меня процедурка (привожу полностью как есть, может кому что бросится в глаза):

UpdateAvailableCapacity(VAR CurrCapacityRec : TEMPORARY Record "Availability Buffer")

CurrCapacityRec."Available Quantity":=
(CurrCapacityRec."Ending Date"-CurrCapacityRec."Starting Date")*24
+(CurrCapacityRec."Ending Time"-CurrCapacityRec."Starting Time")/3600000;

LocBegin:=CREATEDATETIME(CurrCapacityRec."Starting Date",CurrCapacityRec."Starting Time");
LocEnd:=CREATEDATETIME(CurrCapacityRec."Ending Date",CurrCapacityRec."Ending Time");

TmpTimeBreakeCapacity.RESET;
TmpTimeBreakeCapacity.SETCURRENTKEY("Starting Date","Starting Time","Ending Date","Ending Time");
TmpTimeBreakeCapacity.SETFILTER("Starting Date",'<=%1',CurrCapacityRec."Ending Date");
TmpTimeBreakeCapacity.SETFILTER("Ending Date",'>=%1',CurrCapacityRec."Starting Date");
TmpTimeBreakeCapacity.SETRANGE("Line No.",CurrCapacityRec."Entry No.");
IF TmpTimeBreakeCapacity.FIND('-') THEN
REPEAT
BreakBegin:=CREATEDATETIME(TmpTimeBreakeCapacity."Starting Date",TmpTimeBreakeCapacity."Starting Time");
BreakEnd:=CREATEDATETIME(TmpTimeBreakeCapacity."Ending Date",TmpTimeBreakeCapacity."Ending Time");

IF (BreakBegin<=LocBegin) AND (BreakEnd>=LocEnd) THEN BEGIN
CurrCapacityRec."Available Quantity":=0;
EXIT;

END ELSE IF (BreakBegin<=LocBegin) AND (BreakEnd<=LocEnd) AND (BreakEnd>LocBegin) THEN
CurrCapacityRec."Available Quantity":=CurrCapacityRec."Available Quantity"-(BreakEnd-LocBegin)/3600000

ELSE IF (BreakBegin>LocBegin) AND (BreakEnd<=LocEnd) THEN
CurrCapacityRec."Available Quantity":=CurrCapacityRec."Available Quantity"-TmpTimeBreakeCapacity."Available Quantity"

ELSE IF (BreakBegin>LocBegin) AND (BreakBegin<LocEnd) AND (BreakEnd>=LocEnd) THEN
CurrCapacityRec."Available Quantity":=CurrCapacityRec."Available Quantity"-(LocEnd-BreakBegin)/3600000;

UNTIL TmpTimeBreakeCapacity.NEXT=0;


CurrCapacityRec и TmpTimeBreakeCapacity являются темп-таблицами.

Работает такая процедура примерно 0,036 секунды. Цикл по TmpTimeBreakeCapacity проходит около 3-6 записей.
Комп вполне работоспособный (процессор Pentium 1,73 GHz, 795 МГц, 1Гб ОЗУ)
Старый 16.10.2008, 09:55   #2  
romeo is offline
romeo
Участник
Аватар для romeo
 
564 / 10 (2) +
Регистрация: 31.03.2004
Удивлен, что пост от девочки (простите за "девочку" уважаемая, но у меня все, кто не мальчик - девочки).
Это из-за конструктива.
По теме - ну не знаю, почему код выполняется настолько долго.

Не по теме. Более читабельно в коде смотрится конструкция CASE нежели IF .. ELSE IF .. ELSE IF.
Поясню.

Код:
CASE TRUE OF
  (BreakBegin<=LocBegin) AND (BreakEnd>=LocEnd) : BEGIN
	...
  END;
  (BreakBegin<=LocBegin) AND (BreakEnd<=LocEnd) AND (BreakEnd>LocBegin) : BEGIN
	...
  END;
END;
Старый 16.10.2008, 10:00   #3  
romeo is offline
romeo
Участник
Аватар для romeo
 
564 / 10 (2) +
Регистрация: 31.03.2004
Цитата:
Сообщение от romeo Посмотреть сообщение
Удивлен, что пост от девочки (простите за "девочку" уважаемая, но у меня все, кто не мальчик - девочки).
Это из-за конструктива.
По теме - ну не знаю, почему код выполняется настолько долго.

Не по теме. Более читабельно в коде смотрится конструкция CASE нежели IF .. ELSE IF .. ELSE IF.
Поясню.

Код:
CASE TRUE OF
  (BreakBegin<=LocBegin) AND (BreakEnd>=LocEnd) : BEGIN
	...
  END;
  (BreakBegin<=LocBegin) AND (BreakEnd<=LocEnd) AND (BreakEnd>LocBegin) : BEGIN
	...
  END;
END;
Вообще же скорость работы с темп-таблицами определяется размером ОЗУ, потому что работа с ними производится на клиенте. Еще наша ранее проведенная статистика показала, что как только кол-во записей в темп-таблице перебирает за 10000, работа с ней замедляется в разы. Размерность темп-таблицы имеет значение..

To All.
Простите меня за два поста. Я кнопку не ту нажал. Это как в анеке про блондинку - печатаю быстро, но иногда такая фигня получается -)
Старый 16.10.2008, 10:50   #4  
Nataly_imported is offline
Nataly_imported
Участник
 
13 / 10 (1) +
Регистрация: 27.07.2005
На счет конструкции Case - да, действительно читабильнее. Это у меня исторически сложилось, IF-ами писать, уж и не знаю почему.

По поводу критического значения в 10000 записей - спасибо, такая инфа тоже пригодится, но в данном случае кол-во записей на порядки меньше.

P.S. Забавно, что девушки-программисты все еще кого-то удивляют
Старый 16.10.2008, 11:35   #5  
artkashin is offline
artkashin
Участник
MCBMSS
 
519 / 18 (2) ++
Регистрация: 06.12.2006
Цитата:
Сообщение от Nataly Посмотреть сообщение
Код:
TmpTimeBreakeCapacity.RESET;
TmpTimeBreakeCapacity.SETCURRENTKEY("Starting Date","Starting Time","Ending Date","Ending Time");
TmpTimeBreakeCapacity.SETFILTER("Starting Date",'<=%1',CurrCapacityRec."Ending Date");
TmpTimeBreakeCapacity.SETFILTER("Ending Date",'>=%1',CurrCapacityRec."Starting Date");
TmpTimeBreakeCapacity.SETRANGE("Line No.",CurrCapacityRec."Entry No.");
IF TmpTimeBreakeCapacity.FIND('-') THEN
Меня смущает выбранный вами принудительный ключ. Он явно вам не подходит, так как вы фильтруете по полю "Line No." которого в ключе нет. Не знаю, как Nav работает с временными таблицами у себя в памяти, но с реальной таблицей такая оптимизация обошлась бы дорого.
Старый 16.10.2008, 14:41   #6  
Nataly_imported is offline
Nataly_imported
Участник
 
13 / 10 (1) +
Регистрация: 27.07.2005
Цитата:
Сообщение от Kashin Посмотреть сообщение
Меня смущает выбранный вами принудительный ключ. Он явно вам не подходит, так как вы фильтруете по полю "Line No." которого в ключе нет. Не знаю, как Nav работает с временными таблицами у себя в памяти, но с реальной таблицей такая оптимизация обошлась бы дорого.
Вообще я полагала, что при работе с темповскими таблицами действуют другие правила и выбор ключа не влияет на производительность. Но вот сейчас попробовала заменить ключ и время сократилось в 2 раза! Одного запуска конечно мало для выводов, сейчас еще буду тестить, но в любом случае спасибо!
Старый 16.10.2008, 15:53   #7  
RedFox is offline
RedFox
Участник
 
1,441 / 10 (0) +
Регистрация: 28.12.2004
Адрес: Киев
Цитата:
Сообщение от Nataly Посмотреть сообщение
Есть ли какие-то тонкости работы с темп-таблицами в плане быстродействия?
.....
Комп вполне работоспособный (процессор Pentium 1,73 GHz, 795 МГц, 1Гб ОЗУ)
Просто уточнение - версия БД какая?
Старый 16.10.2008, 21:31   #8  
alexb_imported is offline
alexb_imported
Участник
 
256 / 12 (1) ++
Регистрация: 25.08.2006
1. CASE, мо-моему, не только читабельнее, но и чуть-чуть быстрее чем IF..ELSE..IF
2. SETRANGE, по-моему, тоже быстрее чем SETFILTER, поэтому конкретно в этом случае можно обе даты фильтровать не
с SETFILTER
Код:
TmpTimeBreakeCapacity.SETFILTER("Starting Date",'<=%1',CurrCapacityRec."Ending Date");
TmpTimeBreakeCapacity.SETFILTER("Ending Date",'>=%1',CurrCapacityRec."Starting Date");
а с SETRANGE
Код:
TmpTimeBreakeCapacity.SETRANGE("Starting Date",0D,CurrCapacityRec."Ending Date");
TmpTimeBreakeCapacity.SETRANGE("Ending Date",CurrCapacityRec."Starting Date", 2999D);
3. Если позволяет версия Navision и база данных на SQL, то вместо FIND('-'), FIND('+') использоватъ FINDFIRST, FINDLAST
Если есть вероятность, что не всегда имеется отфильтрованная запись в TmpTimeBreakeCapacity, то можно перед FIND'ом
это проверить через ISEMPTY, т.к. лишний (и не нашедший запись) FIND стоит по времени дороже:
Код:
	..............
	TmpTimeBreakeCapacity.SETRANGE("Starting Date",0D,CurrCapacityRec."Ending Date");
	TmpTimeBreakeCapacity.SETRANGE("Ending Date",CurrCapacityRec."Starting Date", 2999D);
	TmpTimeBreakeCapacity.SETRANGE("Line No.",CurrCapacityRec."Entry No.");
	IF TmpTimeBreakeCapacity.ISEMPTY THEN EXIT
	ELSE TmpTimeBreakeCapacity.FINDFIRST;
	REPEAT
	...
	UNTIL TmpTimeBreakeCapacity.NEXT = 0;
Старый 16.10.2008, 22:20   #9  
anatol33 is offline
anatol33
Участник
 
109 / 10 (1) +
Регистрация: 02.09.2008
3. Если позволяет версия Navision и база данных на SQL, то вместо FIND('-'), FIND('+') использоватъ FINDFIRST, FINDLAST
Если есть вероятность, что не всегда имеется отфильтрованная запись в TmpTimeBreakeCapacity, то можно перед FIND'ом
это проверить через ISEMPTY, т.к. лишний (и не нашедший запись) FIND стоит по времени дороже:

уважаемый AlexB в данном примере помоему Вы не правы.

приведу выдержку хелпа по FINDFIRST
Comment
This function should be used instead of FIND('-') when you only need the first record.
You should only use this function when you explicitly want to find the first record in a table/set. Do not use this function in combination with REPEAT .. UNTIL.
Старый 17.10.2008, 08:17   #10  
Nataly_imported is offline
Nataly_imported
Участник
 
13 / 10 (1) +
Регистрация: 27.07.2005
Цитата:
Сообщение от RedFox Посмотреть сообщение
Просто уточнение - версия БД какая?
Вообще пишу под 4.0 SP3, но возможно код будет использовано и под другими версиями (как ниже, так и выше). БД под SQL Server.

Цитата:
Сообщение от AlexB
1. CASE, мо-моему, не только читабельнее, но и чуть-чуть быстрее чем IF..ELSE..IF
2. SETRANGE, по-моему, тоже быстрее чем SETFILTER, поэтому конкретно в этом случае можно обе даты фильтровать не
с SETFILTER
По поводу SETFILTER и SETFILTER действительно просмотрела... а что CASE быстрее работает не знала. Спасибо!

Относительно FINDFIRST, FINDLAST и т.д. Не хотелось их использовать, чтобы безболезненно код переносить под другие версии.

А вообще, разве все это имеет значение для темп-таблиц? Для реальных-то понятно, что быстрее, там запрос на сервер отправляется, а тут же локально все.

Цитата:
Сообщение от anatol33
приведу выдержку хелпа по FINDFIRST
Comment
This function should be used instead of FIND('-') when you only need the first record.
You should only use this function when you explicitly want to find the first record in a table/set. Do not use this function in combination with REPEAT .. UNTIL.
Спасибо за уточнение.


Кстати, я основательно затестила, использование наиболее подходящих ключей очень помогло, скорость существенно улучшилась, спасибо!
Старый 17.10.2008, 10:10   #11  
alexb_imported is offline
alexb_imported
Участник
 
256 / 12 (1) ++
Регистрация: 25.08.2006
За FINDFIRST/FINDLAST извиняюсь, в REPEAT..UNTIL надо конечно использовать FINDSET.
Т.к. код выполняется в различных NAV-версиях, то и в данном конкретном случае FIND('-') придётся оставить.

Кстати, может не совсем в тему топика:
почему и в новых версиях NAV'а (5.0 SP1) в коде стандарта ещё во многих местах в REPEAT..UNTIL используется FIND('-')?
Старый 17.10.2008, 11:05   #12  
RedFox is offline
RedFox
Участник
 
1,441 / 10 (0) +
Регистрация: 28.12.2004
Адрес: Киев
Цитата:
Сообщение от Nataly Посмотреть сообщение
Вообще пишу под 4.0 SP3, но возможно код будет использовано и под другими версиями (как ниже, так и выше). БД под SQL Server.
Если Вы не используете хинтов, то для SQL 2005 всё равно какой ключик. Если план есть, то он будет использовать его, иначе полный скан по БД.

P.S. Кстати, можете глянуть в Clent Monitor что твориться под SQL
Старый 17.10.2008, 14:37   #13  
Control is offline
Control
Участник
Аватар для Control
 
15 / 11 (1) +
Регистрация: 29.01.2008
Цитата:
Сообщение от anatol33 Посмотреть сообщение
приведу выдержку хелпа по FINDFIRST
Comment
This function should be used instead of FIND('-') when you only need the first record.
You should only use this function when you explicitly want to find the first record in a table/set. Do not use this function in combination with REPEAT .. UNTIL.
Офигеть, они хелп пятёрочный подправили. В 4-рке последнего предложения нет, Спасибо.
Старый 20.10.2008, 08:48   #14  
Nataly_imported is offline
Nataly_imported
Участник
 
13 / 10 (1) +
Регистрация: 27.07.2005
Цитата:
Сообщение от RedFox Посмотреть сообщение
Если Вы не используете хинтов, то для SQL 2005 всё равно какой ключик. Если план есть, то он будет использовать его, иначе полный скан по БД.

P.S. Кстати, можете глянуть в Clent Monitor что твориться под SQL
А вы точно про темп-таблицы пишите?
По крайней мере Clent Monitor видит только запросы к базе, работу с темп-таблицами он не отражает.
Старый 06.11.2008, 16:25   #15  
RedFox is offline
RedFox
Участник
 
1,441 / 10 (0) +
Регистрация: 28.12.2004
Адрес: Киев
Цитата:
Сообщение от Nataly Посмотреть сообщение
А вы точно про темп-таблицы пишите?
По крайней мере Clent Monitor видит только запросы к базе, работу с темп-таблицами он не отражает.
"Работает такая процедура примерно 0,036 секунды. " - Это с с заполнением этой временной таблицы в памяти или ТОЛЬКО сравнение?
Далее все эти таблицы хранятся в памяти и если её не достаточно, то будет происходить сброс на винт и восстановление.
А так как куча фильтров ставится, то я не уверен, что всё хранится в памяти!
Старый 06.11.2008, 17:39   #16  
rmv is offline
rmv
Участник
 
481 / 11 (1) +
Регистрация: 15.02.2005
Цитата:
Сообщение от RedFox Посмотреть сообщение
"Работает такая процедура примерно 0,036 секунды. " - Это с с заполнением этой временной таблицы в памяти или ТОЛЬКО сравнение?
Далее все эти таблицы хранятся в памяти и если её не достаточно, то будет происходить сброс на винт и восстановление.
А так как куча фильтров ставится, то я не уверен, что всё хранится в памяти!
Ну в крайнем случае сбросит в своп файл Винды, что то я не слышал чтобы монитор клиента отражал запросы к своп файлу .
По теме: Есть видимо некий порог, когда производительнее использовать возможности SQL сервера,
нежели работать с черным ящиком, именуемым временные таблицы. Предполагаю используется тот же самый
механизм что и для работы с native DB.
Старый 07.11.2008, 13:14   #17  
Nataly_imported is offline
Nataly_imported
Участник
 
13 / 10 (1) +
Регистрация: 27.07.2005
Цитата:
Сообщение от RedFox Посмотреть сообщение
"Работает такая процедура примерно 0,036 секунды. " - Это с с заполнением этой временной таблицы в памяти или ТОЛЬКО сравнение?
0,036 секунды - выполняется ровно то, что написано в приведенном коде, т.е. заполнение таблиц происходит до начала выполнения процедуры.

А вы хотите сказать, что торможение вызвано работой с винтиком, да? Это по крайней мере понятно будет.

Цитата:
Сообщение от rmv
По теме: Есть видимо некий порог, когда производительнее использовать возможности SQL сервера,
нежели работать с черным ящиком, именуемым временные таблицы. Предполагаю используется тот же самый
механизм что и для работы с native DB.
С реальными таблицами здесь очень не удобно будет работать (как минимум придется новые объекты под это занимать + обработка многопользовательской работы + сразу возникнет проблема блокировок), да и вряд ли быстрее, чем с темповскими.
 

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск
Опции просмотра

Ваши права в разделе
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.
Быстрый переход

Рейтинг@Mail.ru
Часовой пояс GMT +3, время: 13:10.