Имя: Пароль:
1C
1С v8
Что лучше для .csv?
, ,
0 pessok
 
11.11.15
16:11
Коллеги, привет! На стадии проектирования было решено, что некий массив данных для загрузки в другую систему будет выгружаться в .csv. В тот же момент было решено, что csv будет формироваться в текстовом документе с разделителями (ТекстовыйДокумент). Потом система выросла, пришла необходимость формировать сразу несколько разных массив данных (ну, скажем, по каждому складу, дабы не вдаваться в ненужные подробности).
Пока массив был один - все было прекрасно, сейчас их 5. Формируются они в разных потоках фоновыми заданиями. Запрос в каждом потоке выполняется секунд по 15-20 (в консоле 3-4 секунды), остальное время - около 15 минут записываются данные в ТекстовыйДокумент (порядка 25 тыщ строк по 100 символов). Система в этот момент глухо висит. Отсюда вопрос - как бы это дело оптимизировать. Пробовал формировать текст в обходе выборки и писать одной строкой в ЗаписьТекста - не улучшило ситуацию. Что еще можно попробовать прикрутить? Может табличный документ?
1 H A D G E H O G s
 
11.11.15
16:12
Не формировать текст и писать построчно в ЗаписьТекста. Тема закрыта.
2 Goggy
 
11.11.15
16:15
(1) Ну у автора не получилось, как он уверяет...
3 pessok
 
11.11.15
16:17
(1) пробую
(2) я делал не как в (1), щас пробую
4 pessok
 
11.11.15
16:29
ну, после (1) стало намного лучше. Пишет шустрее, виснет меньше, хотя все равно подвисает маленько.
H A D G E H O G s , спасибо!
5 pessok
 
11.11.15
16:31
т.е., я правильно понимаю, что ТекстовыйДокумент.ДобавитьСтроку() пишет в раму, а ЗаписьТекста.ЗаписатьСтроку() сразу на диск? Таким образом рама не закакивается и система работает стабильнее?
6 H A D G E H O G s
 
11.11.15
16:33
(5) Нет.
7 pessok
 
11.11.15
16:34
(6) ну так расскажи, не жадничай
8 pessok
 
11.11.15
16:35
з.ы. сейчас все сформировалось за 8 минут и тупило значительно меньше.
9 H A D G E H O G s
 
11.11.15
16:35
"Рама" не может закакиваться. Ее может не хватать, она может быть фрагментирована. Но в твоем случае идет постоянная реаллокация под все большую непрерывную в памяти строку все медленнее и медленнее. Запись на диск тупо скидывает в кэш диска без реаллокации. Щасте.
10 H A D G E H O G s
 
11.11.15
16:36
(8) Все равно медленно.
11 pessok
 
11.11.15
16:36
(9) ну да, "закакивается" - я имел ввиду, что отжирается. Спасибо!
12 pessok
 
11.11.15
16:38
(10) да там само формирование пришлось делать неадекватное.

Я бы даже вполне трезво назвал это gовнокодом...

    ТекстДок = Новый ЗаписьТекста(ПутьВременногоФайла, КодировкаТекста.UTF8);
    Разделитель = ?(НовыйВариант, ",", "#");
    
    Колонки = РезультатЗапроса.Колонки;
    КоличествоКолонок = Колонки.Количество()-1;
    //Формируем заголовок
    ТекстЗаголовок = "pp, c1_code, product_code, category, brand, name, quantity_free, quantity_free_all, price_last, price_min, moic, sell_date";
    МассивКолонокДляВыгрузки = ОбщегоНазначения.РазложитьСтрокуВМассивПодстрок(ТекстЗаголовок);        
    ТекстДок.ЗаписатьСтроку(ТекстЗаголовок);
    
    
    Пока Выборка.Следующий() Цикл
        ТекстСтроки = "";        
        Для Каждого КолонкаПроверки Из МассивКолонокДляВыгрузки Цикл
            
            Колонка = СокрЛП(КолонкаПроверки);
            
            Если Колонки.Найти(Колонка) <> Неопределено Тогда
                
                ЗначениеЗаполнения = Выборка[Колонка];
                
                Если ТипЗнч(ЗначениеЗаполнения) = Тип("Число") Тогда
                    ЗначениеЗаполнения = Формат(ЗначениеЗаполнения, "ЧДЦ=; ЧРД=.; ЧН=0; ЧГ=0");
                Иначе
                    Если НовыйВариант Тогда
                        ЗначениеЗаполнения = СтрЗаменить(ЗначениеЗаполнения, ",", "#");
                        ЗначениеЗаполнения = СтрЗаменить(ЗначениеЗаполнения, """", "^");
                    КонецЕсли;
                КонецЕсли;
                
            Иначе
                
                Если Колонка = "category" Тогда
                    
                    ПолноеНаименование = ?(НовыйВариант,
                    СтрЗаменить(СтрЗаменить(Выборка.Ссылка.ПолноеНаименование(), ",", "#"), """", "^"),
                    Выборка.Ссылка.ПолноеНаименование());
                    
                    Наименование = ?(НовыйВариант,
                    СтрЗаменить(СтрЗаменить(Выборка.Наименование, ",", "#"), """", "^"),
                    Выборка.Наименование);
                    
                    ЗначениеЗаполнения = СтрЗаменить(ПолноеНаименование, "/"+Наименование, "");
                                    
                КонецЕсли;    
            КонецЕсли;
            
            ТекстСтроки = ТекстСтроки + ЗначениеЗаполнения + Разделитель;
        КонецЦикла;
        ТекстСтроки = Лев(ТекстСтроки, СтрДлина(ТекстСтроки)-1);
        ТекстДок.ЗаписатьСтроку(ТекстСтроки);
        ОбщегоНазначенияКлиентСервер.СообщитьПользователю("Обработано "+Инд+" из "+КоличествоЗаписей);
        Инд=Инд+1;
    КонецЦикла;
    
    ТекстДок.Закрыть();
13 H A D G E H O G s
 
11.11.15
16:40
Выборка.Ссылка.ПолноеНаименование()

убрать в запрос
14 H A D G E H O G s
 
11.11.15
16:40
Инд=Инд+1;

заменить хотябы на целочисленно на 1000 деление
15 pessok
 
11.11.15
16:44
(13) в что, появился нормальный способ полное наименование формировать в запросе?
с индикатором согласен, сделаю вывод раз в 1000
16 Serginio1
 
11.11.15
16:46
17 pessok
 
11.11.15
16:47
+(15) просто если это можно нормально сделать в запросе, то можно будет полностью уйти от цикла по колонкам
18 H A D G E H O G s
 
11.11.15
16:48
(17) Ну хотя бы кэш сделай.
19 H A D G E H O G s
 
11.11.15
16:48
Это же жесть
20 Лодырь
 
11.11.15
16:48
(15) А какой у тебя принцип формирования полного наименования?
21 Serginio1
 
11.11.15
16:49
Плюс используй для формирования не текстовый документ а ЗаписьТекста или ЗаписьXML.ЗаписатьБезОбработки http://speshuric.livejournal.com/163665.html
22 pessok
 
11.11.15
16:53
(18) а поможет ли? у меня для каждого массива данных своя номенклатура, т.е. все равно в фоне нужно будет формировать для каждого
(19) однозначно жесть...
(20) платформенная функция

(15), (21) это уже мы порешали :) в данный момент идет разбор именно код формирования строки
23 pessok
 
11.11.15
16:54
(22) хотя... можно ведь сформировать один раз для всей номенклатуры кеш и отдать уже его каждому фоновому заданию, все равно быстрее будет
24 Serginio1
 
11.11.15
16:56
Для чисел используй XMLСтрока
25 Timon1405
 
11.11.15
16:56
(22) Разве нельзя сделать реквизит номенклатуры "ПлатформенноеПолноеНаименование" и ПриЗаписи номенклатуры формировать его?
26 pessok
 
11.11.15
16:58
(25) можно, конечно, но это как-то, на мой вкус, так себе выход. С кешем нравится больше
27 pessok
 
11.11.15
16:58
(24) попробую, мерси
28 pessok
 
11.11.15
17:23
в итоге таки да
сначала формируем кеш полных наименований (соответствие) - около минуты
передаем его фоновому заданию, оно уже записывает в файл влет, что-то тоже около минуты.

это с учетом XMLСтрока вместо Формат

Всем спасибо!
29 H A D G E H O G s
 
11.11.15
17:39
Медленно
30 pessok
 
11.11.15
18:08
(29) ну как еще ускорить - я уже хз

РезультатЗапроса = Запрос.Выполнить();
    Выборка = РезультатЗапроса.Выбрать();
    КоличествоЗаписей = Выборка.Количество();
    Инд = 0;
    
    ИмяФайла = ?(НовыйВариант, "new_", "")+Строка(ТорговаяТочка.Наименование)+".csv";
    ПутьВременногоФайла = КаталогВременныхФайлов()+ИмяФайла;
    
    ТекстДок = Новый ЗаписьТекста(ПутьВременногоФайла, КодировкаТекста.UTF8);
    Разделитель = ?(НовыйВариант, ",", "#");
    
    Колонки = РезультатЗапроса.Колонки;
    КоличествоКолонок = Колонки.Количество()-1;
    //Формируем заголовок
    ТекстЗаголовок = "pp, c1_code, product_code, category, brand, name, quantity_free, quantity_free_all, price_last, price_min, moic, sell_date";
    МассивКолонокДляВыгрузки = ОбщегоНазначения.РазложитьСтрокуВМассивПодстрок(ТекстЗаголовок);        
    ТекстДок.ЗаписатьСтроку(ТекстЗаголовок);
    
    
    Пока Выборка.Следующий() Цикл
        ТекстСтроки = "";        
        Для Каждого КолонкаПроверки Из МассивКолонокДляВыгрузки Цикл
            
            Колонка = СокрЛП(КолонкаПроверки);
            
            Если Колонки.Найти(Колонка) <> Неопределено Тогда
                
                ЗначениеЗаполнения = Выборка[Колонка];
                
                Если ТипЗнч(ЗначениеЗаполнения) = Тип("Число") Тогда
                    //ЗначениеЗаполнения = Формат(ЗначениеЗаполнения, "ЧДЦ=; ЧРД=.; ЧН=0; ЧГ=0");
                    ЗначениеЗаполнения = XMLСтрока(ЗначениеЗаполнения);
                Иначе
                    Если НовыйВариант Тогда
                        ЗначениеЗаполнения = СтрЗаменить(ЗначениеЗаполнения, ",", "#");
                        ЗначениеЗаполнения = СтрЗаменить(ЗначениеЗаполнения, """", "^");
                    КонецЕсли;
                КонецЕсли;
                
            Иначе
                
                Если Колонка = "category" Тогда
                    
                    ПолноеНаименованиеИзКеша = КешПолныхНаименований[Выборка.Ссылка];
                    
                    ПолноеНаименование = ?(НовыйВариант,
                    СтрЗаменить(СтрЗаменить(ПолноеНаименованиеИзКеша, ",", "#"), """", "^"),
                    ПолноеНаименованиеИзКеша);
                    
                    Наименование = ?(НовыйВариант,
                    СтрЗаменить(СтрЗаменить(Выборка.Наименование, ",", "#"), """", "^"),
                    Выборка.Наименование);
                    
                    ЗначениеЗаполнения = СтрЗаменить(ПолноеНаименование, "/"+Наименование, "");
                                    
                КонецЕсли;    
            КонецЕсли;
            
            ТекстСтроки = ТекстСтроки + ЗначениеЗаполнения + Разделитель;
        КонецЦикла;
        ТекстСтроки = Лев(ТекстСтроки, СтрДлина(ТекстСтроки)-1);
        ТекстДок.ЗаписатьСтроку(ТекстСтроки);
        Если Инд%100 = 0 Тогда
            ОбщегоНазначенияКлиентСервер.СообщитьПользователю("Обработано "+Инд+" из "+КоличествоЗаписей);
        КонецЕсли;
        Инд=Инд+1;
    КонецЦикла;
    
    ТекстДок.Закрыть();
Чтобы обнаруживать ошибки, программист должен иметь ум, которому доставляет удовольствие находить изъяны там, где, казалось, царят красота и совершенство. Фредерик Брукс-младший