Вход | Регистрация


1С:Предприятие :: 1С:Предприятие 8 общая

Быстрый перенос данных с ГУИДами

Быстрый перенос данных с ГУИДами
Я
   Lepochkin
 
30.11.17 - 17:28
Всем доброго времени суток.
Есть задача по переносу данных из 1с в sql. Причем в качестве объектов передавать не их человеко читабельные представления в виде кода или наименования а ГУИД объекта.

Если последовательно перебирать выборку и на каждом объекте применять метод XML строка, то получается безумно долго.
Докопался до метода с сериализацией таблицы значений вот таким способом

Функция СериализоватьДанные(мБаза,СтрокиТаблицы)
    #Если Клиент Тогда
        Состояние("Сериализация... ");
    #КонецЕсли    
        
    ЗаписьXML = мБаза.NewObject("ЗаписьXML");
    ЗаписьXML.УстановитьСтроку();
    
    ОбъектXDTO = мБаза.СериализаторXDTO.ЗаписатьXDTO(СтрокиТаблицы);
    мБаза.ФабрикаXDTO.ЗаписатьXML(ЗаписьXML,ОбъектXDTO);
    ХранилищеВСтроке = ЗаписьXML.Закрыть();

    ТекстДок = Новый ТекстовыйДокумент;
    ТекстДок.УстановитьТекст(ХранилищеВСтроке);
    
    ТекстДокНовый = Новый ТекстовыйДокумент;
    
    СтрокаXML = "<Type>xs:string</Type>";
    СтрокаТипXML = "<Value xsi:type="+"""xs:string""";
    Для н = 1 По ТекстДок.КоличествоСтрок() Цикл
        стр = ТекстДок.ПолучитьСтроку(н);
        Если н > 1 и Найти(стр,"http://v8.1c.ru/8.1/data/enterprise/current-config";) > 0 И Найти(стр,"Value") > 0 Тогда
            СимволЗакрыти = Найти(Стр,">");
            НоваяСтрока = СтрокаТипXML + сред(Стр,СимволЗакрыти);
            Стр = НоваяСтрока + Символы.ПС;    
        ИначеЕсли н > 1 и Найти(стр,"http://v8.1c.ru/8.1/data/enterprise/current-config";) > 0 Тогда
            Стр = СтрокаXML + Символы.ПС;    
        КонецЕсли;    
        
        ТекстДокНовый.ДобавитьСтроку(Стр);
    КонецЦикла;
    
    ХранилищеПереработанное = ТекстДокНовый.ПолучитьТекст();
    ЧтениеXML = Новый ЧтениеXML;
    ЧтениеXML.УстановитьСтроку(ХранилищеПереработанное);
    ТЗ = СериализаторXDTO.ПрочитатьXML(ЧтениеXML);
    возврат ТЗ;
КонецФункции

Работает в разы быстрее, но опытным путем установлено, что там нормально работает только на таблицах, в которых содержится 1000 строк или меньше. Потому приходится обходить выборку и формировать маленькие таблички по 1000 строк. Этот метод все равно быстрее, чем первый примерно в 8 раз. В минуту грузим 10000 записей.

Замер производительность показывает, что 60 времени уходить на операцию заполнения значений строки таблицы значений
   НСтр = СтрокиТаблицы.Добавить();
   ЗаполнитьЗначенияСвойств(НСтр,Выборка);

Хотелось бы еще ускорить процесс но уже не знаю куда копнуть.
Подскажите какие еще могут быть варианты быстрого получения ГУИДов или какой-нибудь хитрый способ разбиения результатов запроса на несколько маленьких табличек. Вариант выгрузить в таблицу значений все, потом пронумеровать и делать выборку из нее по частям исходя из номера пробовал. Выходит дольше.

Хочу скорости )) Предложите плиз какие-нибудь варианты
 
 
   Ёпрст
 
1 - 30.11.17 - 17:32
(0) а чего, взять гуид объекта сразу с таблички в скуле и переписать куда надо, не вариант ?
   Lepochkin
 
2 - 30.11.17 - 17:33
Я бы взял, да найти не могу...
   Ёпрст
 
3 - 30.11.17 - 17:33
т.е берешь _IDRRef из таблички _Document*** и инсертишь куды те там надо
   Lepochkin
 
4 - 30.11.17 - 17:33
Он же ведь там в другом виде хранится
   Ёпрст
 
5 - 30.11.17 - 17:34
(2) файловая что ле ?
   Ёпрст
 
6 - 30.11.17 - 17:34
(4) в том же самом и хранится, в виде гуида
   Lepochkin
 
7 - 30.11.17 - 17:34
Нее... Скуль
   Ёпрст
 
8 - 30.11.17 - 17:34
просто в 1с "чутка" преобразован
   Lepochkin
 
9 - 30.11.17 - 17:36
мне нужно ваот так - 00072dd6-f326-11e4-8936-e4115be3c6a9
а в скуле вот так - 0x0000FE44C60311E3964FE4115BE3C6A9
   Ёпрст
 
10 - 30.11.17 - 17:37
Так что, 1с тут вообще не нужен, ну разве что запрос по ado там запустить
 
 Рекламное место пустует
   Ёпрст
 
11 - 30.11.17 - 17:37
(9) и че ?
:)
   Вафель
 
12 - 30.11.17 - 17:37
тебе в строку гуид нужно преобразовать?
   Lepochkin
 
13 - 30.11.17 - 17:37
Я понимаю, что преобразован. И даже знаю как из одного другой получить, только для этого выборку обходит надо будет опять. И по скорости проигрышь будет
   Ёпрст
 
14 - 30.11.17 - 17:37
преобразовать гуид в уид можно же, в скуле тупо хранимкой
   Ёпрст
 
15 - 30.11.17 - 17:38
(13) ?
   Lepochkin
 
16 - 30.11.17 - 17:42
Хранимка штука конечно интересная, но боюсь моем случае не подойтет.
Мне нужно с разных конфигураций данные собирать, причем где-то в чистом виде, где-то результаты запросов для отчетов... И под каждую базу еще и преобразования делать... Тяжеловато будет
   Ёпрст
 
17 - 30.11.17 - 17:43
(16) Ну, тогда выбирай - тебе либо шашечки, либо ехать.
   Lepochkin
 
18 - 30.11.17 - 17:48
Если "ехать" - то при добавлении любого объекта мне потрудиться не кисло надо будет...
Если "шашечки" - то я отдал инструмент и забыл...
Мы ж ленивые люди...
Но хочется что бы побыстрее было ))
   Ёпрст
 
19 - 30.11.17 - 17:50
(18) Что именно вкладывается в понятие "потрудится" ? Ты же имена таблиц и  полей, не руками будешь добавлять в запрос.
   Lepochkin
 
20 - 30.11.17 - 17:57
Что-то плохо у меня картинка складывается...
Мне получается надо будет запрос 1ски конвертнуть в скулевый. Его там исполнить. Обойти результаты скулевого, преобразовать уид и записать в другую базу...
   Ёпрст
 
21 - 30.11.17 - 17:59
нет, нужно просто выполнить sql запрос который сделает insert into select
   Lepochkin
 
22 - 30.11.17 - 18:09
сейчас это выглядит вот так. http://joxi.ru/ZrJzpoDC1gKxVr
и для пользователя, хоть он и программис хочется что бы так же и оставалось
   Вафель
 
23 - 30.11.17 - 18:15
если через скд делать, то можно напрямую ссылки в гуиды переводить
   Вафель
 
24 - 30.11.17 - 18:17
   Lepochkin
 
25 - 30.11.17 - 21:32
СКД не прокатит... Рассматривал этот вариант. Нужен универсальный механизм, что бы им дергать из любой базы 1с. А им я получу com объект
   Tateossian
 
26 - 30.11.17 - 21:47
Смотри, перечисляю все доступные методы решения этой задачи:
Вариант1 = ЧислоИзШестнадцатеричнойСтроки("0xabcde");

Вариант2 - используя функцию Новый БуферДвоичныхДанных и сложение по модулю И

Вариант3 = VBScript.RegExp

Вариант4 = самодельный парсер строк.

Выбирай любой)))
   Lepochkin
 
27 - 30.11.17 - 22:41
Вариант4 - это наверное то, что я уже изобразил...
1 и 3 вряд ли будут универсальны.
а вот 2 кажется интересным. завтра посмотрю в его сторону
   Tateossian
 
28 - 01.12.17 - 03:24
(27) Вариант 4 ужасный колхоз.

Пример с вариантом (3 и 2) смотри ниже (он универсален), так как guid формируется по RFC4122 (https://tools.ietf.org/html/rfc4122)

Как оказалось, платформа не может в сдвиг. Пришлось немного подшаманить. В итоге получилось вот так (тут сразу с замером производительности. Сей код (10000 итераций) на толстяке выполняется 1400 мс.

СтрокаГекс = "0123456789ABCDEF";
ГСЧ = Новый ГенераторСлучайныхЧисел;

Старт = ТекущаяУниверсальнаяДатаВМиллисекундах();

Для i = 0 По 9999 Цикл
    
    ГексСтрингУИД="";
    Для j=0 По 31 Цикл
        Рандом = ГСЧ.СлучайноеЧисло(0, 15);
        ГексСтрингУИД=ГексСтрингУИД+Сред(СтрокаГекс, Рандом, 1);    
    КонецЦикла;

    ПБ = ПорядокБайтов.BigEndian;

    УИДБуфер = ПолучитьБуферДвоичныхДанныхИзHexСтроки(ГексСтрингУИД);
    УИДБуфер.ПорядокБайтов = ПБ;

    СтаршиеБиты = УИДБуфер.Прочитать(0, 8);//fst

    МладшиеБиты = УИДБуфер.Прочитать(8, 8);//snd


    Маска5 = Новый БуферДвоичныхДанных(8, ПБ);
    Маска5.ЗаписатьЦелое64(0, 4294967295, ПБ);
    Группа5 = МладшиеБиты.Скопировать();
    Группа5.ЗаписатьПобитовоеИ(0, Маска5);
    СдвинутыйБуфер5 = Новый БуферДвоичныхДанных(16, ПБ);// <<4

    СдвинутыйБуфер5.Записать(4, Группа5);
    СдвинутыйБуфер5 = СдвинутыйБуфер5.Прочитать(8, 8);

    Маска4 = Новый БуферДвоичныхДанных(8, ПБ);
    Маска4.ЗаписатьЦелое64(0, ЧислоИзШестнадцатеричнойСтроки("0xFFFF00000000"), ПБ);
    Группа4 = МладшиеБиты.Скопировать();
    Группа4.ЗаписатьПобитовоеИ(0, Маска4);
    СдвинутыйБуфер4 = Новый БуферДвоичныхДанных(16, ПБ);// >>2

    СдвинутыйБуфер4.Записать(10, Группа4);
    СдвинутыйБуфер4 = СдвинутыйБуфер4.Прочитать(8, 8);

    Маска3 = Новый БуферДвоичныхДанных(8, ПБ);
    Маска3.ЗаписатьЦелое64(0, ЧислоИзШестнадцатеричнойСтроки("0xFFFF000000000000"), ПБ);
    Группа3 = МладшиеБиты.Скопировать();
    Группа3.ЗаписатьПобитовоеИ(0, Маска3);
    СдвинутыйБуфер3 = Новый БуферДвоичныхДанных(16, ПБ);// >>6

    СдвинутыйБуфер3.Записать(14, Группа3);
    СдвинутыйБуфер3 = СдвинутыйБуфер3.Прочитать(8, 8);

    НоваяСтаршаяГруппа = Новый БуферДвоичныхДанных(8, ПБ);
    НоваяСтаршаяГруппа.ЗаписатьПобитовоеИли(0, СдвинутыйБуфер3);
    НоваяСтаршаяГруппа.ЗаписатьПобитовоеИли(0, СдвинутыйБуфер4);
    НоваяСтаршаяГруппа.ЗаписатьПобитовоеИли(0, СдвинутыйБуфер5);

    ПолныйБуфер = Новый БуферДвоичныхДанных(16, ПБ);
    ПолныйБуфер.Записать(0, НоваяСтаршаяГруппа);
    ПолныйБуфер.Записать(8, СтаршиеБиты);

    // 4-2-2-2-6

    //new UUID("00072dd6-f326-11e4-8936-e4115be3c6a9")


    ПравильныйУИД = НРег(
                    ПолучитьHexСтрокуИзБуфераДвоичныхДанных(ПолныйБуфер.Прочитать(0,4)) + "-" +
                    ПолучитьHexСтрокуИзБуфераДвоичныхДанных(ПолныйБуфер.Прочитать(4,2)) + "-" +
                    ПолучитьHexСтрокуИзБуфераДвоичныхДанных(ПолныйБуфер.Прочитать(6,2)) + "-" +
                    ПолучитьHexСтрокуИзБуфераДвоичныхДанных(ПолныйБуфер.Прочитать(8,2)) + "-" +
                    ПолучитьHexСтрокуИзБуфераДвоичныхДанных(ПолныйБуфер.Прочитать(10,6)));

КонецЦикла;

// 


Длительность = ТекущаяУниверсальнаяДатаВМиллисекундах() - Старт;


Что касается твоего замечания насчет "Работает в разы быстрее, но опытным путем установлено, что там нормально работает только на таблицах, в которых содержится 1000 строк или меньше" то тут все просто - сериализатор использует DOM-анализатор, а это значит, что весь XML загружается в оперативную память, а, учитывая то, что у тебя код написан с утечками памяти (хотя бы то, что ты не закрываешь xml-дескрипторы), получаешь обозначенные ограничения. В любом случае, в твоем конкретном примере использование XPath будет куда более эффективнее.
   Lepochkin
 
29 - 01.12.17 - 10:34
(28) Не очень понял как этот код применим для меня.
Объясните на пальцах плиз. Есть выборка из базы 1с, к которой я подключен com соединениям. Выборка следующая

Выборка.Ссылка - com объект (здесь должен быть ГУИД)
Выборка.Наименование - строка
Выборка.Код - Число

Данные по этой выборке я должен вставить в sql базу.
   Tateossian
 
30 - 01.12.17 - 10:40
(29)  Ты о чем спрашиваешь в посте?
   Lepochkin
 
31 - 01.12.17 - 10:44
Изначальная задача. Есть N баз 1с, нужно создать универсальный инструмент по выгрузке данных из них в базу SQL.
Далее я описывал свое решение в поисках его оптимизации
   Вафель
 
32 - 01.12.17 - 10:45
скд можно и в чужой базе выполнить
   Вафель
 
33 - 01.12.17 - 10:46
схему собирать ручками
 
 
   Вафель
 
34 - 01.12.17 - 10:46
Большой плюс будет, что не нужно будет ссылки возвращать, а сразу строки
   Tateossian
 
35 - 01.12.17 - 10:52
(29) Вот это ты к чему написал?
«мне нужно ваот так - 00072dd6-f326-11e4-8936-e4115be3c6a9
а в скуле вот так - 0x0000FE44C60311E3964FE4115BE3C6A

Напиши, пример guida и его xml-представления 1С любого справочника.
   Вафель
 
36 - 01.12.17 - 10:53
(35) Тут вопрос: как из языка 1с перевести в язык скл? свой парсер писать. Слишком сложная задача
   Lepochkin
 
37 - 01.12.17 - 10:54
(35) Это была часть обсуждения. Задачу я уже озвучил.
(33) Схему раками пособирать - неплохая идея... Попробую
   Ц_У
 
38 - 01.12.17 - 10:55
(37) раками не надо, итак все через них.. :)
   Tateossian
 
39 - 01.12.17 - 10:58
(37) Вы пример не прислали, какой - я написал.
   Tateossian
 
40 - 01.12.17 - 11:02
Зачем вы храните во внешней базе ссылку как nchar(36)? Если это тип binary(16)?
   Ёпрст
 
41 - 01.12.17 - 11:03
(31) как ты данные из 1с тащишь ?
   Tateossian
 
42 - 01.12.17 - 11:05
(36)  Это не сложно, но, думаю, ОПу это не поможет.
   Ёпрст
 
43 - 01.12.17 - 11:05
не понимаю, в чем у тебя сложность сразу вытащить sql запросом данные из 1с и инсёртить их в твою табличку.
Так же, динамически собираешь текст запроса и привет
   Lepochkin
 
44 - 01.12.17 - 11:32
(40) У меня помимо баз 1с есть еще и wms система, откуда тоже данные тащить надо, а ключами по той же номенклатуре являются строковые ГУИДы... Потому вот такая и заморочка
   Lepochkin
 
45 - 01.12.17 - 11:33
Под ГУИДом я понимаю уникальный идентификатор вот такого вида 00072dd6-f326-11e4-8936-e4115be3c6a9
   Tateossian
 
46 - 01.12.17 - 12:08
(45) Тогда понятно. Колхоз, в общем.
   Tateossian
 
47 - 01.12.17 - 12:12
(45) Я бы рассказал про представления (VIEW) и синонимы (SYNONIM). Но порекомендую почитать книжки по MS SQL или не трогать сервер.
   Lepochkin
 
48 - 01.12.17 - 12:26
(47) Почитать - это безусловно беспроигрышное предложение
   FIXXXL
 
49 - 01.12.17 - 12:32
(0) сделать общий реквизит "ГУИД" и один раз его заполнить по всем базам? плюс подписка на новые ссылочные элементы ПриЗаписи
 
 Рекламное место пустует
   Lepochkin
 
50 - 01.12.17 - 12:39
(49) Думал над этим вариантом, но тогда придется вносить изменения в конфигурации, а хочется сделать без этого
   Tateossian
 
51 - 01.12.17 - 12:52
(48) Разумеется, еще и разобраться. Задумайся: почему в 1С ссылки хранятся как binary(16) в 1С, а в вашей там какой-то WMS (?) системе как строки. Они, поди, хоть в индексе?

Если бы ты знал, что такое view, то знал бы, что в sql можно сделать хоть сколько угодно view, а в 1С это подключить как внешний источник. А еще тот код, что я тебе написал выше, прекрасно работает в sql и поместится в одну строчку как скалярный оператор - надо его только правильно переписать.
   Lepochkin
 
52 - 01.12.17 - 14:22
(49) Ты не поверишь, но вьюхи использую в полный рост. И как внешние источники и в отчетах. Причем вьюхи на скулевые и орокловые. Так что сильно не выделвайся. И почему ключи не строковые тоже все студенты знают. Строковый ГУИД используется при интеграции и от него мне не убежать. Вот и думаю как все сделать оптимально
   Вафель
 
53 - 01.12.17 - 15:22
(51) предлагаешь выкинуть эту wms и написать свою?
   Lepochkin
 
54 - 01.12.17 - 15:41
Подтупливаю что-то в пятницу вечером.
Вот это выражение Тип("НаборДанныхЗапросСхемыКомпоновкиДанных") через com как получить?
   Lepochkin
 
55 - 01.12.17 - 15:42
Схему легко...
СхемаКомпановки = мБаза.NewObject("СхемаКомпоновкиДанных");
А тип что-то туплю...
   Lepochkin
 
56 - 01.12.17 - 17:42
Для истории
Функция ВернутьТипВнешнейБазы(мБаза,СтрокаТипа)
    Описатель = мБаза.NewObject("ОписаниеТипов",СтрокаТипа);
    возврат Описатель.Типы().Получить(0);
КонецФункции
   Адинэснег
 
57 - 04.12.17 - 07:49
а чем УникальныйИдентификатор() плох?
13500 вызовов за 0,14 сек:
https://image.prntscr.com/image/AY0PU48lTYGhVmW-tkq4iQ.png
Процедура ПолучитьТаблицуУИД()
    
    Запрос = Новый Запрос("ВЫБРАТЬ
                          |    РеализацияТоваровУслуг.Ссылка КАК Док,
                          |    РеализацияТоваровУслуг.СуммаДокумента,
                          |    РеализацияТоваровУслуг.Номер
                          |ИЗ
                          |    Документ.РеализацияТоваровУслуг КАК РеализацияТоваровУслуг");
    Таб = Запрос.Выполнить().Выгрузить();
    Таб.Колонки.Добавить("UID");
    Для Каждого Стр Из Таб Цикл
        Стр.UID = Строка(Стр.Док.УникальныйИдентификатор());
    КонецЦикла;    
    
КонецПроцедуры


Список тем форума
Рекламное место пустует  Рекламное место пустует
ВНИМАНИЕ! Если вы потеряли окно ввода сообщения, нажмите Ctrl-F5 или Ctrl-R или кнопку "Обновить" в браузере.
Тема не обновлялась длительное время, и была помечена как архивная. Добавление сообщений невозможно.
Но вы можете создать новую ветку и вам обязательно ответят!
Каждый час на Волшебном форуме бывает более 2000 человек.
Рекламное место пустует