Имя: Пароль:
1C
1С v8
И все-таки: удаление записей из регистра сведений
0 moshecogan
 
25.09.12
19:11
Есть регистр ВерсииОбъектов с миллионом записей.
Допустим, надо удалить все объекты старше какой-то даты. Была сделана выборка объектов:

[code]
"ВЫБРАТЬ
   |    ВерсииОбъектов.Объект,
   |    ВерсииОбъектов.НомерВерсии,
   |    ВерсииОбъектов.ВерсияОбъекта
   |ИЗ
   |    РегистрСведений.ВерсииОбъектов КАК ВерсииОбъектов
   |ГДЕ
   |    ВерсииОбъектов.ДатаВерсии < &ДатаОчистки"
[/code]

Варианты в цикле:
1) Создавать МенеджерЗаписи, искать каждую запись и удалять ее:
[code]
Пока Версия.Следующий() Цикл    
   МенеджерЛокальный = РегистрыСведений.ВерсииОбъектов.СоздатьМенеджерЗаписи();
   МенеджерЛокальный.Объект       = Версия.Объект;
   МенеджерЛокальный.НомерВерсии  = Версия.НомерВерсии;
   МенеджерЛокальный.Удалить();
КонецЦикла;
[/code]

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

[code]
НовыйНомерВерсии = 1;    
Пока Версия.Следующий() Цикл    
       // найдем запись
       МенеджерЛокальный = РегистрыСведений.ВерсииОбъектов.СоздатьМенеджерЗаписи();
       МенеджерЛокальный.Объект       = Версия.Объект;
       МенеджерЛокальный.НомерВерсии  = Версия.НомерВерсии;
       МенеджерЛокальный.Прочитать();
       
       // пометим ее
       МенеджерЛокальный.Объект       = Справочники.Номенклатура.ПустаяСсылка();
       МенеджерЛокальный.НомерВерсии  = НовыйНомерВерсии;
       МенеджерЛокальный.ВерсияОбъекта = Неопределено;
       МенеджерЛокальный.Записать();
   НовыйНомерВерсии = НовыйНомерВерсии+1;
   КонецЦикла;
   
   // скопом удалим все отмеченные записи
   НаборЗаписей = РегистрыСведений.ВерсииОбъектов.СоздатьНаборЗаписей();
   НаборЗаписей.Отбор.Объект.Установить(Справочники.Номенклатура.ПустаяСсылка());
   НаборЗаписей.Записать();    
[/code]

В первом случае - миллион вызовов "физического удаления" записи из таблицы.
Во втором - миллион вызовов обновления реквизитов, и один вызов удаления.

С моей точки зрения, второй способ бережнее по отношению к БД.
Как все-таки правлославно?
1 moshecogan
 
25.09.12
19:11
C тэгами на форуме не освоился пока, извините.
2 Fram
 
25.09.12
19:16
по моему монописуально ,учитывая что процедура для единовременного вызова. используй транзакции и вперед
3 ChAlex
 
25.09.12
19:41
(0) - и какой выигрыш в варианте 2? Идет миллион записей, а потом еще и удаление миллиона записей. Вы хотите сказать что удаление записи будет проходить на много медленней чем ее запись?. Я - сомневаюсь. Но можете провести эксперимент с замером производительности.
4 DrShad
 
25.09.12
19:49
пипец, второй вариант тупее в несколько раз
5 Fragster
 
гуру
25.09.12
19:50
А какой там основной отбор у регистра? по логике - все комбинации основных отборов получаем, циклом записываем пустые наборы с этими отборами.
6 Fragster
 
гуру
25.09.12
19:51
если же основной отбор по периоду не стоит, то тут хуже - читаем все наборы, удаляем из них то, что не нужно, записываем
7 Fragster
 
гуру
25.09.12
19:51
быстрее всего удалить скулем, конечно же
8 bazvan
 
25.09.12
19:55
в бытность так как не кодер. выбирал сколько нужно записей и потом их обратно (предварительно создав запись (без одборов и прочего онаже обнуляется) туда все опускал.
Память жрется но мне не кретично (64 гига на серваке было) не загонялся
9 bazvan
 
25.09.12
20:02
Что то типа токого
Если ЧиститьКИпеням Тогда
       
       Сообщить("Очистка НАЧАЛО: " + ТекущаяДата());
       
       Запрос = Новый Запрос;
       Запрос.Текст =
       "ВЫБРАТЬ
       |    *
       |ИЗ
       |    РегистрСведений.МойРегистрСведений КАК МойРегистрСведений
       |ГДЕ
       |    МойРегистрСведений .ТутЧтоТоДляОтбораДаты.Дата > &Дата";
       
       Запрос.УстановитьПараметр("Дата", НачалоДня(ДатаСвертки));
       
       НужныеЗаписи = Запрос.Выполнить().Выгрузить();
       
       НовыйНабор = РегистрыСведений.МойРегистрСведений .СоздатьНаборЗаписей();
       
       НовыйНабор.Загрузить(НужныеЗаписи);
       НовыйНабор.Записать();
       
       Сообщить("Очистка  КОНЕЦ: " + ТекущаяДата());
       
   КонецЕсли; // наиух весь регистр (главное текущая дата:)


зы за код не ругайте писал как мог
10 ChAlex
 
25.09.12
22:49
(9) - все очень сильно зависит от количества удаляемых и количества оставляемых записей. Кординально оптимальное решение - через SQL. Dct ghjcntymrj b ,scnhj
11 bazvan
 
26.09.12
00:12
(10) нее скули и прочие "не типовые"это совсем не для меня, а вот количество, это да удалял 3 мулика оставлял мулик один коленкор при удалении 2 и оставлении 2 соовсем
но опять же на ресурсы было плевать их есть у меня ( 4 полноценных ксиона (по 2 ядра и того 8 полубашков) и 64 гига мозга (винты 15 000 в каком то там шустром реайде или как там) Воообщем такой вот расклад
Я не хочу быть самым богатым человеком на кладбище. Засыпать с чувством, что за день я сделал какую-нибудь потрясающую вещь — вот что меня интересует. Стив Джобс