Имя: Пароль:
1C
1C 7.7
v7: Ускорить обработку 2 документов
,
0 Sima42
 
29.09.21
20:05
Добрый день. Есть документ. В этом документе в табличной части порядка 9000 тыс строк. Есть ещё один документ там 10 тыс строк. Я беру первый документ сравниваю табличные данные с други документом. Если найден то ставлю единичку. Вопрос в скорости обработки. Запускаю и час времени курю. Как ускорить этот процесс?
1 ДенисЧ
 
29.09.21
20:09
В 77 в документе 9 миллионов строк?

Вы там рыбного супа переели?
2 ДенисЧ
 
29.09.21
20:10
"Запускаю и час времени курю. Как ускорить этот процесс?"

Или бросай курить, или затягивайся сильней. На крайний случай можешь чистым кислородом дуть на сигарету.
3 Sima42
 
29.09.21
20:15
Извините ошибся 9 и 10 тыс
4 acanta
 
29.09.21
20:19
Надеюсь дбф.. там номер строки в документах сколько знаков поддерживает?
5 Злопчинский
 
29.09.21
20:21
(4) 4 знака. но на работоспособность это не влияет.
6 Злопчинский
 
29.09.21
20:22
(0) "сравниваю табличные данные" - весьма обобщенное описание. можно посеветовать только одно - сравнивайте быстрее!
7 Злопчинский
 
29.09.21
20:25
Вариантов куча.
ИТЗ из 1С++ - там есть вычитание ТЗ.
можно тупо штатно
- выгрузить 1док в ТЗ1, проставить +1 в допколонке.
- выгрузить 2док в ТЗ2, проставить -1 в допколонке.
ТЗ2 влепить в конец ТЗ1.
и ТЗ1.Свернуть(), где в допколонке получится 0 - там строки совпадают.
Удаляем эти строки из ТЗ1 (умно! а то опять час ждать будешь), то что осталось - несовпадающие строки.
все.
8 Злопчинский
 
29.09.21
20:28
"9000 тыс строк" - 9 миллинов строк? считаем что все-таки 9тыс...
.
как описано выше - "сравнить" на таком количестве строк займет секунд 30, а то и меньше м.б.временные затраты в основном на алгоритм "сравнения". может он у тебя хитровпендренный типа
если в ТЗ1 товар1 с харктеристикой "красный", а в ТЗ2 с харктеристикой "синий" - то это одинаковые строки только в том случае если цена в дух ТЗ отличается не более чем на 13,78%.
.
если сравнение тупое простое по совпадению реквизитов в троках - то как описано выше - это все будет очень быстро
9 Sima42
 
29.09.21
20:31
Процедура СоздатьТХТ2()

ТабЗнач = СоздатьОбъект("ТаблицаЗначений");
ТабЗнач.НоваяКолонка("ГТИН");

ТабЗнач2 = СоздатьОбъект("ТаблицаЗначений");
ТабЗнач2.НоваяКолонка("ГТИН");

Док = СоздатьОбъект("Документ.ВводКодов");
Если Док.НайтиДокумент(ДокКод)=1 тогда
Док.ВыбратьСтроки();
Пока Док.ПолучитьСтроку()=1 цикл
//Док.Печ=1;
ТабЗнач.НоваяСтрока();
ТабЗнач.ГТИН=Док.КодыДатаматрикс;
КонецЦикла;
Док.Записать();
КонецЕсли;

ВыбратьСтроки();
Пока ПолучитьСтроку()=1 цикл
ТабЗнач2.НоваяСтрока();
ТабЗнач2.ГТИН=КодГолова;
КонецЦикла;

ТабЗнач2.Сортировать("ГТИН+");
ТабЗнач.Сортировать("ГТИН+");

ТабЗнач2.ВыбратьСтроки();
Пока ТабЗнач2.ПолучитьСтроку()=1 цикл
ТабЗнач.ВыбратьСтроки();
Пока ТабЗнач.ПолучитьСтроку()=1 цикл
Если СокрЛП(ТабЗнач.ГТИН)=СокрЛП(ТабЗнач2.ГТИН) тогда
ТабЗнач.УдалитьСтроку();
Прервать;
КонецЕсли;
КонецЦикла;
КонецЦикла;


Пер=0;
Док = СоздатьОбъект("Документ.ВводКодов");
Если Док.НайтиДокумент(ДокКод)=1 тогда
Док.ВыбратьСтроки();
Пер=0;
НачатьТранзакцию();
Пока Док.ПолучитьСтроку()=1 цикл
Пер=Пер+1;
ТабЗнач.ВыбратьСтроки();
Пока ТабЗнач.ПолучитьСтроку()=1 цикл
Если СокрЛП(ТабЗнач.ГТИН)=СокрЛП(Док.КодыДатаматрикс) тогда
Док.Печ=0;
Прервать;
КонецЕсли;
КонецЦикла;

Если Пер>=500 Тогда
Пер=0;
ЗафиксироватьТранзакцию();
НачатьТранзакцию();
КонецЕсли;
КонецЦикла;
Док.Записать();
ЗафиксироватьТранзакцию();
КонецЕсли;

КонецПроцедуры
10 Sima42
 
29.09.21
20:33
При таком коде если в ТЗ1 - 9 тыс и в ТЗ2 - 10 тыс то за минуту все делает. Но если в ТЗ1 - 300 тук а в ТЗ2 - 10 тыс. То на час 1с ка повисла
11 pechkin
 
29.09.21
20:35
Мердж уже предлагали делать?
12 Злопчинский
 
29.09.21
20:39
Переделать нахрен все.
13 Sima42
 
29.09.21
20:39
Процедура СоздатьТХТ2()
    
    ТабЗнач = СоздатьОбъект("ТаблицаЗначений");
    ТабЗнач.НоваяКолонка("ГТИН");
        
    ТабЗнач2 = СоздатьОбъект("ТаблицаЗначений");
    ТабЗнач2.НоваяКолонка("ГТИН");
        
    Док = СоздатьОбъект("Документ.ВводКодов");
    Если Док.НайтиДокумент(ДокКод)=1 тогда
        Док.ВыбратьСтроки();
        Пока Док.ПолучитьСтроку()=1 цикл
            Док.Печ=1;
            ТабЗнач.НоваяСтрока();
            ТабЗнач.ГТИН=Док.КодыДатаматрикс;
        КонецЦикла;
        Док.Записать();
    КонецЕсли;
        
    ВыбратьСтроки();
    Пока ПолучитьСтроку()=1 цикл
        ТабЗнач2.НоваяСтрока();
        ТабЗнач2.ГТИН=КодГолова;
    КонецЦикла;
    
    ТабЗнач2.Сортировать("ГТИН+");
    ТабЗнач.Сортировать("ГТИН+");
        
    ТабЗнач2.ВыбратьСтроки();
    Пока ТабЗнач2.ПолучитьСтроку()=1 цикл
        ТабЗнач.ВыбратьСтроки();
        Пока ТабЗнач.ПолучитьСтроку()=1 цикл
            Если СокрЛП(ТабЗнач.ГТИН)=СокрЛП(ТабЗнач2.ГТИН) тогда
                ТабЗнач.УдалитьСтроку();
                Прервать;
            КонецЕсли;
        КонецЦикла;    
    КонецЦикла;
    
    
    Пер=0;
    Док = СоздатьОбъект("Документ.ВводКодов");
    Если Док.НайтиДокумент(ДокКод)=1 тогда
        Док.ВыбратьСтроки();
        Пер=0;
        НачатьТранзакцию();
        Пока Док.ПолучитьСтроку()=1 цикл
            Пер=Пер+1;
            ТабЗнач.ВыбратьСтроки();
            Пока ТабЗнач.ПолучитьСтроку()=1 цикл
                Если СокрЛП(ТабЗнач.ГТИН)=СокрЛП(Док.КодыДатаматрикс) тогда
                    Док.Печ=0;
                    Прервать;
                КонецЕсли;
            КонецЦикла;
            
            Если Пер>=500 Тогда
                Пер=0;
                ЗафиксироватьТранзакцию();
                НачатьТранзакцию();
            КонецЕсли;
        КонецЦикла;
        Док.Записать();
        ЗафиксироватьТранзакцию();
    КонецЕсли;
    
КонецПроцедуры
14 Sima42
 
29.09.21
20:39
Так читаться будет лучше
15 Sima42
 
29.09.21
20:40
(12) Как?
16 Злопчинский
 
29.09.21
20:40
ССЗБ
чтомешало в разных документах одинаковую сущность назвать одинаково- и там и там назвать КодыДатаМатрикс..?
17 Злопчинский
 
29.09.21
20:42
(10) "То на час 1с ка повисла"
потому что удаление строки из середины таблицы - тяжелая операция.
переделать тупо как я написал выше - склеить две таблицы и свернуть.
18 Sima42
 
29.09.21
20:42
(16) Может и нужно было. Меня это как то не напрягает
19 Злопчинский
 
29.09.21
20:44
(15) если тупо - то как я написал в (7) - удаление строк у тебя идет по совпадению ГТИН в двух таблицах.
20 Sima42
 
29.09.21
20:45
(17) В принципе код до получения ТЗ с не совпадающими данными она делает быстро. Затуп происходит на работе с документом.

Тут

Док = СоздатьОбъект("Документ.ВводКодов");
    Если Док.НайтиДокумент(ДокКод)=1 тогда
        Док.ВыбратьСтроки();
        Пер=0;
        НачатьТранзакцию();
        Пока Док.ПолучитьСтроку()=1 цикл
            Пер=Пер+1;
            ТабЗнач.ВыбратьСтроки();
            Пока ТабЗнач.ПолучитьСтроку()=1 цикл
                Если СокрЛП(ТабЗнач.ГТИН)=СокрЛП(Док.КодыДатаматрикс) тогда
                    Док.Печ=0;
                    Прервать;
                КонецЕсли;
            КонецЦикла;
            
            Если Пер>=500 Тогда
                Пер=0;
                ЗафиксироватьТранзакцию();
                НачатьТранзакцию();
            КонецЕсли;
        КонецЦикла;
        Док.Записать();
        ЗафиксироватьТранзакцию();
    КонецЕсли;
21 Злопчинский
 
29.09.21
20:52
(18) думать надо вперед, а не жпс.
Док1.ВыгрузитьТабличнуюЧасть(ТЗ1,"КодыдатаМатрикс");
Док2.ВыгрузитьТабличнуюЧасть(ТЗ2,"КодыдатаМатрикс");
ТЗ1.НоваяКолонка("Флаг","Число");
ТЗ2.НоваяКолонка("Флаг","Число");
ТЗ1.Заполнить(1,,,"Флаг");
ТЗ2.Заполнить(2,,,"Флаг");
КС1 = ТЗ1.КоличествоСтрок();
КС2 = ТЗ2.КоличествоСтрок();
ТЗ1.КоличествоСтрок(КС1+КС2);
ТЗ1.Заполнить(ТЗ2,КС1+1);
ТЗ1.Свернуть("КодыдатаМатрикс","Флаг");
ТЗ1.Сортировать("Флаг+"); //1,2,3
поз = 0;
Если ТЗ1.НайтиЗначение(3,поз,"Флаг") = 1 Тогда
ТЗ1.КоличествоСтрок(поз-1);
КонецЕсли;
.
типа так...
22 Злопчинский
 
29.09.21
20:54
ТЗ1.КоличествоСтрок(поз-1);
модифицировать на обратный проход и удалять пока Флаг = 3
23 Злопчинский
 
29.09.21
20:54
(20) ясен пень.. 9 тыс раз проходить по таблице в 10 тыс строк...
24 Ёпрст
 
29.09.21
20:57
Да уж..выкинь к едрени ыени запись дока, для начала. Лишнюю
25 Ёпрст
 
29.09.21
20:58
Транзакцию, тоже в топку
26 Ёпрст
 
29.09.21
20:58
В этом коде ни то ни то не нужно
27 Злопчинский
 
29.09.21
21:00
Пока Док.ПолучитьСтроку()=1 цикл
            Пер=Пер+1;
            ТабЗнач.ВыбратьСтроки();
            Пока ТабЗнач.ПолучитьСтроку()=1 цикл
                Если СокрЛП(ТабЗнач.ГТИН)=СокрЛП(Док.КодыДатаматрикс) тогда
                    Док.Печ=0;
                    Прервать;
                КонецЕсли;
            КонецЦикла;
.
Передалть нах на типа
.
Пока Док.ПолучитьСтроку()=1 цикл
  Пер=Пер+1;
  поз = 0;
  Если ТабЗнач.НайтиЗначение(ТабЗнач.ГТИН,поз,"КодыДатаматрикс") = 1 тогда
    Док.Печ=0;
  КонецЕсли;
КонецЦикла;
28 Злопчинский
 
29.09.21
21:04
(21) если в доках имена реквизитов разные - код тот же самый - выгрузить в ТЗ, будут в ТЗ разные колонки, добавить во вторую ТЗ (а лучше в обе), новую колонку с унифицированным именем, пробежаться по тЗ перекинуть значения в унифицированную колонку построчно, далее по коду...
29 Злопчинский
 
29.09.21
21:05
(26) поддерживаю
30 Sima42
 
29.09.21
21:11
(25) Это уже от безысходности
31 Злопчинский
 
29.09.21
21:12
(30) не путайте безысходность и бездуховность.
32 Злопчинский
 
29.09.21
21:16
(30) поправь обработку документа как в (270 и всё, я думаю что результат тебя удовлетворит
33 Sima42
 
29.09.21
22:08
(32) Действительно стало лучше. Получились такие цифры.
2500 и 9000 - 2 мин 10 сек.
9500 и 10000 - 1 мин.
Завтра попробую ещё ТЗ сделать по вашему методу. Спасибо большое!
34 Злопчинский
 
29.09.21
23:14
(33) "Действительно стало лучше"
внезапно...
.
"Завтра попробую ещё ТЗ сделать по вашему методу."
пробуй-пробуй, с методом КоличествоСтрок(N) для добавления строки или удаления - аккуратно, там есть засады.
лучше использовать циклом НоваяСтрока() для добавления и обратным удалением для обрезки. Так будет железобетонно.
35 Злопчинский
 
29.09.21
23:17
Впили себе в ГМ функцию, пригодится
.
//------------------------------------------------------------------------------------
//
Функция глОтобратьПоКолонке(ТЗВход,Колонка,Значение) Экспорт //возвращает отобранную ТЗ
    Перем ТЗ, ТЗВрем;
    
    ТЗВход.Выгрузить(ТЗ);
    ТЗ.Сортировать(Колонка+"*");    //по внутр значению, важно!

    НомСтр = 0;
    Если ТЗ.НайтиЗначение(Значение, НомСтр, Колонка) = 0 Тогда //нет такого значения
        ТЗ.УдалитьСтроки();
        Возврат ТЗ;
    Иначе
        //найдем строку, в которой уже не встречается Значение
        ТЗКС = ТЗ.КоличествоСтрок();
        Для счСтрок = НомСтр По ТЗКС Цикл
            Если ТЗ.ПолучитьЗначение(счСтрок, Колонка) <> Значение Тогда //нужное значение есть до пред.строки
                НомСтр2 = счСтрок - 1;
                Прервать;
            КонецЕсли;
            Если счСтрок = ТЗКС Тогда //нужное значение встречается до конца таблицы
                НомСтр2 = ТЗКС;
            КонецЕсли;
        КонецЦикла;
    КонецЕсли;
    ТЗВрем = СоздатьОбъект("ТаблицаЗначений");
    ТЗ.Выгрузить(ТЗВрем,НомСтр,НомСтр2);    //выгрузим только строки с нужным значением
    Возврат ТЗВрем;
КонецФункции //глОтобратьПоКолонке()
Чтобы обнаруживать ошибки, программист должен иметь ум, которому доставляет удовольствие находить изъяны там, где, казалось, царят красота и совершенство. Фредерик Брукс-младший