Имя: Пароль:
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
а новые контрагенты не создаются ибо всё подгрузилось через КД. надо было только договора подгрузить.