Имя: Пароль:
1C
 
Мои запросы в цикле тормозят и делают не то, что нужно, что мне делать
0 breezee
 
07.07.15
21:07
Очень большая база, нужно вытянуть много данных, записать в excel, в общем все виснет к чертям и не собирается завершаться. Может можно как-то
1) в самом запросе разбивать строковео значение на массив подстрок
2) в самом запросе сделать вложенный цикл, как для таблицу значений, ни чего просчитывать там не надо, надо только вывести все возможные сочетания из массива, полученного из строки
1 Волшебник
 
модератор
07.07.15
21:10
зачем в Excel?
2 Волшебник
 
модератор
07.07.15
21:11
Excel предназначен для анализа человеком, а не для учёта первички. Человек не может проанализировать много. Значит нужно вытягивать уже сводные данные
3 ДенисЧ
 
07.07.15
21:11
Вон из профессии
4 Garykom
 
гуру
07.07.15
21:12
не надо прайсы в ексель а? ну не надо....
5 breezee
 
07.07.15
21:12
(1) Там обработка написанная для загрузки в другую базу, мне сказали доделывать, срочно, я в 1с еще не спец
6 Волшебник
 
модератор
07.07.15
21:13
(5) учи матчасть
7 Волшебник
 
модератор
07.07.15
21:13
выгрузка-загрузка из базы в базу делается через XML или COM-соединение
8 breezee
 
07.07.15
21:20
(7) Я это понимаю, но раз сделали так - значит удобнее. Не в этом суть, я сам сейчас в любом случае не смогу написать полноценный обмен и т.д. Мне нужно сделать следующее - есть свойство размерный ряд у номенклатуры, на пример 42-26, есть характериситки(на пример красный, зеленый) - нужно составить все сочитания для номеналатуры, + для той у которой нет свойство выписать с характериситками и для той у которой нет характеристик - выпсиать со свойствами. Я все сделал через запросы и потом выгружал их в тз, с тз и работал. Все грузилось минут 20, но грузилось, потом сказали добавить цены последние - я сделал это запросом для каждой номенклатуры, - все стало совсем долго, 1с хоть и не вылетает, но когда нажимаю alt+tab в списке только иконка конфигуратора, а предприятия нет. Через конфигрутаор захожу - нарисованы часы, показывает что идет загрузка.
9 Волшебник
 
модератор
07.07.15
21:21
(8) запросы в цикле - это зло
10 Garykom
 
гуру
07.07.15
21:22
(9) не, это не всегда зло

вот когда не специалисты берутся делать то что не умеют это да зло
11 breezee
 
07.07.15
21:26
(9) А если я выгружу полученное в тиблицу значений и буду в циле сравнивать - будет оптимальнее?
12 Волшебник
 
модератор
07.07.15
21:28
(11) Сделай замер производительности и доложи
13 breezee
 
07.07.15
22:39
Не помогает ничего, там 20 тысяч строк получается. ЧТо делать? Можно это как-то по часям разбить?
14 Лефмихалыч
 
07.07.15
22:42
(13) ссаных 20 тысяч - это курям на смех
15 breezee
 
07.07.15
22:45
(14) Там 4 вложенных цикла. Может я скину этот шизфореничный бред сюда и Вы поможете разбраться?
16 breezee
 
07.07.15
22:46
Прошу прощение за внешний вид. Сказали завтра сдавать, делал в спешке


Процедура КнопкаВыполнитьНажатие(Кнопка)
   Режим        = РежимДиалогаВыбораФайла.Сохранение;
   ДиалогВыбора = новый ДиалогВыбораФайла(Режим);
   ДиалогВыбора.ПолноеИмяФайла = "";
   Фильтр       = "Файл данных (*.xls)|*.xls";
   ДиалогВыбора.Фильтр = Фильтр;
   ДиалогВыбора.Заголовок = "Выберите Каталог";  

   Если ДиалогВыбора.Выбрать() Тогда
           ТабДок = СформироватьТабДок();
       ТабДок.Записать(ДиалогВыбора.ПолноеИмяФайла,ТипФайлаТабличногоДокумента.XLS97);
           Сообщить("Успешно!");
   Иначе
       Сообщить("Файл не сохранен!");
   КонецЕсли;

КонецПроцедуры

Функция РазложитьСтрокуВМассивПодстрок(Знач Строка, Знач Разделитель = ",",
    Знач ПропускатьПустыеСтроки = Неопределено)

    Результат = Новый Массив;

    // для обеспечения обратной совместимости
    Если ПропускатьПустыеСтроки = Неопределено Тогда
        ПропускатьПустыеСтроки = ?(Разделитель = " ", Истина, Ложь);
        Если ПустаяСтрока(Строка) Тогда
            Если Разделитель = " " Тогда
                Результат.Добавить("");
            КонецЕсли;
            Возврат Результат;
        КонецЕсли;
    КонецЕсли;
    //

    Позиция = Найти(Строка, Разделитель);
    Пока Позиция > 0 Цикл
        Подстрока = Лев(Строка, Позиция - 1);
        Если Не ПропускатьПустыеСтроки Или Не ПустаяСтрока(Подстрока) Тогда
            Результат.Добавить(Подстрока);
        КонецЕсли;
        Строка = Сред(Строка, Позиция + СтрДлина(Разделитель));
        Позиция = Найти(Строка, Разделитель);
    КонецЦикла;

    Если Не ПропускатьПустыеСтроки Или Не ПустаяСтрока(Строка) Тогда
        Результат.Добавить(Строка);
    КонецЕсли;

    Возврат Результат;

КонецФункции
Функция ПолучитьПолныйМассивРазмеров(МассивРазмеров)
    ПолныйМассивРазмеров = новый Массив;
        ПервыйЭлемент =Число(МассивРазмеров[0]);
        ПоследнийЭлемент =Число(МассивРазмеров[МассивРазмеров.Количество() - 1]);
        Пока ПервыйЭлемент <= ПоследнийЭлемент цикл
                ПолныйМассивРазмеров.Добавить(ПервыйЭлемент);
        ПервыйЭлемент = ПервыйЭлемент + 2;  
        КонецЦикла;
        Возврат ПолныйМассивРазмеров;
КонецФункции      
Функция СформироватьТабДок()
    цены = ВернутьЦену();
         Тз = новый ТаблицаЗначений;
           ТЗ.Колонки.Добавить("КодНоменклатуры" , Новый ОписаниеТипов("Строка"));
           ТЗ.Колонки.Добавить("НаименованиеНоменклатуры" , Новый ОписаниеТипов("Строка"));
           ТЗ.Колонки.Добавить("Размер" , Новый ОписаниеТипов("Строка"));
           ТЗ.Колонки.Добавить("Цвет" , Новый ОписаниеТипов("Строка"));
           Тз.Колонки.Добавить("Цена", Новый ОписаниеТипов("Число"));
                //Тз.Колонки.Добавить("ВестиУчет", Новый ОписаниеТипов("Булево"));

           МассивРазмеров = новый Массив;
        Запрос = Новый Запрос;
        Запрос.Текст =
                "ВЫБРАТЬ
                |       ЗначенияСвойствОбъектов.Объект,
                |       ЗначенияСвойствОбъектов.Свойство,
                |       ЗначенияСвойствОбъектов.Значение
                |ИЗ
                |       РегистрСведений.ЗначенияСвойствОбъектов КАК ЗначенияСвойствОбъектов";
      
        РезультатЗапроса = Запрос.Выполнить().Выгрузить();
        Для Каждого ТТ из РезультатЗапроса Цикл
              
                Если тт.Свойство.Код="000000006" И тт.Объект.ВестиУчетПоХарактеристикам И тт.Объект.ПометкаУдаления = ложь тогда  //Свойство РазмерныйРяд
                        ЕстьЦвета = Ложь;
                        Номенклатура=тт.Объект;//Номенклатура для этого свойство
                        РАзмерныйРяд=тт.Значение; //РазмерныйРяд само свойство
                        //цикл по где узнаем все свойства для номенклатуры
                        Для каждого Свойство из РезультатЗапроса цикл
                                Если ТипЗнч(Свойство.Объект)  = Тип("СправочникСсылка.ХарактеристикиНоменклатуры")
                                тогда
                                Если Свойство.Объект.Владелец = Номенклатура тогда
                                        ЕстьЦвета = Истина;
                                        Характеристика = Свойство.Объект; //Всякиие характеристики
                                        Характеристика = СтрЗаменить(Характеристика, "(", "");
                                        Характеристика = СтрЗаменить(Характеристика, ")", "");
                                        РАзмерныйРяд = СтрЗаменить(РАзмерныйРяд,"+", "");
                                        МассивРазмеров = РазложитьСтрокуВМассивПодстрок(РАзмерныйРяд,"-");
                                        ПолныйМассивРазмеров = ПолучитьПолныйМассивРазмеров(МассивРазмеров);
                                        Для каждого Элемент Из ПолныйМассивРазмеров цикл
                                        //НоваяХарактеристика =      ""+Элемент + ", " + Характеристика;
                                        ТзНоваяСтрока = Тз.Добавить();
                                    ТзНоваяСтрока.КодНоменклатуры                           =       Номенклатура.Код;
                                        ТзНоваяСтрока.НаименованиеНоменклатуры     =   Номенклатура.Наименование;
                                        ТзНоваяСтрока.Размер    =    Элемент;
                                         ТзНоваяСтрока.Цвет    =       Характеристика;
                                         //ТзНоваяСтрока.цена =  ВернутьЦену(Номенклатура,Свойство.Объект , тт.Объект.ВестиУчетПоХарактеристикам);
                                         Для каждого СтрЦена из цены цикл
                                             Если СтрЦена.Характеристика = Характеристика и СтрЦена.Номенклатура = Номенклатура тогда
                                                 ТзНоваяСтрока.цена = СтрЦена.цена;
                                                 КонецЕсли;
                                         КонецЦикла;
                                        КонецЦикла;
                                КонецЕсли;
                                КонецЕсли;
                        КонецЦикла;
                        Если НЕ ЕстьЦвета Тогда
                                МассивРазмеров = РазложитьСтрокуВМассивПодстрок(РАзмерныйРяд,"-");
                                ПолныйМассивРазмеров = ПолучитьПолныйМассивРазмеров(МассивРазмеров);
                        Для каждого Элемент Из ПолныйМассивРазмеров цикл
                                        ТзНоваяСтрока = Тз.Добавить();
                                    ТзНоваяСтрока.КодНоменклатуры                           =       Номенклатура.Код;
                                        ТзНоваяСтрока.НаименованиеНоменклатуры     =   Номенклатура.Наименование;
                                        ТзНоваяСтрока.Размер    =    Элемент;
                                         ТзНоваяСтрока.Цвет    =       "";
                                        //ТзНоваяСтрока.ВестиУчет =  тт.Объект.ВестиУчетПоХарактеристикам;
                                        //ТзНоваяСтрока.цена =  ВернутьЦену(Номенклатура, , тт.Объект.ВестиУчетПоХарактеристикам);
                                       Для каждого СтрЦена из цены цикл
                                             Если  СтрЦена.Номенклатура = Номенклатура тогда
                                                 ТзНоваяСтрока.цена = СтрЦена.цена;
                                                 КонецЕсли;
                                         КонецЦикла;

                        КонецЦикла;
                        КонецЕсли;
                        КонецЕсли;
                КонецЦикла;
      
                //ВЫБОРКА ВСЕХ БЕЗ РАЗМЕРНОГО РЯДА
              
                                        Для каждого Свойство из РезультатЗапроса цикл
                                                ЕстьЦвета = Ложь;
                                                Если ТипЗнч(Свойство.Объект)  = Тип("СправочникСсылка.ХарактеристикиНоменклатуры")
                                                                                тогда
                                                                                //номенклатура = свойство.объект;

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

                                        КонецЕсли;
                        КонецЕсли;
                КонецЦикла;

                //Для каждого Строка из тз цикл
                //      Строка.Цена = ПолучитьЦену(Строка.КодНоменклатуры, Строка.Цвет, Строка.ВестиУчет);
                //КонецЦикла;
                //КОНЕЦ ВЫБОРКИ ВСЕХ БЕЗ РАЗМЕРНОГО РЯДА
         ТабДок = Новый ТабличныйДокумент;
Построитель = Новый ПостроительОтчета;
Построитель.ИсточникДанных = Новый ОписаниеИсточникаДанных(ТЗ);      
Построитель.Вывести(ТабДок);
ОблУдал = ТабДок.Область("R1:R3");
ТабДок.УдалитьОбласть(ОблУдал,ТипСмещенияТабличногоДокумента.ПоВертикали);
Возврат ТабДок;

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

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

      
        //Запрос.УстановитьПараметр("Номенклатура", Номенклатура);
      
        РезультатЗапроса = Запрос.Выполнить();
      
        ВыборкаДетальныеЗаписи = РезультатЗапроса.Выгрузить();
      
  //  Пока ВыборкаДетальныеЗаписи.Следующий() Цикл
  //      цена = ВыборкаДетальныеЗаписи.цена;
  //    КонецЦикла;
  //КонецЕсли;

Возврат ВыборкаДетальныеЗаписи;

КонецФункции
17 Garykom
 
гуру
07.07.15
22:50
(16) это пипипи
18 Лефмихалыч
 
07.07.15
22:51
(15) ах*уееееть ЧЕТЫРЕ?!?!?!?!1111одинодин ААААААЯФШОКЕ
19 breezee
 
07.07.15
22:51
Так, за 30 минут собралось, нет многих цен, в самом начале. Сейчас посмотрю что не так, но все вроде собралось
20 breezee
 
07.07.15
22:52
(18) Так сильно же режет производительность. Или я что-то не понимаю?
21 Лефмихалыч
 
07.07.15
22:52
запросы в цикле - признак дурачины, кстати сказать
22 Лефмихалыч
 
07.07.15
22:54
(16) у меня для тебя плохие новости: в твоем коде нечего чинить. Его надо целиком сжечь дотла и написать заново.
23 Garykom
 
гуру
07.07.15
22:54
(21) иногда без этого ну никак (очень редко)

но в данном случае это признак генетической аномалии
24 KarpovDeniska
 
07.07.15
22:56
Оптимизация алгоритмов 8.1 ......
25 Лефмихалыч
 
07.07.15
22:56
(23) нашел, кого учить...
26 Лефмихалыч
 
07.07.15
22:57
(24) починил
27 KarpovDeniska
 
07.07.15
23:03
(16) цены с отбором по номенклатуре/характеристике получай и вложенные циклы по одним и тем же данным убери. Поможет немного
28 breezee
 
07.07.15
23:08
(27) Спасибо, а как их убрать? Мне же нужен перебор по всем значениям. Я пытался и делать отдельные запросы для получения цен. А отбор по характеристке не всегда нужен, так что я выбираю все цены и потом обрщаюсь к некоторым по характеристике и номенклатуре, а к некоторым просто по номенклатуре
29 Лефмихалыч
 
07.07.15
23:09
(28) засунь всё в запрос
30 Wern
 
07.07.15
23:51
Ну нашлись куча перфекционистов. Да хоть 10 вложенных циклов, лишь бы работало. Думать надо головой, а не оптимизировать все подряд что нужно и что не нужно. Пол часа для одноразового действия, более чем нормально.
31 hhhh
 
08.07.15
00:12
(28) вот эту бредятину убери

              Если тт.Свойство.Код="000000006" И тт.Объект.ВестиУчетПоХарактеристикам И тт.Объект.ПометкаУдаления = ложь тогда  //Свойство РазмерныйРяд


вот так будет быстрее в десятки раз

               "ВЫБРАТЬ
                |       ЗначенияСвойствОбъектов.Объект,
                 |       ВЫРАЗИТЬ(ЗначенияСвойствОбъектов.Объект КАК Справочник.Номенклатура).ВестиУчетПоХарактеристикам КАК ВестиУчетПоХарактеристикам,
                |       ВЫРАЗИТЬ(ЗначенияСвойствОбъектов.Объект КАК Справочник.Номенклатура).ПометкаУдаления КАК ПометкаУдаления,
             |       ЗначенияСвойствОбъектов.Свойство,
                 |       ЗначенияСвойствОбъектов.Свойство.Код КАК СвойствоКод,
              |       ЗначенияСвойствОбъектов.Значение
                |ИЗ
                |       РегистрСведений.ЗначенияСвойствОбъектов КАК ЗначенияСвойствОбъектов";
32 Zamestas
 
08.07.15
00:56
(30) Есть две категории 1С'ников,  которые решают задачи по извлечению данных из БД разными способами - одни циклами, вторые запросами, при этом первые (для примера) могут получить срез последних, а вторые получить те же данные за любой период (т.е. с НачДата По КонДата) одним запросом и использование циклов и таблицы в подобной конструкции считают признаком наличие лишней хромосомы в ДНК. Оно конечно пох, как разовую выгрузку реализовать, но варианты решения показывает, размеры тараканов в голове.
33 Zamestas
 
08.07.15
01:02
*показывают
34 Злопчинский
 
08.07.15
01:35
8-ка - это вообще один бльшой таракан. пруссак.
35 Сниф
 
08.07.15
03:07
(34)ты просто не умеешь его готовить. если бы у тебя было много денег, а у меня - много времени, я бы тебя обучил этому 8 за две недели.
36 Повелитель
 
08.07.15
06:25
(16) Жесть конечно.
Вот это:
Для каждого СтрЦена из цены цикл
                                             Если  СтрЦена.Номенклатура = Номенклатура тогда
                                                 ТзНоваяСтрока.цена = СтрЦена.цена;
                                                 КонецЕсли;
                                         КонецЦикла;
Поменять на типовую, хоть и запрос в цикле, но это лучше чем по циклу по ценам бегать, ускорит этот гомнокод раз в 5 минимум:
ТзНоваяСтрока.цена =
УправлениеЦенообразованием.ПолучитьЦенуНоменклатуры(Номенклатура ,ХарактеристикаНоменклатуры ,
            ТекТипЦен, НаДату, ЕдиницаИзмерения,
            ТекТипЦен.ВалютаЦены, 1, 1);
37 zsergey
 
08.07.15
06:26
(16) жесть!
38 Повелитель
 
08.07.15
06:26
(36) И второй цикл по ценам тоже убрать или сколько их там
39 commdt
 
08.07.15
08:29
Не вникал в конкретную задачу, но вообще от циклов избавляет передача ТЗ в запрос и получение данных по левому соединению. При передаче ТЗ в запрос данные из неё нельзя выбирать непосредственно, сначала нужно создать временную таблицу.
Кроме того, в параметры виртуальной таблицы можно передать, например, массив используемых товаров для дальнейшего ускорения. Разумеется, если это возможно, все условия лучше задавать на самом нижнем уровне: во вложенных запросах, либо параметрах виртуальных таблиц. Типа того:

    ИсходнаяТаб = Документ.Товары.Выгрузить();
    ИсходнаяТаб.Свернуть("Номенклатура,ХарактеристикаНоменклатуры");
    
    Запрос = Новый Запрос;
    Запрос.Текст =
        "ВЫБРАТЬ
        |    ИсходнаяТаб.Номенклатура,
        |    ИсходнаяТаб.ХарактеристикаНоменклатуры
        |ПОМЕСТИТЬ ТабНоменклатуры
        |ИЗ
        |    &ИсходнаяТаб КАК ИсходнаяТаб
        |;
        |
        |////////////////////////////////////////////////////////////////////////////////
        |ВЫБРАТЬ
        |    ТабНоменклатуры.Номенклатура,
        |    ТабНоменклатуры.ХарактеристикаНоменклатуры,
        |    ЦеныНоменклатурыСрезПоследних.Цена,
        |    ЦеныНоменклатурыСрезПоследних.Валюта
        |ИЗ
        |    ТабНоменклатуры КАК ТабНоменклатуры
        |        ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.ЦеныНоменклатуры.СрезПоследних(
        |                &Дата,
        |                ТипЦен = &ТипЦен
        |                    И Номенклатура В (&Номенклатура)) КАК ЦеныНоменклатурыСрезПоследних
        |        ПО ТабНоменклатуры.Номенклатура = ЦеныНоменклатурыСрезПоследних.Номенклатура
        |            И ТабНоменклатуры.ХарактеристикаНоменклатуры = ЦеныНоменклатурыСрезПоследних.ХарактеристикаНоменклатуры
        |;
        |
        |////////////////////////////////////////////////////////////////////////////////
        |УНИЧТОЖИТЬ ТабДанных";
        
    Запрос.УстановитьПараметр("ТипЦен", ТипЦен);
    Запрос.УстановитьПараметр("Дата", Дата);
    Запрос.УстановитьПараметр("Номенклатура", ИсходнаяТаб.ВыгрузитьКолонку("Номенклатура"));
    Запрос.УстановитьПараметр("ИсходнаяТаб", ИсходнаяТаб);
    
    Результат = Запрос.Выполнить().Выгрузить();

И - да, не забывайте удалять временные таблицы.
40 Лефмихалыч
 
08.07.15
08:33
+(32) бело бы "пох", ветки бы не было. Метод "пох, как - одноразово, же" дает ровно вот то, что в сабже - оно тормозит и делает не то, что надо, сроки прошли, задача не решена.
41 ХардHard
 
08.07.15
08:40
(0) Не знаю было или нет. Вместо запроса в цикле можно формировать текст запроса в цикле , это более лучший результат часто дает. Иногда крашит все к чертям %).
По-любому с умом надо подходить к этому.
Компьютеры — прекрасное средство для решения проблем, которых до их появления не было.