Имя: Пароль:
1C
 
Оптимизация записей регистров
,
0 Tateossian
 
19.10.17
22:28
Коллеги, всем привет!

В УПП есть такая функция (во всех типовых документах), удаляющая записи регистров:

// Процедура записывает набор записей на сервере (привилегированно)
//
Процедура ЗаписатьНаборЗаписейНаСервере(ИмяРегистра, Регистратор, ТаблицаДвижений = Неопределено, ТипРегистра = "РегистрНакопления") Экспорт
    
    Если ТипРегистра = "РегистрНакопления" Тогда
        Набор = РегистрыНакопления[ИмяРегистра].СоздатьНаборЗаписей();
        
        Если ТаблицаДвижений <> Неопределено Тогда
            Набор.мТаблицаДвижений = ТаблицаДвижений;
            ОбщегоНазначения.ВыполнитьДвижениеПоРегистру(Набор);        
        КонецЕсли;
        
    Иначе
        Если ТипРегистра = "РегистрБухгалтерии" Тогда
            Набор = РегистрыБухгалтерии[ИмяРегистра].СоздатьНаборЗаписей();
        ИначеЕсли ТипРегистра = "РегистрСведений" Тогда
            Набор = РегистрыСведений[ИмяРегистра].СоздатьНаборЗаписей();
        ИначеЕсли ТипРегистра = "РегистрРасчета" Тогда
            Набор = РегистрыРасчета[ИмяРегистра].СоздатьНаборЗаписей();
        КонецЕсли;
        
        Если ТаблицаДвижений <> Неопределено Тогда
            Набор.Загрузить(ТаблицаДвижений);
        КонецЕсли;
    КонецЕсли;
    
    Набор.Отбор.Регистратор.Установить(Регистратор);
    Набор.Записать();
    
КонецПроцедуры

То есть, в любом случае происходит запись набора, даже, если он содержит 0 записей. Я провел следующий тест (функция ниже):

Запрос = Новый Запрос;
Запрос.Текст =
"
|ВЫБРАТЬ ПЕРВЫЕ 100
|    РеализацияТоваровУслуг.Ссылка КАК Ссылка,
|    РеализацияТоваровУслуг.Дата КАК Дата
|ИЗ
|    Документ.РеализацияТоваровУслуг КАК РеализацияТоваровУслуг
|ГДЕ
|    РеализацияТоваровУслуг.Проведен
|    И РеализацияТоваровУслуг.Дата >= &Дата
|
|СГРУППИРОВАТЬ ПО
|    РеализацияТоваровУслуг.Ссылка,
|    РеализацияТоваровУслуг.Дата
|
|УПОРЯДОЧИТЬ ПО
|    Дата,
|    Ссылка";
Запрос.УстановитьПараметр("Дата", Дата("01.01.2016 0:00:00"));


Результат = Запрос.выполнить().Выгрузить();

Для Каждого Док Из Результат Цикл
    
    ДокОбъект = Док.Ссылка.ПолучитьОбъект();
    
    Для Каждого Д Из ДокОбъект.Движения Цикл
        
        //Способ 1: 592 302
        //Д.Записать();
        
        //Способ 2: 149 276
        Д.Прочитать();
        Если Д.Количество() Тогда
            Д.Очистить();
            Д.Записать();
        КонецЕсли;
        
    КонецЦикла;
    
    Состояние(Результат.Индекс(Док)+1);
    
КонецЦикла;

Первый способ просто записывает пустой набор. Второй способ - сначала считывает записи; если количество записей пустое, то ничего не делаем, в противном случае - пишем в регистр.

Полагаю, этот способ имеет наилучшую эффективность, когда гарантированно есть как пустые наборы, так и не пустые. А вопросы такие:

1) это предвзятый ли тест (я базу разворачивал из бэкапа) и в нем много факторов не учтено?
2) действительно ли это оптимизирует запись наборов и почему в типовой так не сделано?

Результаты тестов (100 документов) написаны в комментах - первый способ 592 секунд, второй способ - 149 секунд. Оптимизировать я хочу вот этот место:

    Набор.Отбор.Регистратор.Установить(Регистратор);
    Набор.Записать();

Переписав на чтение и проверку перед записью.
1 h-sp
 
20.10.17
03:43
"Переписав на чтение и проверку перед записью." - сразу выкиньте эту мысль. Это полная жж.па. Более тормозной штуки чем проверка на пустой набор в природе трудно встретить.
2 Cyberhawk
 
20.10.17
06:44
Ты изменишь логику метода, если не будешь писать пустые наборы. Шутник.
3 Cyberhawk
 
20.10.17
06:45
Почему-то ты отбрасываешь сценарии, когда нужно записать пустой набор.
Компьютеры — это как велосипед. Только для нашего сознания. Стив Джобс