Разгон РАУЗ в 1С УПП 1.3 (платформа 8.2)

07.10.14

Задачи пользователя - Закрытие периода

В статье рассматривается вопрос повышения быстродействия расчета себестоимости в конфигурации 1С УПП 1.3 при включенном режиме РАУЗ и наличии большого количества материальных затрат. Глубокого погружения в теорию тут ждать не стоит, для этого есть другие хорошо написанные книги и статьи. Тут будет рассмотрен метод "по быстрому".

Итак, есть УПП версии 1.3, включенный РАУЗ и печальный факт того, что расчет себестоимости выполняется от двух часов и более. Ну и "бешенные" пользователи, которые "для проверки" запускают расчет себестоимости в конце/начеле месяца более чем часто.

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

Итак, не погружаясь особо в дебри теории, просто примем за аксиому, что последовательность измерений независимого (без регистратора) регистра сведений влияет на то, как в конечном счете будут построены индексы SQL. При включенном РАУЗ и большом количестве материальных затрат используется регистр сведений "АналитикаУчетаПартий". Измерения "из коробки" выглядят следующим образом:

 Типовая последовательность измерений РС АналитикаУчетаПартий

Если посмотреть в базу УПП и проанализировать содержимое регистра (это для моего конкретного случая, у кого-то может быть другая картина заполнения), то видно, что 80% содержания регистра занимают вот такие вот записи:

Содержимое регистра партий

 Т.е. статусы партий, заказы, договоры коминтента и т.д. не используются. Т.о. индексы которые создаются как самое 1С, так и SQL сервером в данном случае бестолковые, т.к. тратят процессорное время на то, что бы делать выборку по не заполненным полям. Поэтому, в моем случае последовательность измерений пыла переделана следующим образом:

 новая последовательность измерений

 

Ну и дополнительно по измерению "ФизЛицо" необходимо включить индексирование.  Собственно, вышеописанные действия по анализу содержимого регистров и перемещению измерений можно применить к регистрам сведений "АналитикаУчетаЗатрат" и "АналитикаВидаУчета". Единственное, что стоит помнить, это то что в регистре не стоит ставить галку "индексировать" более чем у 5 измерений (почему так - тоже лучше читать в специальных умных книжках).

Вышеописанные простые действия позволили ускорить расчет себестоимости выпуска на 20 минут. Это конечно хорошо, но, мало. Поэтому, следующим этапом будет небольшая оптимизация кода. Большая часть работы РАУЗ сосредоточена в общем модуле "РасширеннаяАналитикаУчета". Изучение работы документа "Расчет себестоимости" с включенным замером производительности показал, что очень большим тормозом (из-за большого количества вызовов) является функция "ЗаполненыНастройкиАналитикиУчета". Смотрим на содержимое функции:

Функция ЗаполненыНастройкиАналитикиУчета() 
	
	ТекстЗапроса = "
	|ВЫБРАТЬ ПЕРВЫЕ 1
	|	НастройкиАналитикиУчета.Код
	|ИЗ
	|	Справочник.НастройкиАналитикиУчета КАК НастройкиАналитикиУчета
	|ГДЕ
	|	НастройкиАналитикиУчета.УправленческийУчет
	|	ИЛИ НастройкиАналитикиУчета.РегламентированныйУчет
	|
	|";
	Запрос = Новый Запрос;
	Запрос.Текст = ТекстЗапроса;
	РезультатЗапроса = Запрос.Выполнить();
	
	Возврат (Не РезультатЗапроса.Пустой());
	
КонецФУнкции // ЗаполненыНастройкиАналитикиУчета()

Что тут видим. у нас более 300 тыс. раз вызывается простеньких запрос к СУБД с простой выборкой. Всё это хорошо, но, это время. Нужно что-то делать. А делать мы будем повторное использование возвращаемых значений. Так же, не останавливаюсь подробно на том - что это и зачем. Можно почитать в умных книжках. Сейчас просто делаем новый общий модуль, для которого устанавливаем следуюющие свойства:

 Свойстви общего модуля

и переносим в этот модуль вышеописанную функцию (просто копипастим не забыв добавить в конец объявления процедуры директиву "экспорт"), а в типовом модуле расширенной аналитики учета делаем следующее:

Функция ЗаполненыНастройкиАналитикиУчета()
	
	Возврат РасширеннаяАналитикаУчетаПовторноеИспользование.ЗаполненыНастройкиАналитикиУчета();
	
КонецФУнкции // ЗаполненыНастройкиАналитикиУчета()

Что нам это даст? А даст очень простую вещь - обращение к СУБД будет произведено только один раз. Все остальные обращения к функции "ЗаполненыНастройкиАналитикиУчета" будут приводить к тому, что возвращаемое значение будет получаться не путем обращения к SQL базе, а из кэша сервера 1С Предприятие. Дальнейшее изучение расчета седестоимости выявило то, что повторно использовать значения можно еще для двух функций "ШаблонИзмеренийКлючаАналитики" и "ПолучитьСоздатьКлючАналитики".

Вынос указанных выше функций в повторное использование вкупе с небольшой оптимизацией регистров (суть оптимизации так же описал выше) привело к тому, что расчет себестоимости при включеном РАУЗ стал занимать не 2 часа, а 5-7 минут.

Доп. информация: оптимизировал работу на УПП 1.3.49.2.

 


 

Созданный модуль "РасширеннаяАналитикаУчетаПовторноеИспользование" имеет следующие функции (настройки модуля на картинке выше):

 

Функция ЗаполненыНастройкиАналитикиУчета() экспорт
	
	ТекстЗапроса = "
	|ВЫБРАТЬ ПЕРВЫЕ 1
	|	НастройкиАналитикиУчета.Код
	|ИЗ
	|	Справочник.НастройкиАналитикиУчета КАК НастройкиАналитикиУчета
	|ГДЕ
	|	НастройкиАналитикиУчета.УправленческийУчет
	|	ИЛИ НастройкиАналитикиУчета.РегламентированныйУчет
	|
	|";
	Запрос = Новый Запрос;
	Запрос.Текст = ТекстЗапроса;
	РезультатЗапроса = Запрос.Выполнить();
	
	Возврат (Не РезультатЗапроса.Пустой());
	
КонецФУнкции // ЗаполненыНастройкиАналитикиУчета()

Функция ШаблонИзмеренийКлючаАналитики(ИмяРегистра) экспорт
	
	ТекстЗапроса = "
	|ВЫБРАТЬ
	|	НастройкиАналитикиУчета.УправленческийУчет КАК УпрУчет,
	|	НастройкиАналитикиУчета.РегламентированныйУчет КАК РеглУчет,
	|	НастройкиАналитикиУчета.ЗначениеПоУмолчанию КАК Значение,
	|	НастройкиАналитикиУчета.Код КАК Измерение
	|ИЗ
	|	Справочник.НастройкиАналитикиУчета КАК НастройкиАналитикиУчета
	|ГДЕ
	|	НастройкиАналитикиУчета.Родитель = &Родитель
	|	И НастройкиАналитикиУчета.Предопределенный
	|	И (Не НастройкиАналитикиУчета.ЭтоГруппа)
	|
	|УПОРЯДОЧИТЬ ПО
	|	НастройкиАналитикиУчета.Наименование
	|
	|";
	Запрос = Новый Запрос;
	Запрос.Текст = ТекстЗапроса;
	Запрос.УстановитьПараметр("Родитель", Справочники.НастройкиАналитикиУчета[ИмяРегистра]);
	РезультатЗапроса = Запрос.Выполнить();
	Возврат РезультатЗапроса.Выгрузить();

	
	
КонецФункции


// Экспериментальный вызов. Может так случиться, что или глюков добаваит, или 
// требуемого прироста производительности не даст. Если что, нужно отменить вызов данной процедуры
// из модуля расчиренной аналитики и раскомментироватьс тарый код и закомментировать новый.
Функция ПолучитьКлючАналитики (ИмяРегистра, СтруктураИзмерений) экспорт
	
	МенеджерЗаписи = РегистрыСведений[ИмяРегистра].СоздатьМенеджерЗаписи();
	ЗаполнитьЗначенияСвойств(МенеджерЗаписи, СтруктураИзмерений);
	
	МенеджерЗаписи.Прочитать();
	
	Если МенеджерЗаписи.Выбран() Тогда
		Возврат МенеджерЗаписи.Ссылка;
	Иначе
		Возврат неопределено;
	конецЕсли;
	
КонецФункции

 

 Измененные функции модуля "РасширеннаяАналитикаУчета"

 

Функция ЗаполненыНастройкиАналитикиУчета()
	
	// -- Begin -- Sokolov_DN -- 20141005
	// Для уменьшения тормозов: можно вызов засунуть в повторное использование и читать из кэша. 
	// Всё равно вызов непараметризуемый
	
	Возврат РасширеннаяАналитикаУчетаПовторноеИспользование.ЗаполненыНастройкиАналитикиУчета();
	
	// --  End  -- Sokolov_DN -- 20141005
	
КонецФУнкции // ЗаполненыНастройкиАналитикиУчета()

Функция ШаблонИзмеренийКлючаАналитики(
	ИмяРегистра,
	СтруктураКлючиАналитики
	)
	
	Перем ШаблонИзмерений;
	
	ИмяСтруктурыИзмерений = "Шаблон" + ИмяРегистра;
	
	Если СтруктураКлючиАналитики = Неопределено
	 ИЛИ Не СтруктураКлючиАналитики.Свойство(ИмяСтруктурыИзмерений, ШаблонИзмерений) Тогда
		
	 	Если Не ЗаполненыНастройкиАналитикиУчета() Тогда
			ЗаполнитьНастройкиАналитикиПоШаблону();
		КонецЕсли;
		
		Если ИмяРегистра = "АналитикаУчетаПрочихЗатрат" Тогда
			ШаблонИзмерений = ШаблонИзмеренийИзМакета(ИмяРегистра);
		Иначе
		
			// -- Begin -- Sokolov_DN -- 20141005
			// Для уменьшения тормозов: можно вызов засунуть в повторное использование и читать из кэша. 
			// постоянно выбираем из фиксированного справочника, поэтому лучше закэшировать и оставить базу в покое
			
			
			ШаблонИзмерений = РасширеннаяАналитикаУчетаПовторноеИспользование.ШаблонИзмеренийКлючаАналитики(ИмяРегистра);
			// --  End  -- Sokolov_DN -- 20141005
			
		КонецЕсли;
			
		Индексы = ШаблонИзмерений.Индексы;
		Индексы.Добавить("УпрУчет");
		Индексы.Добавить("РеглУчет");
				
		Если СтруктураКлючиАналитики <> Неопределено Тогда
			СтруктураКлючиАналитики.Вставить(ИмяСтруктурыИзмерений, ШаблонИзмерений);
		КонецЕсли;
		
	КонецЕсли;
	
	Возврат ШаблонИзмерений;
	
КонецФункции // ШаблонИзмеренийКлючаАналитики()

Функция ПолучитьСоздатьКлючАналитики(
	СтруктураИзмерений,
	МассивИзмерений,
	ИмяСправочника,
	ИмяРегистра,
	СтруктураКлючиАналитики
	)
	
	ЭлементКлючАналитики = Неопределено;
	
	// Попробуем получить ключ аналитики из кэша.
	Если СтруктураКлючиАналитики <> Неопределено Тогда
		ЭлементКлючАналитики = ПолучитьКлючАналитикиИзТаблицы(
			СтруктураИзмерений,
			ИмяРегистра,
			СтруктураКлючиАналитики
		);
	КонецЕсли;

	Если Не ЗначениеЗаполнено(ЭлементКлючАналитики) Тогда
		
		// Возвращаем пустую ссылку на ключ аналитики затрат, если все измерения не заполнены,
		// так как такая логика (указывать пустую ссылку) предусмотрена при формировании движений
		// в общем модулей УправлениеПроизводствомДвиженияПоРегистрам
		Если ИмяРегистра = "АналитикаУчетаЗатрат" Тогда
			ЕстьЗаполненныеИзмерения = Ложь;
			Для Каждого Измерение Из СтруктураИзмерений Цикл
				ЕстьЗаполненныеИзмерения = ЕстьЗаполненныеИзмерения ИЛИ ЗначениеЗаполнено(Измерение.Значение);
			КонецЦикла;
			Если НЕ ЕстьЗаполненныеИзмерения Тогда
				Возврат Справочники[ИмяСправочника].ПустаяСсылка();
			КонецЕсли;
		КонецЕсли;
		
		// -- Begin -- Sokolov_DN -- 20141005
		// нижестоящий кусочек так же закэшируем. Посмотрим: какой прирост будет
		
		ЭлементКлючАналитики = РасширеннаяАналитикаУчетаПовторноеИспользование.ПолучитьКлючАналитики(ИмяРегистра,СтруктураИзмерений);
		
		Если ЭлементКлючАналитики = неопределено тогда	
		// --  End  -- Sokolov_DN -- 20141005
			
			// Заполним измерения регистра, т.к. после чтения они пустые.
			
			// -- Begin -- Sokolov_DN -- 20141005
			//А вот тут таки надо убранный выше менеджер сделать
			МенеджерЗаписи = РегистрыСведений[ИмяРегистра].СоздатьМенеджерЗаписи();
			ОбновитьПовторноИспользуемыеЗначения();
			// --  End  -- Sokolov_DN -- 20141005
			
			// Заполним измерения регистра, т.к. после чтения они пустые.
			ЗаполнитьЗначенияСвойств(МенеджерЗаписи, СтруктураИзмерений);
			
			// Создадим новый элемент справочника - ключ аналитики.
			СправочникОбъект = Справочники[ИмяСправочника].СоздатьЭлемент();
			СправочникОбъект.Наименование = ПолучитьПолноеНаименованиеКлючаАналитики(
				МассивИзмерений,
				МенеджерЗаписи
			);
			СправочникОбъект.Записать();
			
			ЭлементКлючАналитики = СправочникОбъект.Ссылка;
			
			МенеджерЗаписи.Ссылка = ЭлементКлючАналитики;
			МенеджерЗаписи.Записать(Ложь);
			
		КонецЕсли;
		
		// Добавим новый ключ аналитики в кэш.
		Если СтруктураКлючиАналитики <> Неопределено Тогда
			ДобавитьКлючАналитикиВТаблицу(
				СтруктураИзмерений,
				ИмяРегистра,
				ЭлементКлючАналитики,
				СтруктураКлючиАналитики
			);
		КонецЕсли;
		
	КонецЕсли;
	
	Если ЭлементКлючАналитики = Неопределено Тогда
		ЭлементКлючАналитики = Справочники[ИмяСправочника].ПустаяСсылка();
	КонецЕсли;
	
	Возврат ЭлементКлючАналитики;
	
КонецФункции // ПолучитьСоздатьКлючАналитики()
 

РАУЗ УПП

См. также

Обмен с системой Меркурий через Web + Ветис.API для любых конфигураций (универсальная конфигурация Хамелеон Меркурий)

Оптовая торговля Производство готовой продукции (работ, услуг) Розничная торговля Обмен с ГосИС Платформа 1С v8.3 Конфигурации 1cv8 Сельское хозяйство и рыболовство Розничная и сетевая торговля (FMCG) Оптовая торговля, дистрибуция, логистика Рестораны, кафе и фаст-фуд Пищевая промышленность Россия Бухгалтерский учет Управленческий учет Платные (руб)

Универсальная конфигурация Хамелеон Меркурий для взаимодействия с системой Меркурий(тестовый+рабочий+демо контур) может использоваться для интеграции в любую конфигурацию на базе 1С, версии ПРОФ и выше. Основное отличие от других решений - работа через веб-интерфейс и API 2.0(API 2.1). Для удобства реализован общий интерфейс в виде обработки, схожей с интерфейсом Меркурий, но возможностей гораздо больше, т.к. при интеграции в Вашу учетную систему, можно на основании Ваших справочников и документов, создавать соответствующие документы и справочники в системе Меркурий и наоборот.

104000 руб.

08.11.2017    120851    296    138    

392

АРМ Начальника производства и АРМ Рабочего цеха для 1С:УНФ. Цифровое производство малого и среднего бизнеса

Рабочее место Производство готовой продукции (работ, услуг) Платформа 1С v8.3 1С:Управление нашей фирмой 1.6 1С:Управление нашей фирмой 3.0 Управленческий учет Платные (руб)

Расширение для 1С:УНФ с комплектом из двух АРМ: «АРМ для начальника производства» и «АРМ для рабочего цеха». «АРМ Начальника производства» позволяет анализировать общую картину состояния заказов покупателей и наличие конечных комплектующих и сырья для производства заказанной продукции. Есть возможность направлять заказы в производственную работу (в случае, если заказанную продукцию нужно произвести), резервировать и отгружать готовую продукцию. «АРМ рабочего цеха» позволяет обычным работникам оперативно закрывать производственные задания (оформлять документы выпуска) сразу в программе 1С.

14400 руб.

15.09.2017    48924    79    41    

85

SALE! 50%

Отчет "Полный анализ себестоимости реализованной продукции" для 1С:ERP (ЕРП), 1С:КА, 1С:ERP УХ

Производство готовой продукции (работ, услуг) Учет доходов и расходов Платформа 1С v8.3 1С:ERP Управление предприятием 2 1С:Управление холдингом 1С:Комплексная автоматизация 2.х Бухгалтерский учет Налоговый учет Платные (руб)

Данный отчет показывает себестоимость реализованной продукции в разузлованном виде, как с выделением входящих в нее полуфабрикатов любых уровней, так и свернутый до статей затрат и материалов, видов работ. Отчет работает независимо от метода оценки стоимости товаров и подходит для любых производственных компаний с многопередельным производством. Отчет можно использовать как в типовой 1С:ERP, так и в отраслевых решениях на ее базе (например, 1С:ERP Управление птицеводческим предприятием, Молокозавод и т.д.).Отчет подходит для анализа затрат на гособоронзаказы ГОЗ.

70000 35000 руб.

30.11.2022    11382    10    22    

15

SALE! 50%

Отчет "Полный анализ себестоимости выпущенной продукции" для 1С:ERP (ЕРП), 1С:КА, 1С:ERP УХ

Производство готовой продукции (работ, услуг) Учет доходов и расходов Платформа 1С v8.3 1С:ERP Управление предприятием 2 1С:Управление холдингом 1С:Комплексная автоматизация 2.х Бухгалтерский учет Управленческий учет Платные (руб)

Данный отчет показывает себестоимость выпущенной продукции с разузлованием полуфабрикатов любых уровней, входящих в ее состав, до статей затрат и материалов. Отчет работает независимо от метода оценки стоимости товаров и подходит для любых производственных компаний с многопередельным производством. Отчет можно использовать как в типовой 1С:ERP, так и в отраслевых решениях на ее базе (например, 1С:ERP Управление птицеводческим предприятием и т.д.). Отчет подходит для анализа затрат на гособоронзаказы ГОЗ.

70000 35000 руб.

08.12.2021    23741    16    72    

23

Помощник закрытия месяца

Закрытие периода Платформа 1С v8.3 1С:ERP Управление предприятием 2 1С:Управление торговлей 11 1С:Комплексная автоматизация 2.х Управленческий учет Платные (руб)

В современных конфигурациях УТ 11, КА 2, ERP 2 и их аналогах присутствует механизм закрытия периода. Но при ошибках учета закрыть период корректно становится практически невозможно! Давайте попробуем разобраться, как можно устранить ошибки и закрыть корректно месяц!

9000 руб.

20.03.2018    69834    266    58    

292
Комментарии
В избранное Подписаться на ответы Сортировка: Древо развёрнутое
Свернуть все
1. ojiojiowka 07.10.14 08:52 Сейчас в теме
К сожалению, УПП нет под рукой, поэтому задам пару вопросов. Вторая часть статьи годная, единственное, могут возникнуть проблемы, если в этот момент меняются данные (хоть это и редко случается). Я бы запихнул это в параметры сеанса и обновлял бы их при изменении. По первой части:
1) Разве эффект не был бы таким же, если у физического лица включить индексирование? Меня просто не очень прельщает кардинальная переделка порядка измерений. Здесь помогло, в другом случае может навредить. Надо полностью оценить все основные операции над этим регистром.
2) Не будет ли являться избыточным для первого измерения (физического лица) ещё и установка свойства индексировать? Почитайте про структуру индексов 1С. Нужный индекс уже будет, зачем создавать избыточный с периодом между физ лицом и остальными измерениями?
acanta; alexscamp; DNSokol; +3 Ответить
2. DNSokol 86 07.10.14 11:29 Сейчас в теме
(1) ojiojiowka,

Отвечу по порядку:

Про изменение данных. Да, данные меняются, но, не просто так по коду ползал. Функция ЗаполненыНастройкиАналитикиУчета() делает выборку практически из статичного справочника, которые меняется не чаще чем почти никогда. Это же касается и функции ШаблонИзмеренийКлючаАналитики(). Самый большой вопрос был по функции ПолучитьКлючАналитики(). Тут возможны изменения, в т.ч. и при расчете себестоимости. Поэтому, если вызов данной функции вернул пустой результат, отрабатывает уже типовое создание ключа аналитики, после чего вызывается стандартная функция ОбновитьПовторноИспользуемыеЗначения(). Единственное, чем плох этот алгоритм, так это тем, что ОбновитьПовторноИспользуемыеЗначения() сбрасывает кэш не конкретной функции, для которой включено повторное использование значений, а весь кэш. Тем не менее, т.к. вызовы сброса сильно не частые (у меня в расчете себестоимости сбрасывается кэш 3-4 раза, то использование повторно возвращаемых значений дает очень положительный эффект на быстродействие.

Про эффект. Нет, не был бы. Подробно вспоминать (ибо уже давно не кодер) как работают механизмы 1С просто времени не было. К сожалению. Просто есть факт того, что если измерение сделать первым по списку, то получил прирост скорости работы. Если к этому включить индексирование (в конфигураторе), то прирост будет еще более существенный. Если просто включить индексирование, то прирост будет не такой, как с перемещением измерений.

Про "Надо полностью оценить все основные операции". Это не просто сделать надо, это обязательно надо сделать и в первую же очередь. Я про это в статье и написал. Т.к. если просто переместить измерения и включить индексирование, то можно получить ни прирост в скорости работы, а ухудшение. Например, если в УПП включено использование заказов, и, информации по заказам сильно больше в регистре, чем информации по переданным материалам, то мои изменения приведут к не желательным последствиям.

Про избыточность индекса. Нет, не будет избыточным. Просто похоже 1С при создании на SQL таблицы для регистра сведений (по крайней мере для независимого) делает кластерный индекс вида "измерение1+измерение2+измерение3", а если на измерение повесить галку "индексировать", то будет сделан дополнительно еще один индекс по тем полям, для которых галки "индексировать" установлены. Именно по этой причине злоупотреблять галочками "индексировать" нельзя, т.к. если, например, измерений будет более чем много, то хаотичная расстановка галочек приведет к тормозам при записи (много индексов будет) и отсутствию прироста скорости при чтении (всё равно запросы не будут попадать в индексы и будут сканы таблиц на SQL).

В общем и целом как-то так.
DrBlack; Makushimo; unoDosTres; +3 Ответить
3. AlX0id 07.10.14 13:14 Сейчас в теме
(2) DNSokol,
Про избыточность индекса. Нет, не будет избыточным. Просто похоже 1С при создании на SQL таблицы для регистра сведений (по крайней мере для независимого) делает кластерный индекс вида "измерение1+измерение2+измерение3", а если на измерение повесить галку "индексировать", то будет сделан дополнительно еще один индекс по тем полям, для которых галки "индексировать" установлены.

Ну и в чем тогда дополнительная польза от индекса "Измерение1" при наличии индекса "измерение1+измерение2+измерение3"?
4. DNSokol 86 07.10.14 14:08 Сейчас в теме
(3) AlX0id,

Выгода в скорости. Если у меня запрос только по ФЛ, то SQL выберет индекс по ФЛ, который более оптимален, чем кластерный индекс => запрос отработает быстрее.
8. AlX0id 07.10.14 14:52 Сейчас в теме
(4) DNSokol,
В чем заключается его оптимальность по отношению к кластерному индексу можете сказать?

ЗЫ. А по поводу ЗаполненыНастройкиАналитикиУчета() - запустил у себя расчет себестоимости - вызывается ровно 8 раз.. Видимо, сильно зависит от настроек учета..
12. DNSokol 86 07.10.14 15:37 Сейчас в теме
(8) AlX0id,
это уже в книжки по СУБД. Сорри.
13. AlX0id 07.10.14 15:52 Сейчас в теме
(12) DNSokol,
Ну и на том, спасибо, что отправили )) Если на пальцах, то:
Кластерный индекс - это сама таблица. А вот некластерный индекс в вашем случае - это только ключ из одного столбца.
Если в таблице несколько столбцов, а в некластерном индексе ключ из одного, то и занимать таблица будет больше страниц, чем некластерный индекс, соответственно, чтобы просканировать некластерный индекс надо меньше прочитать экстентов серверу. Отсюда и выигрыш.

15. kapustinag 07.10.14 16:25 Сейчас в теме
(8) AlX0id, Оптимальность/Неоптимальность индекса по одному измерению по сравнению с кластерным индексом - вещь относительная, то есть в разных условиях эксплуатации БД и при разных характеристиках таблицы преимущество может быть то у одного индекса, то у другого.
С одной стороны, кластерный индекс физически в файле базы данных размещается таким образом, чтобы получить выигрыш при чтении данных - то есть узлы кластерного индекса располагаются рядом со строками самой таблицы. Это - в плюс кластерному индексу.
С другой стороны, индекс по одному измерению может занимать существенно меньше места, то есть может быть прочитан за очень малое количество операций физического чтения. Это - в плюс индексу по одному измерению.
Но - еще раз повторюсь - эти плюсы и минусы могут пересиливать друг друга на разных запросах, разной наполненности таблиц, разной степени фрагментированности БД, разной разбивке БД на файлы...
17. DNSokol 86 07.10.14 16:51 Сейчас в теме
(15) kapustinag,

именно так! Помимо этого есть еще множество нюансов, влияющих на конечный результат. Просто в первой части статьи хотел показать сам принцип, что прежде чем лезть в SQL и что-то там докручивать, можно внести небольшие изменения в порядок следования измерений и индексирование. Если делать всё вдумчиво, а не просто "индексы ускоряют, значит сейчас везде понатыкаю галок <индексировать>" то можно получить достаточно существенный прирост производительности.
20. AlX0id 07.10.14 22:56 Сейчас в теме
(15) kapustinag,
Ну вот поэтому-то я и задал вопрос автору, почему он в данном случае считает более оптимальным именно некластерный индекс.

Но чем больше я в это вдаюсь, тем все "страньше и страньше".
Во-первых, некластерный индекс, создаваемый 1С, не так уж и сильно отличается по длине от кластерного в случае того же регистра АналитикаУчетаПартий - так как включает в себя все измерения регистра. То есть, короче ровно на один ресурс.
Во-вторых, по результатам замера производительности расчет себестоимости делает в основном не запросы по Физлицу, как можно предположить из статьи (но довольно странно с точки зрения логики РАУЗ), а по ресурсам регистров аналитики (которые как раз-таки индексированы в типовой).

Вот со второй частью повествования я могу согласиться, хотя у меня данная ситуация и не повторяется. А вот с первой - что-то слишком натянуто. Непонятно, откуда взята мысль, что надо индексировать именно это измерение.

ЗЫ. Начал ковыряться в структуре индексов - вообще наткнулся на такую картину:
Регистр аналитики до реструктуризации
И такие индексы по всем регистрам сведений. То есть НЕкластерные.
А вот если изменить структуру регистра в 1С - тут же появляется кластерный индекс..
ojiojiowka; +1 Ответить
21. DNSokol 86 07.10.14 23:23 Сейчас в теме
(20) AlX0id,

Как бы это по мягше то сказать то.... В общем, я писал уже, что не плохо бы книжки почитать.

Например, про кластерные индексы можно тут узнать. Там же можно узнать почему кластерный индекс на таблицу может быть только один, а не много. И изучив то, как MS SQL строит кластерный индекс можно понять, почему порядок измерений влияет на скорость выборок, при том, существенно.

Про физлицо. Узнать почему нужно индексировать в моем случае именно это измерение - можно из статьи. Там явно это написано. Там же написано, что нужно сделать перед тем, как принять решение о том, что физлицо нужно переместить "вверх" списка измерений.

В остальном вам помогут или ЖКК или изучение того, как РАУЗ работает, а конкретно, как строятся выборки по аналитикам и почему в конкретно моем примере перемещение физлица дало прирост в скорости.

Приношу извинения, но просто заниматься преподаванием основ СУБД нет времени.
23. AlX0id 08.10.14 10:15 Сейчас в теме
(21) DNSokol,
А где вы увидели в моем сообщении, что я ищу несколько кластерных индексов по таблице? В картинке в явном виде показано, что до реструктуризации нет КЛАСТЕРНОГО индекса в принципе, а после, как сказано в сообщении - есть.

Если бы Вы не ограничивались описанием работы исключительно на уровне 1С, а привели план запроса, а заодно и latches по нему для случаев с дополнительным индексом и без него, ваши мысли были бы яснее.

Вот чего я ожидал увидеть в статье, а не некое эмпирически подобранное решение.

В остальном вам помогут или ЖКК или изучение того, как РАУЗ работает, а конкретно, как строятся выборки по аналитикам и почему в конкретно моем примере перемещение физлица дало прирост в скорости.

Ну так приведите же хоть один запрос из расчета себестоимости, где этот индекс дает прирост производительности, и половина вопросов отпадет.
25. DNSokol 86 08.10.14 10:54 Сейчас в теме
(23) AlX0id,
в школу. Учится. Цели проводить обучение у меня не стоит. Ровно как и не стоит цели рассказывать основы СУБД. Про планы запроса - читаем очень внимательно и вдумчиво преамбулу к статье. Там кратко описано содержание статьи. Нужен профайлер и полный технический анализ - берите в руки инструменты и вперед. Напишите тут свой доклад на тему улучшения производительности с техническим обоснованием. У меня задачи загрузить потоком сознания и показать какой я крутой СУБДист - не было.
26. AlX0id 08.10.14 11:11 Сейчас в теме
(25) DNSokol,
Мдэ? То-то я смотрю, вы, как "крутой СУБДист" меня в школу "учится" отправляете ))
Хорошо, не буду задавать вам вопросов, которые вам неудобны.
ilov_boris; +1 Ответить
6. qwinter 671 07.10.14 14:26 Сейчас в теме
(3) AlX0id, для данного регистра разницы между между просто врубить индексирования, и переместить и врубить в быстродействии не будет.

А вообще выборка по первому индексу всегда эффективней, чем по второму, третьему и т.д. Поэтому перемещение относительно других индексированных элементов действительно дает эффект. Но так как данный регистр не подчинен регистратору и не имеет реквизитов с свойством "Индексировать" то у него нет таблиц индексов. И поставив "Индексировать" у физического лица вы создадите единственный индекс. И не важно, какой будет порядок у реквизитов.
11. DNSokol 86 07.10.14 15:32 Сейчас в теме
(6) qwinter,

Ну, тут нет времени подробно разбираться. Тут просто констатирую факт, что разница есть, и, она видна. Если просто порядок измерений поменять, то выборка быстрее производится. Если включить индексирование, то создается на SQL еще один индекс (к тому, что уже имеется "по умолчанию"). Так что порядок имеет значение.
5. qwinter 671 07.10.14 14:18 Сейчас в теме
(2) DNSokol, вы заблуждаетесь, 1С не создает индексов по типу: "измерение1+измерение2+измерение3" регистры сведений индексируются по умолчанию только по регистратору.
7. AlX0id 07.10.14 14:48 Сейчас в теме
(5) qwinter,
Непериодический регистр сведений
Индекс
Условие и описание
Измерение1 + [Измерение2 +...]
Есть хоть одно измерение регистра.
Индекс, включающий все измерения в том порядке, в котором они заданы при конфигурировании.

ИзмерениеN + Измерение1 + [Измерение2 +...]
Измерению "ИзмерениеN" задано свойство "Индексировать" или свойство "Ведущее" и при этом это не первое и не единственное измерение.
Индекс, включающий все измерения. Первое поле - ИзмерениеN, затем все остальные измерения в том порядке, в котором они заданы при конфигурировании.



В частности:
Таблица: РегистрСведений.АналитикаУчетаПартий, Имя таблицы хранения: InfoRg19844, Назначение: Основная
- поля:
СтатусПартии (Fld19845)
Заказ (Fld19846)
ДоговорКомитента (Fld19847)
Комиссионер (Fld19848)
ДоговорКомиссионера (Fld19849)
ДокументПередачи (Fld19850)
ФизЛицо (Fld19851)
НазначениеИспользования (Fld19852)
Ссылка (Fld19853)
(SimpleKey)
- индексы:
ByDims
СтатусПартии + Заказ + ДоговорКомитента + Комиссионер + ДоговорКомиссионера + ДокументПередачи + ФизЛицо + НазначениеИспользования (Fld19845 + Fld19846 + Fld19847 + Fld19848 + Fld19849 + Fld19850 + Fld19851 + Fld19852)
ByResource19854
Ссылка + СтатусПартии + Заказ + ДоговорКомитента + Комиссионер + ДоговорКомиссионера + ДокументПередачи + ФизЛицо + НазначениеИспользования (Fld19853 + Fld19845 + Fld19846 + Fld19847 + Fld19848 + Fld19849 + Fld19850 + Fld19851 + Fld19852)
BySimpleKey
SimpleKey (SimpleKey)
Показать
alexscamp; qwinter; jan27; +3 Ответить
10. DNSokol 86 07.10.14 15:29 Сейчас в теме
(5) qwinter,

Создает, но немного не так, как я описал. Тут ошибочка. Когда смотрел на SQL базу, то посмотрел на регистр, в котором несколько измерений индексировалось.
9. PiccaHut001 07.10.14 15:19 Сейчас в теме
Автор, спасибо. Ускорили РАУЗ в 30!!! раз. Видно, писателям типовой УПП было недосуг заморачиваться просмотром своего овнокода шедеврального творения. Работает на 10 документах, и ладно. А потом эти удакисертифицированные преподаватели запрещают нам писать запросы в цикле(даже если цикл из 2 итераций).
unduty; BorovikSV; DrBlack; +3 Ответить
14. unoDosTres 07.10.14 16:17 Сейчас в теме
ну идея понятна, вот только функцию
ПолучитьКлючАналитики
найти не удалось, я так понимаю все три перечисленные функции вызывались из ОбщегоМодуля "РасширеннаяАналитикаУчета", правда Релиз конфы посвежей, думаю попробовать хотя бы на вызове двух функций проверить с изменением порядка измерений в регистре АналитикаУчетаПартий
16. DNSokol 86 07.10.14 16:44 Сейчас в теме
(14) unoDosTres,

Описался немного. Функция называется "ПолучитьСоздатьКлючАналитики". Сейчас текст подправлю. Соответственно в Расширенной аналитике учета измененный кусок кода вот так выглядит:

		Если ИмяРегистра = "АналитикаУчетаЗатрат" Тогда
			ЕстьЗаполненныеИзмерения = Ложь;
			Для Каждого Измерение Из СтруктураИзмерений Цикл
				ЕстьЗаполненныеИзмерения = ЕстьЗаполненныеИзмерения ИЛИ ЗначениеЗаполнено(Измерение.Значение);
			КонецЦикла;
			Если НЕ ЕстьЗаполненныеИзмерения Тогда
				Возврат Справочники[ИмяСправочника].ПустаяСсылка();
			КонецЕсли;
		КонецЕсли;
		
		// -- Begin -- Sokolov_DN -- 20141005
		// нижестоящий кусочек так же закэшируем. Посмотрим: какой прирост будет
		
		//МенеджерЗаписи = РегистрыСведений[ИмяРегистра].СоздатьМенеджерЗаписи();
		//ЗаполнитьЗначенияСвойств(МенеджерЗаписи, СтруктураИзмерений);
		//
		//МенеджерЗаписи.Прочитать();
		//
		//Если МенеджерЗаписи.Выбран() Тогда
		//	ЭлементКлючАналитики = МенеджерЗаписи.Ссылка;
		//Иначе
		ЭлементКлючАналитики = РасширеннаяАналитикаУчетаПовторноеИспользование.ПолучитьКлючАналитики(ИмяРегистра,СтруктураИзмерений);
		// --  End  -- Sokolov_DN -- 20141005
		
		Если ЭлементКлючАналитики = неопределено тогда	
			// Заполним измерения регистра, т.к. после чтения они пустые.
			
			// -- Begin -- Sokolov_DN -- 20141005
			//А вот тут таки надо убранный выше менеджер сделать
			МенеджерЗаписи = РегистрыСведений[ИмяРегистра].СоздатьМенеджерЗаписи();
			ОбновитьПовторноИспользуемыеЗначения();
			// --  End  -- Sokolov_DN -- 20141005
			
			ЗаполнитьЗначенияСвойств(МенеджерЗаписи, СтруктураИзмерений);
			
			// Создадим новый элемент справочника - ключ аналитики.
			СправочникОбъект = Справочники[ИмяСправочника].СоздатьЭлемент();
			СправочникОбъект.Наименование = ПолучитьПолноеНаименованиеКлючаАналитики(
				МассивИзмерений,
				МенеджерЗаписи
			);
			СправочникОбъект.Записать();
			
			ЭлементКлючАналитики = СправочникОбъект.Ссылка;
			
			МенеджерЗаписи.Ссылка = ЭлементКлючАналитики;
			МенеджерЗаписи.Записать(Ложь);
			
		КонецЕсли;
		
		// Добавим новый ключ аналитики в кэш.
		Если СтруктураКлючиАналитики <> Неопределено Тогда
			ДобавитьКлючАналитикиВТаблицу(
				СтруктураИзмерений,
				ИмяРегистра,
				ЭлементКлючАналитики,
				СтруктураКлючиАналитики
			);
		КонецЕсли;
		
	КонецЕсли;

Показать


а в свой модуль с повторным использованием надо добавить вот такую функцию:
Функция ПолучитьКлючАналитики (ИмяРегистра, СтруктураИзмерений) экспорт
	
	МенеджерЗаписи = РегистрыСведений[ИмяРегистра].СоздатьМенеджерЗаписи();
	ЗаполнитьЗначенияСвойств(МенеджерЗаписи, СтруктураИзмерений);
	
	МенеджерЗаписи.Прочитать();
	
	Если МенеджерЗаписи.Выбран() Тогда
		Возврат МенеджерЗаписи.Ссылка;
	Иначе
		Возврат неопределено;
	конецЕсли;
	
КонецФункции

Показать
18. Константин С. 665 07.10.14 18:29 Сейчас в теме
тогда уж опиши эту процедуру)
"ШаблонИзмеренийКлючаАналитики"

19. DNSokol 86 07.10.14 18:39 Сейчас в теме
(18) Константин С.,

)))) Да я хотел измененные модули приложить, а они только при включенных "поборах" прикладываются :) Изменил статью. В коней статьи добавил код, который менялся.
22. asved.ru 36 08.10.14 07:41 Сейчас в теме
Что касается дополнительного индекса по первому полю кластерного индекса - очень странна Ваша мысль. Регистр-то непериодический, независимый, поэтому поле действительно идет первым в кластерном индексе.

Размер дополнительного индекса возможно, будет немного меньше (а возможно - и нет, тут смотреть надо, не задублировалось ли в нем первое поле), но потом все равно придется делать key_lookup, так что далеко не факт, что СУБД выберет именно такой путь. Это возможно при высочайшей селективности, отсутствии требуемых страниц в буфере и нагруженности I/O.

Если бы Вы не ограничивались описанием работы исключительно на уровне 1С, а привели план запроса, а заодно и latches по нему для случаев с дополнительным индексом и без него, ваши мысли были бы яснее.

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

Хотелось бы, конечно, чтобы платформа позволяла построение произвольных индексов.
alexscamp; qwinter; jan27; ojiojiowka; AlX0id; +5 Ответить
24. DNSokol 86 08.10.14 10:49 Сейчас в теме
(22) asved.ru,

Я же в преамбуле к статье написал, что тут приведена рекомендация по тому, как можно повысить производительность. И там же написал, что некоторые вещи просто принимаются на веру. У меня при написании материала не было задачи доказать, что то, что принято за аксиому, аксиомой и является. Более того, у меня так же не было задачи блестать знаниями профайлера и кому-то что-либо доказывать.

Еще раз - основная задача материала - дать небольшую базу о том, используя какие основы и какие подходы можно существенно поднять производительность, а не загрузить читателя потоком сознания. И судя по комментариям, некоторым статься помогла. Т.е. цель материала достигнута.

Именно поэтому, все описание ограничено средствами 1С и тем, как средствами 1С модно улучшить работу. И именно поэтому тут нет дополнительной "технической доказательной базы". Если есть пытливые умы, которые хотят посидеть под профайлером и почитать книжки - я не против и ни в коей мере не ограничиваю. Берите профайлер и вперед. Можете свою статью написать, где будет большая доказательная база с планами выполнения запросов и т.д.

Сейчас имеем следующее - цель статьи достигнута. На этом большая и жирная точка. Если у меня будет другая цель, напишу по другому.
iterf@yandex.ru; +1 Ответить
31. asved.ru 36 08.10.14 17:04 Сейчас в теме
(24) DNSokol, т.е. Вы вводите людей в заблуждение на предмет дополнительной индексации первого поля кластерного индекса - и считаете, что цель статьи достигнута?
ojiojiowka; +1 Ответить
32. DNSokol 86 08.10.14 17:20 Сейчас в теме
(31) asved.ru,
Напишите свою статью. без "заблуждений". Это первое. Второе - я не буду объяснять почему индекс по ФЛ будет работать быстрее чем имеющийся кластерный индекс. У меня не стоит цели рассказывать основы MSSQL. И третье - зачастую людям нужно получить эффект, а не пространственные объяснения. Я в преамбуле написал, что для объяснений есть книги. Я не знаю как по другому еще сказать. Перечитайте что ли еще раз то, что жирным выделил.

Ну и да, четвертое - постройте табличку с 5 полями и кластерным индексом. Сделайте выборку с условием сначала по первому полю, потом по 4. Измерьте скорость выполнения. Изучите план выполнения. Потом на эту же табличку постройте индекс на первое поле, так же сделайте выборку по индексу из первого поля. Скорость измерить так же надобно. А вот потом на основе полученного эксперимента можете написать здесь статью про то, какой нехороший я, вводящий людей в заблуждение, и какой хороший вы. Заодно посмотрим, на сколько эта статья будет популярна и скольким людям ваша статья поможет увеличить скорость расчета себестоимости в 10 и более раз.

Тема закрыта.
34. ojiojiowka 08.10.14 18:04 Сейчас в теме
(32) по поводу свойства "индексировать" у поля "ФизическоеЛицо" Вы так и не ответили. После изменения порядка измерений оно так и осталось избыточным...
37. asved.ru 36 08.10.14 19:55 Сейчас в теме
(32) DNSokol,
Второе - я не буду объяснять почему индекс по ФЛ будет работать быстрее чем имеющийся кластерный индекс


Зато я уже объяснил несколькими комментариями выше, почему он НЕ будет работать быстрее.

Я в преамбуле написал, что для объяснений есть книги

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

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

alexscamp; Ovrfox; EliasShy; ojiojiowka; +4 Ответить
39. DNSokol 86 08.10.14 23:39 Сейчас в теме
(37) asved.ru,

ну-ну. С выключенной галкой "индексировать" время расчета себестоимости 11:20. Если включаем эту галочку и проводим расчет себестоимости, то время получается 8:02.

Внимание вопрос - что делает галочка?
46. asved.ru 36 11.10.14 20:40 Сейчас в теме
(39) DNSokol,
С выключенной галкой "индексировать" время расчета себестоимости 11:20. Если включаем эту галочку и проводим расчет себестоимости, то время получается 8:02.


А план запроса показать стесняемся?
ojiojiowka; +1 Ответить
47. PiccaHut001 15.10.14 13:11 Сейчас в теме
(46) asved.ru, вы *а****и уже, план запроса не показатель, он может быть разным для одной базы, после ночной индексации он один, вечером, после активной работы - другой. Мы же оптимизируем 1С, какой тогда смысл его выкладывать?
fzt; RibD; +2 Ответить
27. AlexBar 51 08.10.14 11:37 Сейчас в теме
Мне не совсем понятно в чем выигрыш при получении шаблона через новый модуль? При входе в функцию "ШаблонИзмеренийКлючаАналитики" передается параметр "СтруктураКлючиАналитики" которая и содержит "кешированные" шаблоны. Запрос к СУБД производится только в том случае, если в этой структуре шаблон не найден. Смотрите строку
Если СтруктураКлючиАналитики = Неопределено
     ИЛИ Не СтруктураКлючиАналитики.Свойство(ИмяСтруктурыИзмерений, ШаблонИзмерений) Тогда


Т.е. к СУБД обращение производится только один раз для каждого из регистров "УчетЗатрат" ("УчетЗатратРегл"). Вы анализировали сколько раз при вызове данной функции выполняется запрос?

То же самое касается и "ПолучитьСоздатьКлючАналитики". Для каждого ключа аналитики действие производится только один раз, после получения ключа он помещается в таблицу и в следующий раз считывается уже оттуда:

    // Попробуем получить ключ аналитики из кэша.
    Если СтруктураКлючиАналитики <> Неопределено Тогда
        ЭлементКлючАналитики = ПолучитьКлючАналитикиИзТаблицы(
            СтруктураИзмерений,
            ИмяРегистра,
            СтруктураКлючиАналитики
        );
    КонецЕсли;

    Если Не ЗначениеЗаполнено(ЭлементКлючАналитики) Тогда
Показать


Т.е. обращение к СУБД и запись в СУБД ключа производится производится только один раз для каждого набора аналитики.
Вы анализировали эту ситуацию прежде чем оптимизировать данные участки кода?
28. DNSokol 86 08.10.14 13:39 Сейчас в теме
(27) AlexBar,

Я тоже сначала так думал. Но, расстроило меня то, что СУБД даки постоянно читалась. Поэтому, выигрыш в том, что мы не лезем каждый раз в базу.

Так вот, если уж разбираться подробно, то если смотреть вызовы функции ШаблонИзмеренийКлючаАналитики в модуле расширенной аналитики, то видно приблизительно следующее:

		Запрос.Текст = "ВЫБРАТЬ";
		СтруктураИзмерений = Новый Структура();
		МассивИзмерений = Новый Массив();
		ШаблонИзмерений = ШаблонИзмеренийКлючаАналитики(КлючАналитики.Ключ, Неопределено);



т.е. вместо "кэша" всегда и во всех вызовах передается "неопределено". Итого у нас получается 2 варианта: использовать повторное использование значений или городить огород с реализацией кэша. Я выбрал второй вариант, т.к. изменения типовых модулей минимальны, а это значит, что обновлять их будет проще, в случае надобности. Собственно, это еще и ответ на вопрос про анализ :) естественно анализировал, и, естественно смотрел что в функцию передаётся.

И да, то же самое касается и "ПолучитьСоздатьКлючАналитики". Эта функция вызывается в единственном месте в функции "ПолучитьЗначениеКлючаАналитики". В данную функцию передается тот самый "кэш" последним параметром, и... и он во всех вызовах использует или "неопределено" или туда передается пустая структура, как, например в процедуре "ПолучитьАналитикуРаспределенияЗатратНаВыпуск", которая вызывается из "ВыполнитьРаспределениеСтрокиРасходовНаВыпуск" которая вызывается из "ВыполнитьРаспределениеРасходов" в которой вот это перед вызовом:
СтруктураКлючиАналитики = Новый Структура


поэтому в этом "кэше" всегда пусто. Поэтому чтение СУБД происходит при каждом новом вызове. Можно было всё эту вереницу вызовов размотать, докопаться до того, как заставить всё это работать с кэшем, а можно было просто сделать повторное использование.

У меня есть предположения, почему кэш перестали использовать, но, это только предположения.
29. AlexBar 51 08.10.14 15:41 Сейчас в теме
Вероятно мы с Вами смотрим разные куски кода указанного модуля.
Приведенный Вами код имеет отношение только к процедурам тестирования и проверки ключей аналитики: "ОбновитьНаименованияКлючейАналитики" и "ПроверитьСсылочнуюЦелостностьКлючейАналитики". Пожалуй это мы обсуждать не будем, так как к нашей теме отношения не имеет.
В функции же, которая возвращает значение ключа аналитики ("ПолучитьЗначениеКлючаАналитики") используется иной код:
	ШаблонИзмерений = ШаблонИзмеренийКлючаАналитики(
		ИмяРегистра,
		СтруктураКлючиАналитики
	);

Именно эта функция и используется во всех механизмах расчетов и формирования движений РАУЗ.

При анализе видно что при начале формирования движений, не обязательно РСВ, СтруктураКлючиАналитики создается пустой, но по мере формирования движений структура наполняется шаблонами.
30. DNSokol 86 08.10.14 17:03 Сейчас в теме
(29) AlexBar,

Сначала вернусь к первоначальному вопросу "в чем выигрыш" - выигрыш во времени исполнения функции получения данных. При идентичном наборе входящих параметров функция возвращает результат без исполнения. Конкретно не производится выборка базы. Во времени этот выигрыш конкретно по указанной процедуре - 40 минут расчета себестоимости. Это мной задокументированный факт. С часами, думаю, спорить бесполезно и бессмысленно как минимум по одной причине - время выполнения - это объективная констатация факта.

Далее, нет, тут вы не правы (про тестирование). В процедуру "ШаблонИзмеренийКлючаАналитики" неопределено засовывается именно в процедурах расчета, а не в процедурах тестирования. Данная функция вызывается из процедур "ПолучитьЗначениеКлючаАналитики", "ОбновитьНаименованияКлючейАналитики" и "ПроверитьСсылочнуюЦелостностьКлючейАналитики". в 2 и 3 в качестве "кэша" засовывается "неопределено". в процедуре 1 - передается структура. Сам вызов при расчете себестоимости поисходит из модулей УправлениеПроизводствомДвиженияПоРегистрам и "процедурыРасчетаСебестоимостиРасширеннаяАналитика". Где в каждом месте вызова "основной процедуры" стоит что-то вида:
Процедура СформироватьДвиженияПоВыпускуУслуг(СтруктураШапкиДокумента)
	
	СтруктураНаборыЗаписей  = РасширеннаяАналитикаУчета.ПолучитьНаборыЗаписейРегистров(СтруктураШапкиДокумента);
	СтруктураКлючиАналитики = Новый Структура;
	
// ля-ля-ля

	Если НЕ Результат.Пустой() Тогда
		
		Выборка = Результат.Выбрать();
		
		Пока Выборка.Следующий() Цикл
			
	
Показать


в цикле происходит вызов функции ПолучитьЗначениеКлючаАналитики. Как только процедура СформироватьДвиженияПоВыпускуУслуг завершается, про кэш можно забыть. его не будет. Ибо при следующем вызове данной процедуры мы получим опять вот это:

	СтруктураКлючиАналитики = Новый Структура;


Вызовов "основных процедур", где сбрасывается кэш более чем много. Не знаю как сюда картинку прилепить, но вызов вынесенного запроса производится более 300 тысяч раз. в типовом варианте это 300 тысяч обращений к СУБД. В то же время, выборка максимум вернет 30 тыс. вариантов записей. оставшиеся разы - это именно сбрасывания кэша. На этом и основан эффект, потому как при повторном использовании нам всё равно на эти обнуления. Если входящие в вызов значения идентичны закэшированным - вернется кэш.

Более того, я знаю даже почем этот "кэш" обнуляется. Все происходит потому, что этот "кэш" нужен исключительно для конкретного этапа расчета по конкретному виду расчета. В этом "кэше" должны содержаться записи, необходимые только для данного этапа, а не вообще все записи. В то же время, повторное использование значений наполнит этот "кэш" только нужными записями. Всё остальное - в памяти сервера.

С остальными процедурами картина идентична. Описывать их не буду, т.к. это и так выходит за рамки того, что в статье хотел показать.
33. pumbaE 08.10.14 17:40 Сейчас в теме
35. AlexBar 51 08.10.14 18:08 Сейчас в теме
Дмитрий, относитесь ко всему спокойнее. Вы же видите по комментариям что есть люди которым Ваша статья помогла, а это по моему мнению очень важно! А сколько еще людей прочтет вашу статью и будут Вам благодарны!
Я, да и другие коллеги, не пытаюсь Вас критиковать, всего лишь пытаюсь понять суть.
Вот допустим Вы приводите данные что вызов функции "ЗаполненыНастройкиАналитикиУчета" производится более 300 тысяч раз за время проведения одного документа РСВ. Соответственно столько же раз выполняется запрос. В такой ситуации вполне логичное решение от этого избавиться, так как это само по себе не нормально.
Я запустил замеры времени на своей базе на момент расчета себестоимости. После расчета посмотрел результат: у меня вызов этой функции производится всего 2 раза. При этом аналитики учета у нас доработаны, в ключи введены еще пара измерений. Расчет себестоимости не превышает 10 минут.
Вроде 10 минут и так не много, однако если есть не оптимальные участки кода, то их бы в любом случае хотелось бы ликвидировать. Вот и копаюсь вместе с Вами в данных процедурах, чтобы понять каким образом получился выигрыш.
36. DNSokol 86 08.10.14 18:19 Сейчас в теме
(35) AlexBar,
Сорри, просто 1001 дело когда делаешь, заносит иногда. По теме - отвечу позже. У нас в базе объективно много таких вызовов. Распишу всё ближе к ночи.
38. DNSokol 86 08.10.14 23:08 Сейчас в теме
(35) AlexBar,

про 300 тыс. К сожалению, от этого не избавиться. Точнее, можно избавиться только одним способом - избавившись от РАУЗа как такового. Дело в том, что в самом регистре с аналитиками около 30 тыс. ключей. Это значит ровно одно - будет минимум 30 тыс. обращений минимум. Распределение затрат многоэтапное. Я уже неоднократно проползал весь РАУЗ. Там или глобально все переделывать надо, а это трудозатраты бешенные, или пытаться минимизировать количество обращений к СУБД. Я в общем и целом специально акцент сделал на физлицах и материалах. Если в организации большое количество рабочего персонала и большое количество подразделений, то в аналитикеУчетаПартий сформируется столько уникальных записей, сколько возможно вариантов ФизЛицо+ДокументПередачи+НазначениеИспользования. Т.о. выходит что количество таких комбинаций безгранично. В моем случае пока это 30 тыс. вариантов. РАУЗ пока из все не вычитает, бузет лезть в базу. Далее, 4 этапа распределения этих затрат, но, есть "перезакрытия". Всё это приводит к тому, что типовыми механизмами вычитываться все эти 30 тыс. позиций будут около 10 раз (точнее, количество итераций больше, но, не все 30 тыс. ключей за раз вычитываются).

В итоге, что мы имеем? А имеем то, что при таком объеме спецодежды и спецоснастки (а такой объем комбинаций именно по этой части учета) нужно или упрощать учет (не реально), или оптимизировать чтения базы. Последний вариант наименее трудозатратный в сило возможности использования повторного использования возвращаемых значений. В этом случае вся эта куча аналитит будет прочитана только один раз за расчет себестоимости.
40. AlexBar 51 09.10.14 00:22 Сейчас в теме
(38) DNSokol,
Каким методом ты подсчитывал количество вызовов функции "ЗаполненыНастройкиАналитикиУчета"?
Мне сейчас интересен не столько механизм оптимизации, сколько понять причину таких многочисленных вызовов.
Расчет себестоимости оперирует только ключами аналитики в процессе решения уравнений.
Даже при расчете базы распределения ключи не создаются, а считываются из базы на основании настроек регистра способов распределений.
Чтение и создание ключей аналитики производится только при формировании документов регистрации хозяйственной деятельности, но никак не РСВ. Этот документ не создает ключи аналитики, следовательно ему незачем столько раз читать шаблоны.
Дима, у тебя точно типовой код РСВ?
Попробуй провести РСВ в 3 итерации: первый документ выполняет пункты 1-2, второй 3-4, третий 5.
Зафиксируй сколько времени у тебя займет проведение каждого из этих документов.
Зафиксируй при какой итерации происходит многочисленный вызов обозначенной функции.
Не психуй и не поленись. Очень хочется разобраться.

ojiojiowka; AlX0id; +2 Ответить
41. Vladimir-R 167 09.10.14 09:05 Сейчас в теме
(40) количество вызовов определяется с помощью замера производительности.
42. DNSokol 86 09.10.14 10:43 Сейчас в теме
(40) AlexBar,
Расчет типовой. РСВ естественно не создает. Я специально написал про материалы и физлиц. Типовой документ "Передача материалов в эксплуатацию" создает ключи. у меня таких документов в месяц более 200. В каждом документе около 100 строчек. Помимо этого, есть еще возвраты, перемещения и т.д. Которые так же ключики создают. В идеале, если ключ единожды создан, то он должен использоваться, если бы не одно "но". В типовой УПП есть механизм назначений использования спецодежды и спецоснастки. В этом механизме используется справочник "назначения использования", который в свою очередь подчинен номенклатуре. Т.е. для каждой номенклатурной позиции будет столько записей в этом справочнике, сколько вариаций "счет учета/статья/подразделение/метод списания". У меня при 50 подразделениях, 10 статьях затрат (5 статей Принимаемые + 5 статей не принимаемые) и 4 счетах учета, используемых для отражения амортизации спец. одежды, на каждую позицию создается в итоге (т.в. спец* выдается во все подразделения) около 500-800 записей в этот справочник. А это всё - уникальные ключи для РАУЗа. Вот отсюда и вызовы.

Я, собственно, по этому и писал, что такое ускорение, как в статье, в первую очередь касается тех, у кого большой объем спец* на производстве. Можно, конечно, переделать этот блок, но, опять же, это упирается в большое количество трудозатрат. Проще провести оптимизацию вызовов. По крайней мере, на данном этапе.

Что до эксперимента, то каждый документ "Передача материалов в эксплуатацию" в итоге или создает, или использует 100 ключей. которые еще и "длинные", потому как для того, что бы по спец. одежде добраться до затратного счета, нужно проделать путь "Документ передачи (в измерениях для РАУЗ есть) -> Физлицо (в измерениях для РАУЗ) -> Назначение использования (ключ) -> Способ отражения расходов (по ссылке из ключа)".

Про измерения. После того как попередвигал измерения, документ стал проводиться около 3х секунд. До этого около минуты проводился.

Если взять регистры РАУЗа, то самый маленький - это аналитика вида учета. Там порядка 20 тыс. записей. Дальше аналитика учета затрат - 80 тыс. записей. Еще дальше - аналитика учета партий. Там около 200 тыс. записей уже. Когда оптимизировался было 150 тыс.

Вся "проблема" в спец. одежде. Если её выкинуть, то да, процедура по чтению ключей вызывается 3 или 4 раза.

Количество вызовов смотрел замером производительности. Не поверил. Поставил итератор. Сходится. Могу скрин в ЛС кинуть, если интересно. Не могу тут прицепить изображение.
43. AlexBar 51 09.10.14 11:13 Сейчас в теме
(42) DNSokol,
Я немного потерян. О чем мы сейчас говорим? Об РСВ или хоз.документах? Если о хоз.документах тогда количество вызовов становится вполне понятным если все записи являются уникальными. Если об РСВ, то укажи мне откуда производятся такие многочисленные вызовы. У меня конечно не так много спец***, но если следовать твоим рассуждениям, то в любом случае указанные функции должны вызываться столько раз, сколько различных аналитик имеется в регистре учета затрат. Я продолжаю тему только по одной причине: я не поленился внести указанные тобой изменения. Если до этих изменений РСВ проводился 9:35, то с внесенными изменениями после реиндексации и реструктуризации регистров получил время 9:29. Выигрыш в пределах погрешностей, связанных с нагрузкой на сервер рабочими базами. Однако твои результаты иные: с 2-х часов до 10-ти минут. Другой коллега заявил что ускорение 30-ти кратное. Цифры впечатляющие. Но я пытаюсь докопаться до сути.
Если ты решишь не продолжать дальше тему, то достаточно сказать: Леша, давай тему закроем. :)
44. DNSokol 86 09.10.14 12:21 Сейчас в теме
(43) AlexBar,

Написал же... Речь о хоз. документах естественно в части создания и РСВ - в части чтения. Документ "Передача материалов в эксплуатацию" создает много уникальных ключей, которые потом вычитываются РСВ.

Если смотреть по этапам:

Этап 1. Первичные документы (конкретно по спец**) в течение месяца формируют множество уникальных ключей.

Этап 2. Документами Корректировка НЗП так же походу создаются ключи (или читаются). документы делают бухгалтера перед закрытием.

Этап 3. Документом "расчет себестоимости" вызывается процедура "ПроцедурыРасчетаСебестоимостиРасширеннаяАналитика.ВыполнитьДействияДокумента", которая в конечном счете приводит к вызову "ВыполнитьРаспределениеЗатрат", которая в свою очередь в цикле вызывает следующую функцию:
					// Заполним аналитику получателя (кор. аналитику)
					АналитикаПолучателя = ПолучитьАналитикуПолучателя(СтрокаБазы, СтрокаДанныеИсточника, ПравилоРаспределения, СтруктураШапкиДокумента);



Тут АналитикаПолучателя - это тот самый пресловутый "кэш", который на самом деле не кэш, а набор ключей для дальнейшего расчета. Ну и понятно, что при каждом вызове в цикле функции "ПолучитьАналитикуПолучателя" производится сброс этого кэша, т.к.

// Возвращает аналитику получателя согласно способу определения аналитики, который указан в правиле распределения.
//
Функция ПолучитьАналитикуПолучателя(СтрокаБазы, СтрокаИсточника, ПравилоРаспределения, СтруктураШапкиДокумента)
	
	АналитикаПолучателя = Новый Структура;



Соответственно, если повторное значение не использовать, то при каждом вызове "ПолучитьАналитикуПолучателя" происходит чтение базы. При повторном использовании заполнение структуры "АналитикаПолучателя" производится сильно быстрее, т.к. при одинаковом наборе входящих параметров мы читаем базу только при первом вызове ПолучитьАналитикуПолучателя. При всех последующих вызовах то, что уже закэшировано сервером - просто возвращается. Чтение базы происходит только по тем ключам, которые не были получены ранее.

Надеюсь, теперь понятнее объяснил. Или нет? Что не понятно?
45. DNSokol 86 09.10.14 12:43 Сейчас в теме
(43) AlexBar,
И да, похожая "петрушка" наблюдается еще на строительстве, где много отношений с комиссионерами. У меня есть такой филиал. АналитикаУчетаПартий содержит 20 тыс. уникальных строчек (уникальные пары Комиссионер/Договор), но, считается по ним всё очень быстро, т.к. нет кучи циклов. По комиссионерам ключ/значение читается только 1 раз, и далеко не все 20 тыс. записей (в отличие от спец**), т.к. отношения эти не долгоиграющие.
48. ojiojiowka 15.10.14 13:27 Сейчас в теме
Наверное потомучто он зависит еще и от существующих индексов и всем интересно чем созданный доп индекс лучше кластерного по измерениям.
49. leo-i 105 24.01.15 12:39 Сейчас в теме
Добавьте тогда и это:
ШаблонИзмеренийИзМакета(ИмяРегистра).

И пара вопросов:

1. Почему выбрали свойство "Повторное использование возвращаемых значений" - "На время сеанса", а не "На время вызова"?
2. Чем на Ваш взгляд может быть чревато включение в модуль "РасширеннаяАналитикаУчетаПовторноеИспользование" функции СформироватьЗапросПоЗначениямАналитики(СправочникСсылка)?

50. DNSokol 86 27.01.15 12:13 Сейчас в теме
(49) leo-i,

не добавлял, т.к. по времени исполнения вроде как существенной прибавки к скорости работы не дает. Но, в принципе можно добавить.

По вопросам:
1. На сколько я понял из описаний, то при установке значения повторного использования "на время вызова", то по окончании работы процедуры на стороне сервера, кэш слетает, а если выбрать "на время сеанса", то кэш существует на все время сеанса работы, т.е. пока клиентское приложение не закроется. Т.к. в расчете себестоимости постоянно вызовы между клиентом и сервером прыгают, то я подумал, что лучше режим выбрать "на время сеанса", хотя, тут может и не сильно прав... нужно будет поиграть с вызовами, посмотреть, к чему это приведет.

2. На первый взгляд - ничем. Но, могу заблуждаться. нужно смотреть откуда функция вызывается.
51. ketr 125 15.09.17 11:51 Сейчас в теме
Сделал всё как написано, ощутимого прироста производительности не получил(
Вместо одного часа , стало считаться 50 минут
52. DNSokol 86 19.09.17 22:56 Сейчас в теме
(51) значит у вас тормоза где-то в другом месте. Надо конкретно с вашей базой разбираться. Так же тормоза могут быть из-за не корректно произведенных настроек сервера СУБД. У меня как-то одним тюнингом СУБД получилось существенно поднять производительность.

В любом случае без каких-либо подробностей о базе, что-то конкретное сказать сложно.
53. Монту 28.09.18 08:48 Сейчас в теме
Интересная статья, себестоймость в 1С УПП с большим числом полуфабрикатов закрывается 3-4 часа, меня это не устраивает. В выходные попробуем данное решение, и поделюсь замерами времени
54. Монту 04.10.18 14:27 Сейчас в теме
Итого результатов никаких. Ускорение на 2 минуты с 2,08 часа до 2,06 можно считать погрешностью
55. DNSokol 86 04.10.18 17:54 Сейчас в теме
(54) Значит в базе небольшое количество значений в регистре. Для того, чтобы понять почему 2 часа считается, надо прогнать расчет с/с под замером производительности, посмотреть на каком запросе тормоза и танцевать оттуда. Тормоза могут быть как вычислительные (только увеличивать производительность сервера), так и из-за гигантского количества запросов к базе. И тут вот нужно смотреть, куда лезет расчет и там ковыряться. Если есть интерес повысить скорость, можем вместе как-нибудь посмотреть.
56. Монту 04.10.18 21:27 Сейчас в теме
В регистре АналитикаУчетаПартий заполнены: Комиссионер, Договор комиссионера,Ссылка
в регистре АналитикаУчетаЗатрат заполнены: Затрата, Характеристика, Серия, Качество, ссылка
в регистре АналитикаВидаУчета заполнены: Раздел учета, Организация, Подразделение, Счет учета, Счет учета(ну), ссылка
А 99,9% времени это ПроцедурыРасчетаСебестоимостиРасширеннаяАналитика.ВыполнитьДействияДокумента

Интерес есть, производство большое, в смысле много полуфабрикатов да и продукции так что большой месяц может считаться и 3-4 часа
Оставьте свое сообщение