Статьи :
Оптимизация 1С :
Общий анализ
|
|
Пример оптимизации бухгалтерской конфигурации
Помимо собственно наблюдения за функционированием информационной системы предприятия, мониторинг является полезным инструментом для ее оптимизации. Так, в ходе анализа базы данных мониторинга одного из клиентов были выявлены повторяющиеся всплески загрузки процессора сервера до максимума одним и тем же пользователем на значительное время:
![]() На скриншоте, с лева, по графику нагрузки на процессор, хорошо виден всплеск нагрузки. С права показан списко пользователей, которые в это время работали в системе. Как видно из списка, всплеск нагрузки создавал пользователь Василенко_А, выполняя отчёт ОборотноСальдоваяВедомость. В квадратных скобках показан номер строки модуля конфигурации, который выполнялся в рассматриваемый момент. Строка 241 отчета соответствует коду:
Если Ит.ВыполнитьЗапрос(Дата1, Дата2, Счет) = 0 Тогда Первоначальное и очевидное предположение, что пользователь запускает ОСВ за большой период с разворачиванием по всем аналитикам оказалось неверным. В силу своих служебных обязанностей пользователь делает ОСВ по товарным остаткам с отбором по группе справочника номенклатуры. Рассмотрим, как реализуется 1С данный отчет и попробуем выяснить причину большой загрузки им сервера. Открыв форму трасс и наложив фильтр по времени и по данному пользователю мы видим последовательность действий 1С:
1) создание временной таблицы для хранения идентификаторов субконто и их типов
CREATE TABLE #SCID( CORR TINYINT,VSC INTEGER,SC CHAR(13), PRIMARY KEY( CORR, VSC, SC ) ) 2) заполнение ее аналитикой (товарами, подчиненными выбранной группе) DECLARE @SCID CHAR(13) IF EXISTS ( SELECT * FROM SC148 WHERE ID=' 3GX ' AND ISFOLDER=1 ) BEGIN INSERT INTO #SCID SELECT 0, CASE WHEN ISFOLDER=2 THEN 367 ELSE -367 END, ID FROM SC148 WHERE PARENTID=' 3GX ' WHILE 1=1 BEGIN SELECT @SCID=MAX(SC) FROM #SCID WHERE CORR=0 AND VSC=-367 IF @SCID IS NULL BREAK INSERT INTO #SCID SELECT 0, CASE WHEN ISFOLDER=2 THEN 367 ELSE -367 END, ID FROM SC148 WHERE PARENTID=SUBSTRING(@SCID, 1, 9) DELETE FROM #SCID WHERE CORR=0 AND VSC=-367 AND SC=@SCID END END ELSE INSERT #SCID VALUES( 0, 367, ' 3GX ' ) 3) Выполнение собственно запроса SELECT ACCID,CURRID,FLAGS=MAX(FLAGS),SC0,SC1,SC2,SUM_=SUM(SUM_),CURSUM=SUM(CURSUM),AMOUNT=SUM(AMOUNT) FROM ( SELECT ACCID,CURRID,FLAGS,SC0=CASE WHEN VSC0=338 THEN SC0 WHEN VSC1=338 THEN SC1 WHEN VSC2=338 THEN SC2 ELSE ' ' END ,SC1=CASE WHEN VSC0=367 THEN SC0 WHEN VSC1=367 THEN SC1 WHEN VSC2=367 THEN SC2 ELSE ' ' END ,SC2=CASE WHEN VSC0=368 THEN SC0 WHEN VSC1=368 THEN SC1 WHEN VSC2=368 THEN SC2 ELSE ' ' END ,SUM_=CASE KIND WHEN '1' THEN SD+(OBDT1-OBKT1)+(OBDT2-OBKT2) ELSE 0 END,CURSUM=CASE KIND WHEN '2' THEN SD+(OBDT1-OBKT1)+(OBDT2-OBKT2) ELSE 0 END,AMOUNT=CASE KIND WHEN '3' THEN SD+(OBDT1-OBKT1)+(OBDT2-OBKT2) ELSE 0 END FROM ( SELECT ID FROM _1SACCS(NOLOCK INDEX=CODE) WHERE PLANID=334 AND SCHKOD>='28.1.' AND substring(SCHKOD,1,5)='28.1.' AND (SC0 = 338 OR SC1 = 338 OR SC2 = 338) AND (SC0 = 367 OR SC1 = 367 OR SC2 = 367) AND (SC0 = 368 OR SC1 = 368 OR SC2 = 368) ) AS DT, #SCID DTSC1,_1SBKTTL BKTTL(NOLOCK) WHERE DATE='20081001' AND ACCID=DT.ID AND ( BKTTL.VSC0=338 OR BKTTL.VSC1=338 OR BKTTL.VSC2=338 ) AND ( DTSC1.CORR=0 AND DTSC1.VSC=367 AND ( BKTTL.VSC0=367 AND BKTTL.SC0=DTSC1.SC OR BKTTL.VSC1=367 AND BKTTL.SC1=DTSC1.SC OR BKTTL.VSC2=367 AND BKTTL.SC2=DTSC1.SC ) ) AND ( BKTTL.VSC0=368 OR BKTTL.VSC1=368 OR BKTTL.VSC2=368 ) AND (KIND = '1' OR KIND = '2' OR KIND = '3') ) AS SD GROUP BY ACCID,CURRID,SC0,SC1,SC2 HAVING SUM(SUM_)<>0 OR SUM(CURSUM)<>0 OR SUM(AMOUNT)<>0
Анализ плана показывает, что основное время сервер затратил на объединение остатков и временной таблицы. Попробуем избавиться от отбора по родителю справочника, написав для пользователя специализированный отчет, в котором используем следующий код: Ит=СоздатьОбъект("БухгалтерскиеИтоги"); Ит.ИспользоватьСубконто(ВидыСубконто.ТМЦ,,1); Ит.ИспользоватьСубконто(ВидыСубконто.МестаХранения, ВыбрСклад,2); Ит.ВыполнитьЗапрос(Дата1, Дата2, Счет.ПолучитьЗначение(сзСчета.ТекущаяСтрока()), , ,1,,"СК"); Ит.ВыбратьСубконто(); Пока Ит.ПолучитьСубконто()=1 Цикл Если Ит.Субконто().ПринадлежитГруппе(Группа)=1 Тогда //выводим в отчет Расшифровка.Установить("Субконто2", Ит.Субконто()); Табл.ВывестиСекцию("Строка"); НПП=НПП+1; КонецЕсли; КонецЦикла; Сравним время выполнения нового отчета на тех же исходных данных: - время снизилось в пять раз (с 460 секунд до 85); - уменьшилась загрузка сервера во время выполнения запроса. Эффект оптимизации основан на том, что для данного клиента оказалось быстрее получить все неотрицательные остатки и отфильтровать по условию на родительскую папку, чем выполнить объединение двух больших таблиц – остатков и отбора по родителю. И эффект оптимизации будет значительным в том случае, если в выбранной группе справочника у большой части элементов нет остатков или оборотов. |
| Copyright © 2004—2009 «СофтПоинт» |


