Меню


Курсы СтимулСправочникПолезные материалы1С:Предприятие 8.2РазработчикамПрактикум

1С:Предприятие 8.2 /
Разработчикам /
Практикум

Оглавление

Практикум 8. Оптимизация процедуры проведения

Оптимизация процедуры проведения документа ОказаниеУслуги

Особенности использования ссылочных данных

Оптимизация документа ОказаниеУслуги

 

Оптимизация процедуры проведения документа ОказаниеУслуги

Теперь, когда вы уже достаточно хорошо знакомы с языком запросов, мы наконец-то можем приступить к одной из самых важных тем → к оптимизации документа ОказаниеУслуги, и, в частности, к полному изменению его обработчика событияОбработкаПроведения.

Зачем это нужно?

Во-первых, предположим, что руководство фирмы решило, наконец-то, завершить «эксперименты» по ручному вводу стоимости расходуемых материалов и перейти на автоматический расчет стоимости расходуемых материалов « по среднему ».

Во-вторых, в обработчике события ОбработкаПроведения мы используем обращение к реквизиту ВидНоменклатурысправочникаНоменклатура «через точку». Такое обращение может сильно замедлить скорость выполнения процедуры при больших объемах табличной части документа.

Поэтому, изменения, вносимые нами в документ ОказаниеУслуги, будут преследовать две цели:

Особенности использования ссылочных данных

Термином ссылочные данные мы будем обозначать данные, хранящиеся в базе данных, доступ к которым возможен при помощи объектов встроенного языка вида Ссылка:СправочникСсылка.<имя>, ДокументСсылка. <имя> и т.д.

Для того чтобы дальнейшее изложение было понятнее, построим объяснение на примере получения ссылки на вид номенклатуры при проведении документа ОказаниеУслуги.

Не все данные, хранящиеся в базе данных, являются ссылочными. Это связано с тем, что в модели данных 1С:Предприятие 8.1 существует деление на данные, представляющие объектные сущности (справочники, планы счетов , документы и т.д.), и данные, представляющие необъектные сущности ( регистры сведений , регистры накопления и т.д.).

С точки зрения системы некоторая совокупность объектных данных определяется не только значениями своих полей, но и самим фактом своего существования. Другими словами, удалив из базы некоторую совокупность объектных данных, мы не сможем вернуть систему в то же состояние, которое было до удаления. Даже если мы заново создадим ту же самую совокупность объектных данных с теми же самыми значениями полей, с точки зрения системы это будет ДРУГАЯ совокупность объектных данных. Каждую такую совокупность объектных данных, уникальную с точки зрения системы, называют объектом базы данных. Для того чтобы система могла отличать один объект базы данных от другого, каждый объект базы данных (совокупность объектных данных) имеет внутренний идентификатор. Различные объекты базы данных всегда будут иметь разные внутренние идентификаторы. Этот идентификатор хранится вместе с остальными данными объекта в специальном поле Ссылка.

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

Таким образом, поскольку мы можем однозначно указать на каждый объект базы данных, у нас появляется возможность хранить такой указатель в полях других таблиц базы данных, выбирать его в поле ввода, указывать в параметрах запроса при поиске по ссылке и т.д. Во всех этих случаях как раз и будет использоваться объект встроенного языка вида Ссылка. Фактически этот объект хранит только внутренний идентификатор, находящийся в поле Ссылка.

Например, если взять наш документ ОказаниеУслуги, то в поле, хранящем реквизит табличной части Номенклатура, на самом деле находится внутренний идентификатор, указывающий на элемент справочника Номенклатура.

База данных Ссылка Номер Ссылка Номенклатура Количество . ... .. 6 1 1 . .. .... .. . .. . .. Ссылка. 'Код Наименование . .. 11 Подключение йоды . .. У

Когда в обработчике события ОбработкаПроведения документа ОказаниеУслуги мы присваиваем значение реквизита Номенклатура табличной части какой-либо переменной, мы имеем дело с объектом ДокументОбъект.ОказаниеУслуги. Этот объект содержит в себе значения всех реквизитов документа и реквизитов его табличных частей. Поэтому обращение

Движение.Материал = ТекСтрокаПереченьНоменклатуры.Номенклатура;

приводит к тому, что мы просто читаем данные, хранящиеся в оперативной памяти:

ссылка на номенклатуру ссылка о ДокументОбъект. Оказание Услуги Т -4-4 -4-4—4 44 Ссылк ДоХумеН Номе Ба а даннь т Оказание У Ссылка О луги Н мснклаї гра О

Однако, когда мы обращаемся к виду номенклатуры как к реквизиту того элемента справочника, ссылка на который указана в табличной части документа

Если ТекСтрокаПереченьНоменклатуры.Номенклатура.ВидНоменклатурыО Перечисления.ВидыНоменклатуры.Материал Тогда

происходит следующее:

Безымянный: Ссылка на Вид номенклатуры ссылка о Оперативная память ДокументОбъект. ОказаниеУслуги ссылка на элемент справочника Номенклатура Кэш объектов Баз; данных Сщ авонн ик. Номенклатур а Ссылка Код Наименование О 11 Подключение воды

Поскольку в объекте ДокументОбъект.ОказаниеУслуги есть только ссылка на элемент справочника Номенклатура и больше никаких данных об этом элементе нет, система возьмет эту ссылку и обратится по ней в кэш объектов в надежде найти там данные того объекта, ссылка на который у нее есть. Если кэш объектов не будет иметь нужных данных, он обратится к базе данных с тем, чтобы прочитать все данные объекта, ссылкой на который он обладает. После того, как все данные, хранящиеся в реквизитах нужного элемента справочника и в реквизитах его табличных частей, будут считаны в кэш объектов, кэш объектов вернет запрашиваемую ссылку, хранящуюся в реквизите ВидНоменклатуры справочника Номенклатура.

Как несложно догадаться, подобное обращение к базе данных требует большего количества времени, нежели простое чтение из оперативной памяти. При интерактивном заполнении документа подобные задержки ничтожно малы, по сравнению со скоростью работы пользователя . Однако при выполнении большого количества расчетов (например, при проведении больших документов, содержащих несколько тысяч строк), разница во времени может быть довольно ощутимой.

Из всего выше сказанного можно сделать следующий вывод: если алгоритм проведения документа использует только те данные, которые присутствуют в реквизитах документа (и его табличных частей), вполне достаточно использовать конструктор движений документа (как это было у нас в случае с документом ПриходнаяНакладная). Если же в алгоритме проведения требуется анализировать дополнительные реквизиты объектов, ссылки на которые содержатся в документе, а также использовать результаты расчета итогов регистров, следует использовать запросы для более быстрой выборки данных из базы данных.

То же самое справедливо в отношении выполнения любых участков программы, критичных по производительности. Механизм запросов лучше «читает» информационную базу и может за один раз выбрать все необходимые данные, поэтому, например, в типовых решениях вы практически не увидите использования объекта СправочникВыборка.<имя>.

Оптимизация документа ОказаниеУслуги

1. Первое, что мы сделаем для оптимизации документа ОказаниеУслуги, - удалим реквизит табличной части Стоимость, который нам не понадобится в дальнейшем.

2. Также следует удалить соответствующую колонку из табличного поля, расположенного в форме.

3. После этого можно полностью удалить содержимое обработчика события ОбработкаПроведения в модуле документа и создать в нем заготовку процедуры проведения. Текст запроса, выполняемого в режиме оперативного проведения, будет отличаться от запроса, выполняемого при неоперативном проведении . Поэтому формирование текста запроса мы включим в условие Если …¦ Иначе …¦ КонецЕсли:

 Процедура ОбработкаПроведения Отказ, Режим Запрос = Новый Запрос; Если Режим = РежимПроведенияДокумента.Оперативный Тогда Запрос.Текст = ; Иначе Запрос.Текст = ; КонецЕсли; - КонецПроцедуры

4. Сначала составим запрос, который будет выполняться при оперативном проведении документа. Установим курсор перед точкой с запятой, из контекстного меню вызовем конструктор запроса,

Документ ОказаниеУслуги: Модуль объекта _ п 5 Процедура ОбработкаПроведения Отказ, Режим Запрос = Новый Запрос; Если Режим = РежимПроведенияДокумента.Оперативный Тогда Запрос.Текст = Иначе Запрос.Текст = КонецЕсли; Ко не цПр о цедуры 17/ і іикн и і щ Перех

на вопрос «Создать новый запрос?» согласимся, раскроем таблицу ПереченьНоменклатуры табличной части документа ОказаниеУслуги и выберем из нее поля:

Эти поля будут нужны нам для задания значений измерений регистров и их ресурсов. Кроме того, поле ВидНоменклатуры понадобится нам для анализа того, чем является номенклатура , указанная в документе: материалом или услугой.

ГШ Конструктор запроса _ П -.її- База данных [ 1;Д Справочники Й' 1 Документы ЁЬМ ПриходнаяНаклад В- г/ 0 казаниеУ слуги — Ссылка - ПометкаУдал - Номер - Дата - Проведен ЁЪ— Склад [+] — Клиент ЁЬ— Мастер ф=1=] - Представлени! - МоментВреме! Й [.Л Перечисле

5. Для указания значений ресурса Стоимость регистров СтоимостьМатериалов и Продажи нам понадобится рассчитать текущую стоимость номенклатуры как частное стоимости остатка этого материала и его оставшегося количества.

Поэтому добавим к списку выбранных таблиц еще две:

База данных / ч [+1-Д1 Справочники Ш Документы Перечисления В- РегистрыСведений РегистрыНакопления Й-! ОстаткиМатериалов Й-! ОстаткиМатериалов.Обороты И: дД 0 от ат к и М атериалов.Остат к и Й-! 0 статкиМ атериалов. 0 статкиИ 0 б ЁН СтоимостьМ атериалов Й-

6. Для этих виртуальных таблиц нам нужно будет задать одинаковые параметры. Они будут включать в себя момент времени, на который должны быть получены остатки этих регистров, и условие получения данных.

Условие получения данных указывает, что остатки должны быть получены только по тем позициям номенклатуры, которые содержатся в проводимом документе (перед выполнением запроса мы передадим в параметр СписокНоменклатурыДокумента список всех позиций номенклатуры, содержащихся в проводимом документе).

Параметры виртуальной таблицы Период Условие Шоменг Времени Материал В СписокНоменклатуры Документа . .. ок Отмена Справка

7. После того как будут заданы параметры обеих виртуальных таблиц регистров накопления, выберем из них поля СтоимостьОстаток и КоличествоОстаток:

Т аблицы Поля El lli 0 казаниеУ слугиП еречень 1.....- 0 казаниеУ слугиП еременьН оменклатуры. Н оменкл E-if 0 статкиМ атериаловО стаї і.....- 0 казаниеУ слугиП еременьН оменклатуры. Количеств EI— Материал 1.....- 0 казаниеУ слугиП еременьН оменклатуры. Н

8. Теперь вспомним о том, что документы ОказаниеУслуги могут быть проведены как в оперативном, так и в неоперативном режиме.

Поскольку в оперативном режиме нам понадобится контролировать остатки спмсываемой номенклатуры на складе, выберем еще раз виртуальную таблицу регистра накопленияОстаткиМатериаловОстатки и переименуем ее в ОстаткиМатериаловОстаткиНаСкладе.

Т аблицы В I1U 0 казаниеУ слугиП ереченьН оменклатуры 0! ! 0статкиМатериаловОстатки ф-і І4 S-i U СтоимостьМатериаловО статки О статкиМ атериаловО статкиН аСкладе

9. Для этой виртуальной таблицы мы также укажем параметр МоментВремени, а в условии напишем, что материал должен находиться в списке номенклатуры и склад должен быть равен складу, указанному в документе:

Параметры виртуальной таблицы Период Условие Шоменг Времени Материал В СписокНоменклатуры Документа И Склад = СкладВДокументе О К Отмена Справка

10. Теперь из этой виртуальной таблицы мы выберем поле КоличествоОстаток:

.....- 0 казаниеУ слугиП ереченьН оменклатуры. Н оменклатура . ....- 0 казаниеУ слугиП ереченьН оменклагуры. Количество . ....- 0 казаниеУ слугиП ереченьН оменклагуры. Н оменклатура. В иаН . ....- 0 казаниеУ слугиП ереченьН оменклагуры. Сумма . ....g 0 сга

11. На этом формирование списка выбранных полей закончено, и мы можем перейти к заданию условий связи между выбранными таблицами.

12. Каждую из виртуальных таблиц необходимо связать с таблицей документа таким образом, что для всех записей таблицы документа должны подбираться имеющиеся записи виртуальной таблицы, причем номенклатура в таблице документа должна быть равна материалу из виртуальной таблицы:

№ T аблица 1 Все Т аблица 2 Все 1 =1= 0 казаниеУ слугиП ереченьН оменклатуры у: Л4 СтоимостьМатериалоеОстатки 2 =1= 0 казаниеУ слугиП ереченьН оменклатуры 0 Л4 ОстаткиМатериалоеОстатки 3 =1= 0 казаниеУ слугиП ереченьН оменклатуры 0 }, ОстаткиМатериалоеОста

Выбранные таблицы

Условие связи - 0 казаниеУ слугиП ереченьН оменклагуры. Н оменклатура = I— СтоимостьМатериаловОстатки.Материал - 0 казаниеУ слугиП ереченьН оменклагуры. Н оменклатура = I— ОстаткиМатериаловОстатки.Материал - 0 казаниеУ слугиП ереченьН оменклагуры. Н оменкл

Условия связи между таблицами

13. Теперь перейдем на закладкуДополнительно и установим флаг Для изменения. Предложение ДЛЯ ИЗМЕНЕНИЯ позволяет заблаговременно заблокировать чтение указанных данных (которые могут читаться транзакцией другого соединения) уже при считывании, чтобы исключить взаимные блокировки при записи. Это предложение дает возможность указать в запросе те таблицы, считываемые данные которых предполагается изменить.

14. Поскольку мы планируем выполнить запись регистров накопления ОстаткиМатериалов, укажем таблицы этих регистров в качестве таблиц для изменения:

Таблицы и поля Связи Группировка Условия Дополнительно Объединения/Псевдонимы Порядок Итоги Построитель Без повторяющихся записей О Первые 0 Для изменения Поместить ОказаниеУслуги 1 С записей Разрешенные Т аблицы для изменения Л4 0статкиМатериалов.Остатки

15. Перейдем на закладку Условия и зададим условия отбора из таблицы документа только строк проводимого документа (ссылка на него будет передана в параметр запроса Ссылка):

гїй Конструктор запроса _ П Таблицы и поля Связи Группировка Условия Дополнительно Объединения/Псевдонимы Порядок Итоги Построитель = Поля В =11 ОказаниеУслугиПеречені Й~- С І.....— НомерСтроки Номер П... Условие Вп - 0 казаниеУ слугиП ереченьН оменклатуры

16. Перейдем на закладку Псевдонимы и зададим следующие псевдонимы полей:

17. Нажмем ОК и посмотрим, какой текст запроса сформировал конструктор:

5 Процедура ОбработкаПроведения Отказ, Режим Запрос = Новый Запрос; Если Режим = РежимПроведенияДокумента.Оперативный Тогда Запрос.Текст = ВЫБРАТЬ ОказаниеУслугиПереченьНоменклатуры.Номенклатура, ОказаниеУслугиПереченьНоменклатуры.Количество, ОказаниеУслуг

В этом запросе нет ничего сложного, за исключением, быть может, трех левых соединений с таблицей табличной части документа и использования ключевого предложения ДЛЯ ИЗМЕНЕНИЯ, значение которого было уже объяснено.

18. Текст запроса для случая неоперативного проведения документа будет практически таким же, за исключением того, что в нем будет отсутствовать третье левое соединение и, соответственно, поле КоличествоОстатокНаСкладе, т.к. проверку остатков в этом случае мы выполнять не будем:

Иначе Запрос.Текст = ВЫБРАТЬ ОказаниеУслугиПереченьНоменклатуры.Номенклатура, ОказаниеУслугиПереченьНоменклатуры.Количество, ОказаниеУслугиПереченьНоменклатуры.Номенклатура.ВидНоменклатуры КАК ВидНоменклатуры, ОказаниеУслугиПереченьНоменклатуры.Сумма, С то

Документ.ОкаваниеУслуги.ПереченьНоменклатуры КАК ОкаваниеУслугиПереченьНоменклатуры ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.СтоимостьНатериалов.Остатки МоментВремени, Материал В СписокНоменклатурыДокумента КАК С то имо с ть Нате р иало вОс татки ПО ОказаниеУслу

19. Теперь добавим в текст обработчика задание параметров запроса:

 РегистрНакопления.СтоимостьНатериалов.Остатки ; Запрос.УстановитьПараметр СкладВДокументе ,Склад ; Иначе Запрос.Текст = ВЫБРАТЬ РегистрНакопления.СтоимостьНатериалов.Остатки ; КонецЕсли; Запрос.УстановитьПараметр МоментВремени ,НоментВремени ; Запрос.Уста

Обратите внимание, что для формирования списка номенклатуры документа мы используем метод ВыгрузитьКолонку() объекта ДокументТабличнаяЧасть.Оказание Услуги.ПереченьНоменклатуры.

20. После этого добавим получение результата запроса и цикл его обхода:

Запрос.УстановитьПараметр Ссылка ,Ссылка ; ВыборкаРезультатаЗапроса = Запрос.Выполнить .Выбрать Пока ВыборкаРезультатаЗапроса.Следующий Цикл КонецЦикла; - КонецПроцедуры

21. Теперь, прежде чем начать формирование движений по регистрам , нам нужно проверить наличие на складе достаточного количества номенклатуры в цикле обхода результата запроса:

Пока ВыборкаРезультатаЗапроса.Следующий Цикл // Проверить остаток при оперативном проведении Если Режим = РежимПроведенияДокумента.Оперативный Тогда Если ВыборкаРезультатаЗапроса.ВидНоменклатуры = Перечисления.ВидыНоменклатуры.Материал Тогда Остаток = Выбо

22. И в заключение, после проверки остатков на складе, перед самым концом цикла, добавим формирование движений по регистрам накопления:

// Сформировать движения Если ВыборкаРезультатаЗапроса.ВидНоменклатуры = Перечисления.ВидыНоменклатуры.Материал Тогда //Регистр ОстаткиМатериалов Расход Движение = Движения.ОстаткиМатериалов.Добавить ; Движение.ВидДвижения = ВидДвиженияНакопления.Расход; Д

23. А сразу после цикла добавим запись движений регистров:

КонецЦикла; // Записать движения регистров Движения.ОстаткиМатериалов.Записать ; Движения.СтонкостьНатериалов.Записать Движения.Продажи.Записать ; 1- КонецПроцедуры

24. Запустим 1С:Предприятие в режиме отладки и проверим работу нового обработчика события ОбработкаПроведения, перепроведя все документы ОказаниеУслуги.


Нас находят: оптимизация процедуры проведения документов


Подписка на новости RSS     Добавьте в закладки Google fusion     Мы в Google+    

 

Мы ВКонтакте

 

Мы на Facebook