Имя: Пароль:
1C
1С v8
Что быстрее? НайтиПоРеквизиту или Запрос?
0 Кокос
 
22.02.13
16:15
Сабж. Надо подгрузить из экселя один реквизит в мульон договоров БП20.
1 Aswed
 
22.02.13
16:17
Запрос
2 MSII
 
22.02.13
16:18
Прочитать значения реквизитов из файла, запихать массив и одним запросом выбрать все договоры.
3 Ksandr
 
22.02.13
16:18
Только не запрос в цикле :)
4 MSII
 
22.02.13
16:20
(3) А НайтиПоРеквизиту - это как раз оно. Так что при всем богатстве выбора запросу альтернативы нет.
5 EvgeniuXP
 
22.02.13
16:23
(0) а что быстрее: установить отбор использовать() или установить параметр в динамическом списке? :)
6 Кокос
 
22.02.13
16:26
&НаСервере
Процедура ЗагрузитьКодыМакономиНаСервере(КаталогИБ)
   ИмяФайла=КаталогИБ+"\..\..\..\romix_test1.txt";
   fso=Новый COMОбъект("Scripting.FileSystemObject");
   file=fso.OpenTextFile(ИмяФайла, 1, 0, 0); //Открываем файл в режиме "только чтение"
   Запрос = Новый Запрос;
   ЗАпрос.Текст = "ВЫБРАТЬ
                  |    ДоговорыКонтрагентов.Ссылка
                  |ИЗ
                  |    Справочник.ДоговорыКонтрагентов КАК ДоговорыКонтрагентов
                  |ГДЕ
                  |    ДоговорыКонтрагентов.Владелец.ВнешнийКод = &ВнКод
                  |    И ДоговорыКонтрагентов.Наименование = &Имя";
   стр=file.ReadLine(); ВнешнийКод ="";Договор="";КодМакономи="";
   Пока file.AtEndOfStream=0 Цикл
     стр=file.ReadLine();
     Поз = найти(Стр,";");
     Если Поз >1 Тогда
         ВнешнийКод = СокрЛП(Лев(Стр,Поз-1));
     Иначе
         Продолжить;
     КонецЕсли;
     ОстатокСтр = Сред(Стр,Поз+1);
     Поз = найти(ОстатокСтр,";");
     Если Поз >1 Тогда                          
         Договор = СокрЛП(Лев(ОстатокСтр,Поз-1));
     Иначе
         Продолжить;
     КонецЕсли;      
     ОстатокСтр = Сред(ОстатокСтр,Поз+1);
     Поз = найти(ОстатокСтр,";");
     Если Поз >1 Тогда
         КодМакономи = СокрЛП(Лев(ОстатокСтр,Поз-1));
     Иначе
         Продолжить;
     КонецЕсли;
     Запрос.УстановитьПараметр("ВнКод",ВнешнийКод);
     Запрос.УстановитьПараметр("Наименование",Договор);
     ТДог = Запрос.Выполнить().Выгрузить();
     Если ТДог.Количество() > 0 Тогда
         оДок = ТДог[0].ссылка.ПолучитьОбъект();
         оДок.КодМакономи = КодМакономи;
         оДок.Записать();
     Иначе
         сКонтрагент = Справочники.Контрагенты.НайтиПоРеквизиту("ВнешнийКод",ВнешнийКод);
       оВлад = Неопределено;
       Если сКонтрагент.Пустая() Тогда
           Продолжить;
       КонецЕсли;
       оДоговор = Справочники.ДоговорыКонтрагентов.СоздатьЭлемент();
       оДоговор.Наименование = Договор;
       оДоговор.Владелец = сКонтрагент;
       оДоговор.КодМакономи = КодМакономи;
       оДоговор.Организация = ЭтаФорма.Организация.Ссылка;
       оДоговор.ВалютаВзаиморасчетов = Константы.ВалютаРегламентированногоУчета.Получить().Ссылка;
       оДоговор.ВидДоговора = Перечисления.ВидыДоговоровКонтрагентов.СПокупателем;
       оДоговор.Записать();
     КонецЕсли;
     //Сообщить(стр);
   КонецЦикла;
   file.Close();

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

&НаКлиенте
Процедура Вып(Команда)
   ЗагрузитьКодыМакономиНаСервере(НСтр(СтрокаСоединенияИнформационнойБазы(), "File"));
КонецПроцедуры

щаз буду тестировать на 10 записях. а потом на ночь оставлю...
7 Кокос
 
22.02.13
16:27
а такое запросом без перебора можно сделать?:)
8 Reset
 
22.02.13
16:30
етить, хотя бы
       оДоговор.Организация = ЭтаФорма.Организация.Ссылка;
       оДоговор.ВалютаВзаиморасчетов = Константы.ВалютаРегламентированногоУчета.Получить().Ссылка;
из цикла вытащи и .ссыка убери tt
9 Reset
 
22.02.13
16:31
точнее второе вытащить, а первое просто точку убрать
10 Кокос
 
22.02.13
16:31
(8) .ссыка у меня это привычка :))
11 rs_trade
 
22.02.13
16:32
Стесняюсь спрсить. А НайтиПоРеквизиту это не запрос?
12 EvgeniuXP
 
22.02.13
16:32
(0) запрос в 8.1 выполняется за 8 секунд, тот же самый запрос на 8.3 - выполняется минуту :) 8.3 вывод: самая ужасная платформа :)
13 Reset
 
22.02.13
16:32
(7) Сначала все "Договор"(где строковое имя) в таблицу вытащить, а потом 1 запрос
14 Classic
 
22.02.13
16:32
(0)
Найти по реквизиту - вообще штука стремная при больших наборах данных. Лучше уже извращаться с параллельным обходом
16 H A D G E H O G s
 
22.02.13
16:34
(12) Байки.
17 EvgeniuXP
 
22.02.13
16:37
(15) нет не байки, возьми один документ и выбери у него два реквизита и ссылку, тут же объедини с другим видом документа, выбери те же два реквизита и свою ссылку, потом сгруппируй получившийся результат по двум реквизитам и выведи итог в дерево.

Запрос1

Объединить

Запрос 2

ИТОГИ

через СКД те же 8 секунд, через консоль - минута, может чуть более.
18 EvgeniuXP
 
22.02.13
16:38
(17) выведи иерархию всю с итогами.
19 ВалераОшкин
 
22.02.13
16:39
(0) НайтиПоРеквизиту быстрее, если ищешь не в цикле.

Если надо искать в цикле, лучше пиши запрос, который обработает весь свод информации без цикла.
20 Ksandr
 
22.02.13
16:39
Кокос похоже romix, но почему-то Кокос :)
21 Кокос
 
22.02.13
16:39
(20) это я из книги знаний мисты взял код :)
22 H A D G E H O G s
 
22.02.13
16:40
(17) Делать мне больше нечего, повторяя ваши глупые тесты.
23 H A D G E H O G s
 
22.02.13
16:40
Как ни удивительно, но ВалераОшкин сегодня прав, именно в ситуации (19).
24 rs_trade
 
22.02.13
16:41
(19) <<НайтиПоРеквизиту быстрее, если ищешь не в цикле.

А почему быстрее?
25 Кокос
 
22.02.13
16:41
26 Кокос
 
22.02.13
16:42
мне не просто искать нужно. мне еще нужно "если нет то создать" :)
27 GANR
 
22.02.13
16:42
(0) Ставим вопрос по другому: план запроса для НайтиПоРеквизиту и Запрос какой? Операция SEEK быстрее SCAN. А вообще можно мини-конфигурашку сделать, рандомом генерировать 20000-50000 элементов справочника и проверить.
28 ВалераОшкин
 
22.02.13
16:44
(24) Потому, что НайтиПоРеквизиту это встроенный запрос платформы
29 Кокос
 
22.02.13
16:45
(27) = > (6) 500 000 строк :)
30 rs_trade
 
22.02.13
16:46
(28) Ого. А чем встроенный запрос лучше не встроенного? Почему он быстрее будет искать?
31 GANR
 
22.02.13
16:47
(29) А убрать запрос из цикла нельзя??? Выборка.Сбросить() с Выборка.НайтиСледующий() пошустрее существенно.
32 Ksandr
 
22.02.13
16:47
Значение уникально?
33 Кокос
 
22.02.13
16:48
(31) а с параметрами как быть?:)
34 Кокос
 
22.02.13
16:50
(32) уникален ВнешнийКод и ИмяДоговора. Вообще это номер счета. а у них договор = счет.
35 ВалераОшкин
 
22.02.13
16:52
(30) Сам подумай, все тебе разжевывать надо :)
36 Кокос
 
22.02.13
16:52
я просто через КД грузил и он у меня при загрузке всех договоров валился. я поставил договора по ссылке. все загрузил. теперь подгружаю левым способом через текстовик сами договора. молюсь чтобы это все влезло в файловую БП30
37 ВалераОшкин
 
22.02.13
16:54
(23) Спасибо, я буду гордиться, что сам H A D G E H O G s меня похвалил :0)
38 Ksandr
 
22.02.13
17:02
Вот Вам почва для размышлений
https://dl.dropbox.com/u/39913355/Снимок.PNG

1. Поиск по реквизиту
2. Запрос по реквизиту
3. Запрос по массиву значений и поиск по единственному
4. Тоже что и 3, но выгрузка в ТЗ, добавление индекса колонке и поиск
39 GANR
 
22.02.13
17:02
(33) Вот так:
&НаСервере
Процедура ЗагрузитьКодыМакономиНаСервере(КаталогИБ)
   ИмяФайла=КаталогИБ+"\..\..\..\romix_test1.txt";
   fso=Новый COMОбъект("Scripting.FileSystemObject");
   file=fso.OpenTextFile(ИмяФайла, 1, 0, 0); //Открываем файл в режиме "только чтение"

   Запрос = Новый Запрос;
   ЗАпрос.Текст = "ВЫБРАТЬ
                  |    ДоговорыКонтрагентов.Ссылка КАК Ссылка,
          |    ДоговорыКонтрагентов.Владелец.ВнешнийКод КАК ВнешнийКод,
                  |    ДоговорыКонтрагентов.Наименование КАК Наименование
                  |ИЗ
                  |    Справочник.ДоговорыКонтрагентов КАК ДоговорыКонтрагентов";

   ВыборкаДоговоры = Запрос.Выполнить().Выбрать();
   ОтборДоговоры = Новый Структура("ВнешнийКод, Наименование");

   Запрос = Новый Запрос;
   ЗАпрос.Текст = "ВЫБРАТЬ
                  |    Контрагенты.Ссылка,
          |    Контрагенты.ВнешнийКод КАК ВнешнийКод
                  |ИЗ
                  |    Справочник.Контрагенты КАК Контрагенты";
   ВыборкаКонтрагенты = Запрос.Выполнить().Выбрать();
   ОтборКонтрагент = Новый Структура("ВнешнийКод");

   стр=file.ReadLine(); ВнешнийКод ="";Договор="";КодМакономи="";
   Пока file.AtEndOfStream=0 Цикл
     стр=file.ReadLine();
     Поз = найти(Стр,";");
     Если Поз >1 Тогда
         ВнешнийКод = СокрЛП(Лев(Стр,Поз-1));
     Иначе
         Продолжить;
     КонецЕсли;
     ОстатокСтр = Сред(Стр,Поз+1);
     Поз = найти(ОстатокСтр,";");
     Если Поз >1 Тогда                          
         Договор = СокрЛП(Лев(ОстатокСтр,Поз-1));
     Иначе
         Продолжить;
     КонецЕсли;      
     ОстатокСтр = Сред(ОстатокСтр,Поз+1);
     Поз = найти(ОстатокСтр,";");
     Если Поз >1 Тогда
         КодМакономи = СокрЛП(Лев(ОстатокСтр,Поз-1));
     Иначе
         Продолжить;
     КонецЕсли;

     ОтборДоговоры.ВнешнийКод = ВнешнийКод;
     ОтборДоговоры.Наименование = Договор;

     ВыборкаДоговоры.Сбросить();

     Если ВыборкаДоговоры.НайтиСледующий(отборДоговоры) Тогда
         оДок = ВыборкаДоговоры.ссылка.ПолучитьОбъект();
         оДок.КодМакономи = КодМакономи;
         оДок.Записать();
     Иначе

       ВыборкаКонтрагенты.Сбросить();
       ОтборКонтрагент.ВнешнийКод = ВнешнийКод;
       оВлад = Неопределено;

       Если Не ВыборкаКонтрагенты.НайтиСледующий(ОтборКонтрагент) Тогда
           Продолжить;
       Иначе
           сКонтрагент = ВыборкаКонтрагенты.Ссылка;
       КонецЕсли;

       оДоговор = Справочники.ДоговорыКонтрагентов.СоздатьЭлемент();
       оДоговор.Наименование = Договор;
       оДоговор.Владелец = сКонтрагент;
       оДоговор.КодМакономи = КодМакономи;
       оДоговор.Организация = ЭтаФорма.Организация.Ссылка;
       оДоговор.ВалютаВзаиморасчетов = Константы.ВалютаРегламентированногоУчета.Получить().Ссылка;
       оДоговор.ВидДоговора = Перечисления.ВидыДоговоровКонтрагентов.СПокупателем;
       оДоговор.Записать();
     КонецЕсли;
     //Сообщить(стр);

   КонецЦикла;
   file.Close();

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

&НаКлиенте
Процедура Вып(Команда)
   ЗагрузитьКодыМакономиНаСервере(НСтр(СтрокаСоединенияИнформационнойБазы(), "File"));
КонецПроцедуры
40 Кокос
 
22.02.13
17:04
(39) спасибо за урок. Буду теперь всегда так делать. :)
41 ВалераОшкин
 
22.02.13
17:04
(38) в базе, естественно, никто не работает?
42 ВалераОшкин
 
22.02.13
17:05
(39) Это столько буков надо написать, чтобы найти по реквизиту? :)
43 Ksandr
 
22.02.13
17:05
(41) Файловый вариант, никто не работает
44 ВалераОшкин
 
22.02.13
17:06
(43) А нормальные пацаны про файловый вариант и не знают...
45 GANR
 
22.02.13
17:06
(40)+(39) Это Константы.ВалютаРегламентированногоУчета.Получить().Ссылка
и это
Перечисления.ВидыДоговоровКонтрагентов.СПокупателем
являются скрытыми запросами в цикле (см. замер производительности) - их надо за пределами цикла 1 раз получить и подставлять

       оДоговор.ВалютаВзаиморасчетов = пВалютаВзаиморасчетов;
       оДоговор.ВидДоговора = пВидДоговораСПокупателем;
46 ВалераОшкин
 
22.02.13
17:08
+(44) ты так не смеши больше с файловым вариантом и производительностью. Ладно?
47 Ksandr
 
22.02.13
17:14
(46) Расскажи про разницу в относительных измерениях, а я следом выложу скрин клиент-сервер с 20 пользователями онлайн
48 Ksandr
 
22.02.13
17:15
Подсказка - существенные отличия только в одной цифре - в какой?
49 rs_trade
 
22.02.13
17:24
(35) Подумал. Не придумал. Разжуй пожалуйста.
50 Ksandr
 
22.02.13
17:27
в дополнение к (38)
клиент-сервер (32 бита, СУБД MS SQL 2008), 20 пользователей онлайн
https://dl.dropbox.com/u/39913355/Снимок2.PNG
51 EvgeniuXP
 
22.02.13
21:32
(22) тогда не надо утверждать - "Байки" :)
52 GANR
 
23.02.13
11:40
(40) И ещё, в отличии от (6) (39) не найдет созданные в цикле элементы, поэтому при создании нового договора и контрагента их нужно добавлять в кэш (массив, соответствие) и искать их там дальше по ключу ВнешниКод для контрагент и ВнешнийКод + СимволКоторыйНеМожетПрисутствоватьВДоговорИНаименование+Наименование для договоров. Это позволит избежать задвоения.
53 Кокос
 
23.02.13
12:04
(52) ну в данном случае я думаю этого не произойдет. в исходной таблице по определению нет задвоений. А так всё прошло ок. Часа за два загрузилось.
54 Кокос
 
23.02.13
12:04
а новые контрагенты не создаются ибо всё подгрузилось через КД. надо было только договора подгрузить.
Чтобы обнаруживать ошибки, программист должен иметь ум, которому доставляет удовольствие находить изъяны там, где, казалось, царят красота и совершенство. Фредерик Брукс-младший