|
Быстрый перенос данных с ГУИДами | ☑ | ||
---|---|---|---|---|
0
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) а чего, взять гуид объекта сразу с таблички в скуле и переписать куда надо, не вариант ?
|
|||
2
Lepochkin
30.11.17
✎
17:33
|
Я бы взял, да найти не могу...
|
|||
3
Ёпрст
30.11.17
✎
17:33
|
т.е берешь _IDRRef из таблички _Document*** и инсертишь куды те там надо
|
|||
4
Lepochkin
30.11.17
✎
17:33
|
Он же ведь там в другом виде хранится
|
|||
5
Ёпрст
30.11.17
✎
17:34
|
(2) файловая что ле ?
|
|||
6
Ёпрст
30.11.17
✎
17:34
|
(4) в том же самом и хранится, в виде гуида
|
|||
7
Lepochkin
30.11.17
✎
17:34
|
Нее... Скуль
|
|||
8
Ёпрст
30.11.17
✎
17:34
|
просто в 1с "чутка" преобразован
|
|||
9
Lepochkin
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
|
тебе в строку гуид нужно преобразовать?
|
|||
13
Lepochkin
30.11.17
✎
17:37
|
Я понимаю, что преобразован. И даже знаю как из одного другой получить, только для этого выборку обходит надо будет опять. И по скорости проигрышь будет
|
|||
14
Ёпрст
30.11.17
✎
17:37
|
преобразовать гуид в уид можно же, в скуле тупо хранимкой
|
|||
15
Ёпрст
30.11.17
✎
17:38
|
(13) ?
|
|||
16
Lepochkin
30.11.17
✎
17:42
|
Хранимка штука конечно интересная, но боюсь моем случае не подойтет.
Мне нужно с разных конфигураций данные собирать, причем где-то в чистом виде, где-то результаты запросов для отчетов... И под каждую базу еще и преобразования делать... Тяжеловато будет |
|||
17
Ёпрст
30.11.17
✎
17:43
|
(16) Ну, тогда выбирай - тебе либо шашечки, либо ехать.
|
|||
18
Lepochkin
30.11.17
✎
17:48
|
Если "ехать" - то при добавлении любого объекта мне потрудиться не кисло надо будет...
Если "шашечки" - то я отдал инструмент и забыл... Мы ж ленивые люди... Но хочется что бы побыстрее было )) |
|||
19
Ёпрст
30.11.17
✎
17:50
|
(18) Что именно вкладывается в понятие "потрудится" ? Ты же имена таблиц и полей, не руками будешь добавлять в запрос.
|
|||
20
Lepochkin
30.11.17
✎
17:57
|
Что-то плохо у меня картинка складывается...
Мне получается надо будет запрос 1ски конвертнуть в скулевый. Его там исполнить. Обойти результаты скулевого, преобразовать уид и записать в другую базу... |
|||
21
Ёпрст
30.11.17
✎
17:59
|
нет, нужно просто выполнить sql запрос который сделает insert into select
|
|||
22
Lepochkin
30.11.17
✎
18:09
|
сейчас это выглядит вот так. http://joxi.ru/ZrJzpoDC1gKxVr
и для пользователя, хоть он и программис хочется что бы так же и оставалось |
|||
23
Вафель
30.11.17
✎
18:15
|
если через скд делать, то можно напрямую ссылки в гуиды переводить
|
|||
24
Вафель
30.11.17
✎
18:17
|
||||
25
Lepochkin
30.11.17
✎
21:32
|
СКД не прокатит... Рассматривал этот вариант. Нужен универсальный механизм, что бы им дергать из любой базы 1с. А им я получу com объект
|
|||
26
Tateossian
30.11.17
✎
21:47
|
Смотри, перечисляю все доступные методы решения этой задачи:
Вариант1 = ЧислоИзШестнадцатеричнойСтроки("0xabcde"); Вариант2 - используя функцию Новый БуферДвоичныхДанных и сложение по модулю И Вариант3 = VBScript.RegExp Вариант4 = самодельный парсер строк. Выбирай любой))) |
|||
27
Lepochkin
30.11.17
✎
22:41
|
Вариант4 - это наверное то, что я уже изобразил...
1 и 3 вряд ли будут универсальны. а вот 2 кажется интересным. завтра посмотрю в его сторону |
|||
28
Tateossian
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 будет куда более эффективнее. |
|||
29
Lepochkin
01.12.17
✎
10:34
|
(28) Не очень понял как этот код применим для меня.
Объясните на пальцах плиз. Есть выборка из базы 1с, к которой я подключен com соединениям. Выборка следующая Выборка.Ссылка - com объект (здесь должен быть ГУИД) Выборка.Наименование - строка Выборка.Код - Число Данные по этой выборке я должен вставить в sql базу. |
|||
30
Tateossian
01.12.17
✎
10:40
|
(29) Ты о чем спрашиваешь в посте?
|
|||
31
Lepochkin
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
|
Большой плюс будет, что не нужно будет ссылки возвращать, а сразу строки
|
|||
35
Tateossian
01.12.17
✎
10:52
|
(29) Вот это ты к чему написал?
«мне нужно ваот так - 00072dd6-f326-11e4-8936-e4115be3c6a9 а в скуле вот так - 0x0000FE44C60311E3964FE4115BE3C6A Напиши, пример guida и его xml-представления 1С любого справочника. |
|||
36
Вафель
01.12.17
✎
10:53
|
(35) Тут вопрос: как из языка 1с перевести в язык скл? свой парсер писать. Слишком сложная задача
|
|||
37
Lepochkin
01.12.17
✎
10:54
|
(35) Это была часть обсуждения. Задачу я уже озвучил.
(33) Схему раками пособирать - неплохая идея... Попробую |
|||
38
Ц_У
01.12.17
✎
10:55
|
(37) раками не надо, итак все через них.. :)
|
|||
39
Tateossian
01.12.17
✎
10:58
|
(37) Вы пример не прислали, какой - я написал.
|
|||
40
Tateossian
01.12.17
✎
11:02
|
Зачем вы храните во внешней базе ссылку как nchar(36)? Если это тип binary(16)?
|
|||
41
Ёпрст
01.12.17
✎
11:03
|
(31) как ты данные из 1с тащишь ?
|
|||
42
Tateossian
01.12.17
✎
11:05
|
(36) Это не сложно, но, думаю, ОПу это не поможет.
|
|||
43
Ёпрст
01.12.17
✎
11:05
|
не понимаю, в чем у тебя сложность сразу вытащить sql запросом данные из 1с и инсёртить их в твою табличку.
Так же, динамически собираешь текст запроса и привет |
|||
44
Lepochkin
01.12.17
✎
11:32
|
(40) У меня помимо баз 1с есть еще и wms система, откуда тоже данные тащить надо, а ключами по той же номенклатуре являются строковые ГУИДы... Потому вот такая и заморочка
|
|||
45
Lepochkin
01.12.17
✎
11:33
|
Под ГУИДом я понимаю уникальный идентификатор вот такого вида 00072dd6-f326-11e4-8936-e4115be3c6a9
|
|||
46
Tateossian
01.12.17
✎
12:08
|
(45) Тогда понятно. Колхоз, в общем.
|
|||
47
Tateossian
01.12.17
✎
12:12
|
(45) Я бы рассказал про представления (VIEW) и синонимы (SYNONIM). Но порекомендую почитать книжки по MS SQL или не трогать сервер.
|
|||
48
Lepochkin
01.12.17
✎
12:26
|
(47) Почитать - это безусловно беспроигрышное предложение
|
|||
49
FIXXXL
01.12.17
✎
12:32
|
(0) сделать общий реквизит "ГУИД" и один раз его заполнить по всем базам? плюс подписка на новые ссылочные элементы ПриЗаписи
|
|||
50
Lepochkin
01.12.17
✎
12:39
|
(49) Думал над этим вариантом, но тогда придется вносить изменения в конфигурации, а хочется сделать без этого
|
|||
51
Tateossian
01.12.17
✎
12:52
|
(48) Разумеется, еще и разобраться. Задумайся: почему в 1С ссылки хранятся как binary(16) в 1С, а в вашей там какой-то WMS (?) системе как строки. Они, поди, хоть в индексе?
Если бы ты знал, что такое view, то знал бы, что в sql можно сделать хоть сколько угодно view, а в 1С это подключить как внешний источник. А еще тот код, что я тебе написал выше, прекрасно работает в sql и поместится в одну строчку как скалярный оператор - надо его только правильно переписать. |
|||
52
Lepochkin
01.12.17
✎
14:22
|
(49) Ты не поверишь, но вьюхи использую в полный рост. И как внешние источники и в отчетах. Причем вьюхи на скулевые и орокловые. Так что сильно не выделвайся. И почему ключи не строковые тоже все студенты знают. Строковый ГУИД используется при интеграции и от него мне не убежать. Вот и думаю как все сделать оптимально
|
|||
53
Вафель
01.12.17
✎
15:22
|
(51) предлагаешь выкинуть эту wms и написать свою?
|
|||
54
Lepochkin
01.12.17
✎
15:41
|
Подтупливаю что-то в пятницу вечером.
Вот это выражение Тип("НаборДанныхЗапросСхемыКомпоновкиДанных") через com как получить? |
|||
55
Lepochkin
01.12.17
✎
15:42
|
Схему легко...
СхемаКомпановки = мБаза.NewObject("СхемаКомпоновкиДанных"); А тип что-то туплю... |
|||
56
Lepochkin
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 = Строка(Стр.Док.УникальныйИдентификатор()); КонецЦикла; КонецПроцедуры |
Форум | Правила | Описание | Объявления | Секции | Поиск | Книга знаний | Вики-миста |