Имя: Пароль:
1C
1С v8
Механизмы платформенной сериализации
0 Tateossian
 
12.02.18
14:31
​Коллеги, всем привет! Это будет пост для размышления и обсуждения следующей проблемы. Мне не нравятся существующий стек технологий интеграции между 1С. Ни XML/JSON/свойTXT. Ни COM не нравится. Разве что веб-сервисы. Но интересуют именно коробочные, нативные решения. А вот почему. Я являюсь разработчиком на J2EE в нагрузку к 1С и там есть такая технология - встроенная сериализация в binary-формате. Почему 1С не сделает такой? Вот ежли брать классические текстовые форматы - они очень много весят. До упаковки в zip. И долго разбираются парсером. Каждый день ввиду специфики приходится грузить в базу 80Гб xml. Он грузится в 16 фоновых заданий и занимает процесс все равно около 1-1,5 часа. А вот такая проблема - я использую свою систему версионирования. Для хранения ссылок используется метод ЗначениеВСтрокуВнутр(); так как это поле нужно для поиска - оно индексируемое, а лимит на строковый индекс - 442 символа, а бывают отборы на 900 и более строк. Ок, для быстрого поиска я юзаю хэш-ключи, удобно многомерные сущности создавать, эти механизмы ускорили проведение расчета себестоимости с 30 до 5 минут. Но у хэша есть обратная проблема - из жэша нельзя получить искомые сущности. Так вот вопрос: как придумать свою компактную систему сериализации, чтобы быстро работала и весила не много. Может есть готовые советы. FastInfoSet не предлагать. Делал через поток в памяти скрестить с zip архиватором, но там не обойтись без вывода в файл, а нужен быстрый способ чтения/записи, без временных файлов. Какие есть варианты?
44 H A D G E H O G s
 
12.02.18
15:27
Но ты можешь расширить альфавит и писать base128 или base256, зная, что у тебя используется только кириллица, тогда строка будет еще короче. Только придется самому писать функцию.
45 Tateossian
 
12.02.18
15:29
(42) Все верно, но не лучше ли заставить работать zip архиватор? Короче, переформулирую: как строку закодировать в строку, чтобы она была короче исходной и подвергалась десериализации?
46 Tateossian
 
12.02.18
15:29
(44) Не вопрос. Есть предположение, что это будет работать очень универсально и быстро?
47 Tateossian
 
12.02.18
15:31
(41) Вот, у меня такая функция есть для кодирования в хэш

Функция ПолучитьХэш(МассивОбъектов, Знач Метод = "ХешФункция.SHA256", Знач БинарныйФормат = Истина) Экспорт
    Перем ДД, ДДСтрокой;
    Ф = ?(ТипЗнч(Метод) = Тип("Строка"), ПредопределенноеЗначение(Метод), Метод);
    
    Если Не ТипЗнч(МассивОбъектов) = Тип("Массив") Тогда
        ЛокМассив = Новый Массив;
        ЛокМассив.Добавить(МассивОбъектов);
    КонецЕсли;
    ФОбъекты = Новый ФиксированныйМассив(МассивОбъектов);
    
    ПростыеТипы = Новый ОписаниеТипов("Строка,Число,Булево,Дата");
    
    СсылочныеТипы = Новый ОписаниеТипов(Документы.ТипВсеСсылки(), Справочники.ТипВсеСсылки().Типы());
    СсылочныеТипы = Новый ОписаниеТипов(СсылочныеТипы, Перечисления.ТипВсеСсылки().Типы());
    СсылочныеТипы = Новый ОписаниеТипов(СсылочныеТипы, ПланыВидовХарактеристик.ТипВсеСсылки().Типы());
    СсылочныеТипы = Новый ОписаниеТипов(СсылочныеТипы, ПланыСчетов.ТипВсеСсылки().Типы());
    СсылочныеТипы = Новый ОписаниеТипов(СсылочныеТипы, ПланыВидовРасчета.ТипВсеСсылки().Типы());
    СсылочныеТипы = Новый ОписаниеТипов(СсылочныеТипы, БизнесПроцессы.ТипВсеСсылки().Типы());
    СсылочныеТипы = Новый ОписаниеТипов(СсылочныеТипы, БизнесПроцессы.ТипВсеСсылкиТочекМаршрутаБизнесПроцессов().Типы());
    СсылочныеТипы = Новый ОписаниеТипов(СсылочныеТипы, Задачи.ТипВсеСсылки().Типы());
    СсылочныеТипы = Новый ОписаниеТипов(СсылочныеТипы, ПланыОбмена.ТипВсеСсылки().Типы());
    
    Хеширование = Новый ХешированиеДанных(Ф);
    
    Получатели = Новый Массив;
    Получатели.Добавить("XMLСтрока(Эл)");
    Получатели.Добавить("СокращенноДанныеИнформационнойБазыСтрокой(Эл)");
    Получатели.Добавить("ДанныеИнформационнойБазыСтрокой(Эл)");
    Кейс = Новый ФиксированныйМассив(Получатели);
    
    Для Каждого Эл Из ФОбъекты Цикл
        
        Флаг = ЧислоИзДвоичнойСтроки("0b" + ПолучитьФлаг(Не ПростыеТипы.СодержитТип(ТипЗнч(Эл))) +
                ПолучитьФлаг(Не СсылочныеТипы.СодержитТип(ТипЗнч(Эл))))-1;
                
        ТекстовыйИД = Вычислить(Получатели[Флаг]);
        
        Хеширование.Добавить(ТекстовыйИД);            
                
    КонецЦикла;
    
    Если Ф = ХешФункция.CRC32 Тогда
        Буф = Новый БуферДвоичныхДанных(8);
        Буф.ЗаписатьЦелое64(0, Хеширование.ХешСумма);
        ДД = ПолучитьДвоичныеДанныеИзБуфераДвоичныхДанных(Буф);
    Иначе
        ДД = Хеширование.ХешСумма;
    КонецЕсли;
    
    Если Не БинарныйФормат Тогда
        ДДСтрокой = ПолучитьHexСтрокуИзДвоичныхДанных(ДД);
    КонецЕсли;
    
    Возврат ?(БинарныйФормат, ДД, ДДСтрокой);
    
КонецФункции
48 H A D G E H O G s
 
12.02.18
15:38
(47) попробуй сначало base64
49 H A D G E H O G s
 
12.02.18
15:42
sha256 - 32 байта данных. В base64 это будет 43 символа. Или 86 байт данных в виде строки в 1С
50 Fragster
 
гуру
12.02.18
15:46
(49) в utf-8 первые 128 символов таблицы весят 1 байт
51 Fragster
 
гуру
12.02.18
15:49
хотя глянул, в мсскуле не utf-8
52 Tateossian
 
12.02.18
15:52
(51) Только начиная с 16 поддержка UTF реализована
53 H A D G E H O G s
 
12.02.18
15:54
"Капитан сказал большому старине Джо Генри: Здесь, где-то здесь валяется старый молоток.
Возьми этот отбойный молоток и начинай работу!
И пусть он стучит! Стучит! Бьет сталь до дыр!
Пусть стучит, стучит, бьет сталь до дыр!"

Короче, работайте, братья.
54 Tateossian
 
12.02.18
16:02
(53) Смотри, есть такой пример. Ключ регистра в значении стр внутр:
{"#",767bf336-1fa8-4283-be31-fee83ee3c286,{2,{"D",00010101000000},0:00000000000000000000000000000000,2,{"#",a86305d7-b8a1-4312-901f-2ade3efdb351,135:911aee3a33f0f6be4ac5d0f44f4481f9},{"#",39cb59ea-9735-433b-bf1d-8eb9e4b96cc0,153:8ad2005056920edd11deebd9d3a8033e},0,0}}

270 символов

потом его переводим в бин-данные:

ДД = ПолучитьДвоичныеДанныеИзСтроки(СтрокаКлючи);
Выход = Base64Строка(ДД)

На выходе вот это

eyIjIiw3NjdiZjMzNi0xZmE4LTQyODMtYmUzMS1mZWU4M2VlM2MyODYsezIseyJE
IiwwMDAxMDEwMTAwMDAwMH0sMDowMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAw
MDAwMCwyLHsiIyIsYTg2MzA1ZDctYjhhMS00MzEyLTkwMWYtMmFkZTNlZmRiMzUx
LDEzNTo5MTFhZWUzYTMzZjBmNmJlNGFjNWQwZjQ0ZjQ0ODFmOX0seyIjIiwzOWNi
NTllYS05NzM1LTQzM2ItYmYxZC04ZWI5ZTRiOTZjYzAsMTUzOjhhZDIwMDUwNTY5
MjBlZGQxMWRlZWJkOWQzYTgwMzNlfSwwLDB9fQoK

(370 символов) еще больше стало... Но идея у меня была такая же, надо отсюда копать.
55 Вафель
 
12.02.18
16:05
так бы и говорил, что тебе нужна архивация.
Но эта проблема уже решена давно
56 Вафель
 
12.02.18
16:06
Например rar умеет входщие данные брать из stdin
57 ptiz
 
12.02.18
16:06
(0)
Я так делаю, когда надо объекты 1С гонять:

объект 1С (например, структура с кучей таблиц значений) - в хранилище со сжатием:
Хранилище = Новый ХранилищеЗначения(МояСтруктура, Новый СжатиеДанных(9));

хранилище - сериализую:
КомандаСтрокой = СериализоватьЗначениеВXML(Хранилище);


Функция СериализоватьЗначениеВXML(Значение) Экспорт

    ЗаписьXML = Новый ЗаписьXML();
    ЗаписьXML.УстановитьСтроку();
    СериализаторXDTO.ЗаписатьXML(ЗаписьXML, Значение);
    СтрокаXML = ЗаписьXML.Закрыть();    
    
    Возврат СтрокаXML;

КонецФункции // СериализоватьЗначениеВXML()

Ну и потом - обратная операция.
58 Tateossian
 
12.02.18
16:06
(55) Как, расскажи. Вот ищу тебя, друг!
59 Tateossian
 
12.02.18
16:10
(57)

Хранилище = Новый ХранилищеЗначения(Стр, Новый СжатиеДанных(9));

Выход = ТиповыеОтчеты.СериализоватьОбъектXDTO(Хранилище);
Возвращает еще больше строк чем было)) Уж лучше не сериализовать, ибо это тот же бейс64
<ValueStorage xmlns="http://v8.1c.ru/8.1/data/core"; xmlns:xs="http://www.w3.org/2001/XMLSchema"; xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">AgFTS2/0iI3BTqDV67a9oKcN7ZDBTQUxDEQRxy/9JsI1luw4ycbLlQ6oII6dJlZb
GYdfEi0QVuKGRAM8+ziekef1+eni8+NxhPcQwxHCSwhxq5tO5go0e4OcGoM6E0z3
xu48UqvxSHHJ35YcEemaizPijn8Qr9vvqN4qY7ENtHWCzJRAkCakbs4+TblQJC67
EPUV3Zknzqqe+yiGM+e1jaacP44sQ4t4B9m4LEdW0EkGzVU8q9QxMFLhvXVLiAVL
lYRuRmTuamLcGzL7eiTied5v99t/L7/3Es4v</ValueStorage>
60 Tateossian
 
12.02.18
16:12
(56) Представляю теперь потери на запуск стороннего процесса чтобы 100 символов засунуть в архив.

Уж проще переписать функцию архивирования на 1С:)))
61 Вафель
 
12.02.18
16:12
бейс64 много избыточности добавляет. ибо он нечитаемые символы приводит к читаемым. а тебе это не нунжно
62 H A D G E H O G s
 
12.02.18
16:13
(54) Мы до этого говорили о хэше, а не о данных. Откуда у тебя данные вылезли внезапно?
63 Tateossian
 
12.02.18
16:14
(61) Да, идеальный вариант - это хэширование. Но это процесс одностороний... Почему я про зип заговорил, потому как 80Гб файл текста превращается в 100Мб, так как тест очень сильно архивируется. У него избыточность большая.
64 Tateossian
 
12.02.18
16:15
(62) Я говорил о сериализации и десериализации.
65 Вафель
 
12.02.18
16:16
все смешалось в доме Облонских
66 Cyberhawk
 
12.02.18
16:21
(63) А чем тебе уменьшение 80 Гб до 100 Мб не подходит?
67 Tateossian
 
12.02.18
16:21
(65) Не знаю как там у них, а у меня вопрос вполне понятен.
Как сжимать строки не теряя строковой сути?
68 Tateossian
 
12.02.18
16:27
(66) Смотри, есть специальный регистр по версиям. Он в отдельной базе. Он умеет хранить спарвочники, документы и независимые регистры сведений, всю историю. У необъектных сущностей используются ключи, которые состоят из отборов. При сериализации ключ может занимать очень много места, более 900 символов. Хочу сократить это (сейчас строка дробится на две части, 442 символа и все остальное).
И вторая цель - небольшие кусочки данных в прикладном коде использовать в своем формате. Для большого файла это удобно, а для маленьких операций очень затратно открывать zip архиватор.
69 Cyberhawk
 
12.02.18
16:34
(68) Справочник ключей не предлагать? :)
70 Tateossian
 
12.02.18
16:34
(69) Нет, так как там сделано все на третьей нормальной форме на уровне SQL-я.
71 Cyberhawk
 
12.02.18
16:35
"небольшие кусочки данных в прикладном коде использовать в своем формате ... для маленьких операций очень затратно открывать zip архиватор" // Кастую TormozIT в ветку
72 Tateossian
 
12.02.18
16:36
(71) Да, я пользуюсь его инструментами разработчика, крутая штукенция. Там внутри можно хватить удар:) Но сериализация там у него стандартная. Зип+XDTO
73 Cyberhawk
 
12.02.18
16:36
(70) Ты хочешь, чтоб длинную строку можно было сделать короче 900 символов и чтоб обратно из этого упакованного вида еще делать можно было?
74 Tateossian
 
12.02.18
16:36
(73) ДА!
75 Cyberhawk
 
12.02.18
16:37
(74) Но ты же понимаешь, что когда-то этому настанет предел и очередная длинная строка не влезет в ограничение по длине 900? Или такого не предвидится (кодируемые строки не растут со временем)?
76 Tateossian
 
12.02.18
16:38
(73) Почему я так хочу - да потому что zip даже на 400 символов потом весит в пять раз меньше. Но файловую систему использовать для этого кощунственно - у меня кластер по 64Кб. Каждый файл на 10 байт - это минус 64Кб.
77 Cyberhawk
 
12.02.18
16:39
(76) Был тут на форуме кто-то кто строковый ГУИД превращал в ЕАН13 :)
78 Cyberhawk
 
12.02.18
16:40
С потерями что ли тока
79 Cyberhawk
 
12.02.18
16:40
Ну т.е. с коллизиями
80 Tateossian
 
12.02.18
16:40
(75) Да это я взял лимит на индекс в байтах в SQL. В идеале нужна другая сериализация. Самый простой вариант - упакованная XML строка в двоичный данные и потом в виде HEX строки хранимая)
81 Tateossian
 
12.02.18
16:41
(78) Ну zip же может текст и без потерь сжимать. По крайней мере на практике не разу не бывало чтоб xml из zip не прочитался.
82 Cyberhawk
 
12.02.18
16:42
(81) Я так понял что тебя устроит алгоритм zip-сжатия, если он будет выполняться в памяти (без задействования диска)?
83 Tateossian
 
12.02.18
16:42
(82) Да.
84 Cool_Profi
 
12.02.18
16:42
(81) Зип с потерями сжимать не может. по алгоритму
85 Tateossian
 
12.02.18
16:42
(82) Я пытался потоки прикрутить 1С, но там на выход только можно поток, на вход нельзя.
86 Cyberhawk
 
12.02.18
16:44
(85) Нативную компоненту напиши какую-нибудь, на вход ей подаешь строку или поток, она там уже в памяти шуршит и делает. Или нативные компоненты 1С так не умеют (с памятью работать) в силу каких-нибудь архитектурных ограничений?
87 Tateossian
 
12.02.18
16:44
(82) ЗаписьZipФайла (ZipFileWriter)
Методы:

Добавить (Add)
Записать (Write)
Открыть (Open)
ПолучитьДвоичныеДанные (GetBinaryData) <================= вот это

Конструкторы:

На основании имени файла
На основании потока
Формирование неинициализированного объекта

Описание:

Предназначен для записи в ZIP-архив.

Доступность:

Тонкий клиент, сервер, толстый клиент, внешнее соединение.

-----------------

Можно кончено и через средства ОС запускать zip, но это не принесет особого эффекта на небольших операциях, очевидно.
88 H A D G E H O G s
 
12.02.18
16:45
ЗаписьZipФайла (ZipFileWriter)
На основании потока
Синтаксис:

Новый ЗаписьZipФайла(<Поток>, <Пароль>, <Комментарий>, <МетодСжатия>, <УровеньСжатия>, <МетодШифрования>)
89 Buster007
 
12.02.18
16:45
(22) "И очень я считаю красиво." я так понимаю, это ты придумал эту схему?)
90 Tateossian
 
12.02.18
16:45
(88) Тут есть подвох:

ПолучитьДвоичныеДанные(<Пароль>, <Комментарий>, <МетодСжатия>, <УровеньСжатия>, <МетодШифрования>)
Параметры:

<Пароль> (необязательный)

Тип: Строка.
Пароль, который будет назначен архиву.
Если пароль не назначен или является пустой строкой, то шифрование не происходит.
<Комментарий> (необязательный)

Тип: Строка.
Комментарий, описывающий ZIP-файл.
<МетодСжатия> (необязательный)

Тип: МетодСжатияZIP.
Метод сжатия, которым будет сжиматься архив.
Значение по умолчанию: Сжатие.
<УровеньСжатия> (необязательный)

Тип: УровеньСжатияZIP.
Уровень сжатия данных.
Значение по умолчанию: Оптимальный.
<МетодШифрования> (необязательный)

Тип: МетодШифрованияZIP.
Метод шифрования, которым будет зашифрован архив.
Значение по умолчанию: Zip20.
Возвращаемое значение:

Тип: ДвоичныеДанные.

Описание:

Получает ZIP-архив в виде двоичных данных и закрывает файл.
При использовании данного метода объект ЗаписьZipФайла должен быть создан с помощью конструктора без параметров. <=========================
При этом открывать архив явно с помощью метода Открыть не требуется.
При завершении работы данный метод закрывает архив, аналогично методу Записать.
91 H A D G E H O G s
 
12.02.18
16:46
Но я все равно нихера не понимаю, что хочет автор.
Зачем в ключи поиска писать данные?
В ключи поиска нужно писать хэш данных.
Данные нужно писать в неиндексируемые поля.
92 Tateossian
 
12.02.18
16:46
(89) Да, я.
93 Tateossian
 
12.02.18
16:47
(91) А как ты историю по регистру будешь смотреть? Час сидеть, ждать SEEk LOOP когда выполнится? Напоминаю, база с версионированием - одна таблица более 100Гб. Там миллиард строк.
94 H A D G E H O G s
 
12.02.18
16:49
(93) Я ты часто данные смотришь?
95 H A D G E H O G s
 
12.02.18
16:49
(93) Ты имел ввиду key lookup ? Так он быстр.
96 Tateossian
 
12.02.18
16:49
(91) Можно и не писать, для этого есть хэширование. Но хэш ты потом не загрузишь в другую базу.
97 Tateossian
 
12.02.18
16:50
(94) Очень. Все этим пользуются, без него никак. А на ссылку там стоит строка или ЗначениеВСтрокуВнутр()
98 Tateossian
 
12.02.18
16:52
(95) на миллиарде записей нужно полминуты иногда ждать отклика. Но отчет точечный работает быстро. Только по ссылочной сущности.
99 Buster007
 
12.02.18
16:52
(92) подскажи "Ок, для быстрого поиска я юзаю хэш-ключи, удобно многомерные сущности создавать, эти механизмы ускорили проведение расчета себестоимости с 30 до 5 минут" Что за расчет себестоимости? Что за сущности ты объединил?
100 Tateossian
 
12.02.18
16:53
Почему я хочу такое - да потому что у JVM есть и работает это круто. .bin выгрузка занимает десяток-другой байт. Это не прожорливый xml. И потом его можно на другой виртуальной машине распаковать.
101 Tateossian
 
12.02.18
17:03
(99) Смотри, в УПП какой кусок кода есть.
102 Tateossian
 
12.02.18
17:07
(101)
Процедура РассчитатьСписаниеПоСредней(ТаблицаТоваров, ДатаНач, ДатаКон, СтруктураДопПараметров)
    
    // Основное допущение данного метода - игнорирование замкнутой цепочки перемещений между состояниями ("холостого хода"):
    // считаем, что если товар в ходе перемещений снова попал в исходное состояние, то он как бы не перемещался,
    // это движение можно исключить из общего оборота, а стоимость движения принять равной 0. Цепочки перемещений
    // таким образом размыкаются, что позволяет рассчитать стоимости движений, начиная от конца цепочки.
    
    // Получим все состояния для товара, которые он принимал за период в виде таблицы
    //    ---------------------------------------------------------------------------------------------------------------------------------
    // |Состояние 1 (Источник) |Состояние 2 (Приемник)| Перемещаемое количество| Стоимость (нужна для упрощения последующей корректировки)
    
    // Последовательно обходя состояния, выделим контуры (пути, начала и концы которых совпадают)
    // В каждом контуре найдем количество, которое совершило перемещение по замкнутому кругу ("холостой ход"),
    // и уменьшим каждое движение из контура на данное количество.
    // Будем выбирать другие состояния для получения всех контуров и применим к ним то же правило.
    
    // После нахождения контуров в графах перемещений и сокращения "холостого хода" получаем совокупность разомкнутых
    // путей перехода товара между состояниями (остовные деревья). Внутри каждой такой цепочки выполняем расчет.
    // Важно:  в общем случае результат сокращения зависит от последовательности обхода контуров, поэтому
    // для повторяемости результата она должна подчиняться какому-либо правилу (например, чтобы сводные перемещения
    // упорядочивались по возрастанию даты первого перемещения)
    
    // Получим таблицу перемещений, содержащую суммарные перемещения между состояниями
    
    // Получаемая таблица должна содержать колонку "Количество", "Стоимость" и колонки, описывающие старое и новое состояние,
    // причем имена колонок нового состояния заканчиваются на ПрефиксПараметровНовогоСостояния
    ПрефиксПараметровНовогоСостояния="_НовоеСостояние";
    
    Таб = ПолучитьТаблицуПеремещений(ТаблицаТоваров, ДатаНач, ДатаКон, ПрефиксПараметровНовогоСостояния, СтруктураДопПараметров);
    
    СтруктураДопПараметров.Вставить("ТаблицаСписанныхПартийСпецодежды", ПолучитьСтруктруТаблицыСписанныхПартийСпецодежды(СтруктураДопПараметров.Учет));
    
    //1. Приведем переданную таблицу перемещений к требуемому виду:
    // Таблица имеет колонки Источник, Приемник, Количество
    // строка таблицы соответствует перемещению из состояния 1 в состояние 2, перемещения не повторяются.
    
    // Количество колонок без ПрефиксПараметровНовогоСостояния должно быть равно количеству колонок с ПрефиксПараметровНовогоСостояния
    // Сформируем также структуру, которая содержит параметры состояния товара
    СтруктураСостояния = Новый Структура;
    
    МассивСумм = Неопределено;
    СтруктураДопПараметров.Свойство("МассивСумм", МассивСумм);
    
    Если ТипЗнч(МассивСумм) <> Тип("Массив") Тогда
        МассивСумм = Новый Массив;
        МассивСумм.Добавить("Стоимость");
    КонецЕсли;
    
    
    // То же самое, но в соответствии - для удобства поиска
    СоотвСумм = Новый Соответствие;
    
    Для Каждого ЭлементСумм Из МассивСумм Цикл
        СоотвСумм.Вставить(ЭлементСумм, ЭлементСумм);
    КонецЦикла;
    
    Инд=0;
    Пока Инд< Таб.Колонки.Количество() Цикл
        
        Колонка = Таб.Колонки[Инд];
        
        // Имя колонки не совпадает с количеством и колонками стоимости
        Если ВРег(Колонка.Имя) <> ВРег("Количество") Тогда
            
            // Это колонка суммы
            Если СоотвСумм[Колонка.Имя] <> Неопределено Тогда
                Инд = Инд+1;
                Продолжить;
            КонецЕсли;
            
            // Колонки, оканчивающиеся на ПрефиксПараметровНовогоСостояния - правые (новое состояние), им должны соответствовать такие же левые, оканчивающиеся на ПрефиксПараметровНовогоСостояния
            Если Прав(Колонка.Имя, СтрДлина(ПрефиксПараметровНовогоСостояния)) = ПрефиксПараметровНовогоСостояния  Тогда
                ИмяСоответствующейКолонки=Лев(Колонка.Имя, СтрДлина(Колонка.Имя)-СтрДлина(ПрефиксПараметровНовогоСостояния));
                Если Таб.Колонки.Найти(ИмяСоответствующейКолонки)=Неопределено Тогда
                    Таб.Колонки.Добавить(ИмяСоответствующейКолонки, Колонка.ТипЗначения)
                КонецЕсли;
                // И наоборот, колонки, не оканчивающиеся на ПрефиксПараметровНовогоСостояния - левые (новое состояние), им должны соответствовать такие же правые, оканчивающиеся на ПрефиксПараметровНовогоСостояния
            Иначе
                ИмяСоответствующейКолонки=Колонка.Имя+ПрефиксПараметровНовогоСостояния;
                Если Таб.Колонки.Найти(ИмяСоответствующейКолонки)=Неопределено Тогда
                    Таб.Колонки.Добавить(ИмяСоответствующейКолонки, Колонка.ТипЗначения)
                КонецЕсли;
                
                СтруктураСостояния.Вставить(Колонка.Имя);
            КонецЕсли;
        КонецЕсли;
        
        Инд=Инд+1;
    КонецЦикла;
    
    // В таблице перемещений заменим параметры состояний индексами состояний, сами параметры будут храниться в СоотвПараметровСостояний
    
    //*15.01.2017 ******** 1456 {
    //Таб.Колонки.Добавить("Источник", Новый ОписаниеТипов("Число", Новый КвалификаторыЧисла(9,0)));
    //Таб.Колонки.Добавить("Приемник", Новый ОписаниеТипов("Число", Новый КвалификаторыЧисла(9,0)));
    Таб.Колонки.Добавить("Источник", Новый ОписаниеТипов("Число", Новый КвалификаторыЧисла(9,0, ДопустимыйЗнак.Неотрицательный)));
    Таб.Колонки.Добавить("Приемник", Новый ОписаниеТипов("Число", Новый КвалификаторыЧисла(9,0, ДопустимыйЗнак.Неотрицательный)));
    //**15.01.2017 ******** 1456 }

    СоотвПараметровСостояний = Новый Соответствие;
    
    //*15.01.2017 ******** 1456 {
    
    _СоотвПараметровСостояний = Новый Соответствие;
    _СоответствиеНумератор = Новый Соответствие;
    
    Для Каждого Строка Из Таб Цикл
        Хеширование = Новый ХешированиеДанных(ХешФункция.SHA256);
        Для Каждого Элемент Из СтруктураСостояния Цикл
            Если Элемент.Ключ = "ВременнаяРазница" или Элемент.Ключ = "ПостояннаяРазница" тогда
                Продолжить;
            КонецЕсли;
            Если ОбщегоНазначения.ЭтоСсылка(ТипЗнч(Строка[Элемент.Ключ])) Тогда
                Хеширование.Добавить(ИдентификаторСсылки(Строка[Элемент.Ключ]));
            Иначе                
                Хеширование.Добавить(XMLСтрока(Строка[Элемент.Ключ]));
            КонецЕсли;
        КонецЦикла;
        Хэш = Хеширование.ХешСумма;
        
        Если _СоотвПараметровСостояний.Получить(Хэш) = Неопределено Тогда
            ИндексСостояния = _СоотвПараметровСостояний.Количество();
            _СоответствиеНумератор.Вставить(Хэш, ИндексСостояния);
            _СоотвПараметровСостояний.Вставить(Хэш, Строка);
            СтрСост = Новый Структура;
            Для Каждого Элемент Из СтруктураСостояния Цикл
                Если Элемент.Ключ = "ВременнаяРазница" или Элемент.Ключ = "ПостояннаяРазница" тогда
                    Продолжить;
                КонецЕсли;
                СтрСост.Вставить(Элемент.Ключ, Строка[Элемент.Ключ]);
            КонецЦикла;
            СоотвПараметровСостояний.Вставить(ИндексСостояния, СтрСост);
        Иначе
            ИндексСостояния = _СоответствиеНумератор.Получить(Хэш);    
        КонецЕсли;
    
        Строка.Источник = ИндексСостояния;
        
        Хеширование = Новый ХешированиеДанных(ХешФункция.SHA256);
        Для Каждого Элемент Из СтруктураСостояния Цикл
            Если Элемент.Ключ = "ВременнаяРазница" или Элемент.Ключ = "ПостояннаяРазница" тогда
                Продолжить;
            КонецЕсли;
            Если ОбщегоНазначения.ЭтоСсылка(ТипЗнч(Строка[Элемент.Ключ+ПрефиксПараметровНовогоСостояния])) Тогда
                Хеширование.Добавить(ИдентификаторСсылки(Строка[Элемент.Ключ+ПрефиксПараметровНовогоСостояния]));
            Иначе
                Хеширование.Добавить(XMLСтрока(Строка[Элемент.Ключ+ПрефиксПараметровНовогоСостояния]));
            КонецЕсли;
        КонецЦикла;
        Хэш = Хеширование.ХешСумма;
        
        Если _СоотвПараметровСостояний.Получить(Хэш) = Неопределено Тогда
            ИндексСостояния = _СоотвПараметровСостояний.Количество();
            _СоответствиеНумератор.Вставить(Хэш, ИндексСостояния);
            _СоотвПараметровСостояний.Вставить(Хэш, Строка);
            СтрСост = Новый Структура;
            Для Каждого Элемент Из СтруктураСостояния Цикл
                Если Элемент.Ключ = "ВременнаяРазница" или Элемент.Ключ = "ПостояннаяРазница" тогда
                    Продолжить;
                КонецЕсли;
                СтрСост.Вставить(Элемент.Ключ, Строка[Элемент.Ключ+ПрефиксПараметровНовогоСостояния]);
            КонецЦикла;
            СоотвПараметровСостояний.Вставить(ИндексСостояния, СтрСост);
        Иначе
            ИндексСостояния = _СоответствиеНумератор.Получить(Хэш);    
        КонецЕсли;
        
        Строка.Приемник = ИндексСостояния;
        
    КонецЦикла;
    
    //**15.01.2017 ******** 1456 }
    
    ////Для Каждого Строка Из Таб Цикл // поиск выплняется полным перебором
    ////    
    ////    // Состояния-источники
    ////    // Найдем состояние в соответсвии                
    ////    НайденоСостояние=Ложь;
    ////    Для Каждого ЭлементСостояние Из СоотвПараметровСостояний Цикл
    ////        
    ////        НайденоСостояние=Истина;
    ////        Для Каждого Элемент Из СтруктураСостояния Цикл
    ////            
    ////            Если Элемент.Ключ = "ВременнаяРазница" или Элемент.Ключ = "ПостояннаяРазница" тогда
    ////                Продолжить;
    ////            КонецЕсли;
    ////            Если НЕ (ЭлементСостояние.Значение[Элемент.Ключ] = Строка[Элемент.Ключ]) Тогда
    ////                
    ////                НайденоСостояние = Ложь; // состояния различны
    ////                
    ////                Прервать; // дальше можно не проверять
    ////            КонецЕсли;
    ////        КонецЦикла;
    ////        
    ////        Если НайденоСостояние Тогда
    ////            Прервать;
    ////        КонецЕсли;
    ////    КонецЦикла;
    ////    
    ////    Если НайденоСостояние Тогда
    ////        ИндексСостояния = ЭлементСостояние.Ключ;
    ////    Иначе
    ////        // Переносим в соответствие
    ////        СтрСост = Новый Структура;
    ////        Для Каждого Элемент Из СтруктураСостояния Цикл
    ////            Если Элемент.Ключ = "ВременнаяРазница" или Элемент.Ключ = "ПостояннаяРазница" тогда
    ////                Продолжить;
    ////            КонецЕсли;
    ////            СтрСост.Вставить(Элемент.Ключ, Строка[Элемент.Ключ]);
    ////        КонецЦикла;
    ////        
    ////        ИндексСостояния = СоотвПараметровСостояний.Количество();
    ////        СоотвПараметровСостояний.Вставить(ИндексСостояния, СтрСост);
    ////    КонецЕсли;
    ////    
    ////    // Оставим в таблице ссылку на состояние
    ////    Строка.Источник = ИндексСостояния;
    ////    
    ////    
    ////    // То же самое для состояний-приемников
    ////    // Найдем состояние в соответсвии                
    ////    НайденоСостояние=Ложь;
    ////    Для Каждого ЭлементСостояние Из СоотвПараметровСостояний Цикл
    ////        
    ////        НайденоСостояние=Истина;
    ////        Для Каждого Элемент Из СтруктураСостояния Цикл
    ////            
    ////            Если Элемент.Ключ = "ВременнаяРазница" или Элемент.Ключ = "ПостояннаяРазница" тогда
    ////                Продолжить;
    ////            КонецЕсли;
    ////            
    ////            Если НЕ (ЭлементСостояние.Значение[Элемент.Ключ] = Строка[Элемент.Ключ+ПрефиксПараметровНовогоСостояния]) Тогда
    ////                
    ////                НайденоСостояние = Ложь; // состояния различны
    ////                
    ////                Прервать; // дальше можно не проверять
    ////            КонецЕсли;
    ////        КонецЦикла;
    ////        
    ////        Если НайденоСостояние Тогда
    ////            Прервать;
    ////        КонецЕсли;
    ////    КонецЦикла;
    ////    
    ////    Если НайденоСостояние Тогда
    ////        ИндексСостояния = ЭлементСостояние.Ключ;
    ////    Иначе
    ////        // Переносим в соответствие
    ////        СтрСост = Новый Структура;
    ////        Для Каждого Элемент Из СтруктураСостояния Цикл
    ////            СтрСост.Вставить(Элемент.Ключ, Строка[Элемент.Ключ+ПрефиксПараметровНовогоСостояния]);
    ////        КонецЦикла;
    ////        
    ////        ИндексСостояния = СоотвПараметровСостояний.Количество();
    ////        СоотвПараметровСостояний.Вставить(ИндексСостояния, СтрСост);
    ////    КонецЕсли;
    ////    
    ////    // Оставим в таблице ссылку на состояние
    ////    Строка.Приемник = ИндексСостояния;
    ////    
    ////КонецЦикла;
    
    // "Свернем" встречные перемещения: вместо двух перемещений типа 1->2 и 2->1 оставим одно
    // с количеством |Кол12 - Кол21| в направлении большего перемещения.
    
    // Проведем следующее преобразование: повернем пары так, чтобы количество перемещения стало положительным
    Для Каждого Строка Из Таб Цикл
        
        Если Строка.Количество<0 Тогда
            Буф=Строка.Приемник;
            Строка.Приемник = Строка.Источник;
            Строка.Источник = Буф;
            Строка.Количество = - Строка.Количество;
            Для Каждого КолСумма Из МассивСумм Цикл
                Строка[КолСумма] = - Строка[КолСумма];
            КонецЦикла;
        КонецЕсли;
    КонецЦикла;
    
    // "Свертка" встречных перемещений
    Инд=0;
    КолВо = Таб.Количество();
    
    //*15.01.2017 ********  1456 {
    МИсточник = Новый ФиксированныйМассив(Таб.ВыгрузитьКолонку("Источник"));
    МПриемник = Новый ФиксированныйМассив(Таб.ВыгрузитьКолонку("Приемник"));
    МассивТаб = Новый Массив;
    Для Каждого Строка Из Таб Цикл
        МассивТаб.Вставить(Таб.Индекс(Строка), Строка);    
    КонецЦикла;
    ФиксМассив = Новый ФиксированныйМассив(МассивТаб);
    //**15.01.2017 ********1456 }
    
    Пока Инд<КолВо Цикл
        
        Строка = ФиксМассив[Инд];
        
        Инд2 = Инд+1;
        Пока Инд2<КолВо Цикл
            
            //*16.01.2017 ******** 1456 {
            Строка2 = ФиксМассив[Инд2];
            //Строка  = Таб[Инд];
            //**16.01.2017 ********1456 }
            
            // Если найдено соответствующее встречное перемещение
            //*15.01.2017 ******** 1456 {
            //Если Строка.Источник = Строка2.Приемник
            //    И Строка.Приемник = Строка2.Источник Тогда
            Если МИсточник[Инд] = МПриемник[Инд2] И МПриемник[Инд] = МИсточник[Инд2] Тогда
            //**15.01.2017 ******** 1456 }
                
                Если Строка.Количество>Строка2.Количество Тогда
                    УменьшитьНаКоличество = Строка2.Количество;
                Иначе
                    УменьшитьНаКоличество = Строка.Количество;
                КонецЕсли;
                
                Строка.Количество  = Строка.Количество  - УменьшитьНаКоличество;
                Строка2.Количество = Строка2.Количество - УменьшитьНаКоличество;
                
                Для Каждого КолСумма Из МассивСумм Цикл
                    
                    Если Строка.Количество>Строка2.Количество Тогда
                        УменьшитьНаСтоимость = Строка2[КолСумма];
                    Иначе
                        УменьшитьНаСтоимость = Строка[КолСумма];
                    КонецЕсли;
                    
                    // То же самое - со стоимостью
                    Строка[КолСумма]  = Строка[КолСумма]  - УменьшитьНаСтоимость;
                    Строка2[КолСумма] = Строка2[КолСумма]  - УменьшитьНаСтоимость;
                КонецЦикла;
                
                // На этом обход можно прервать: быть не более одной пары встречных перемещений
                Прервать;
                
            Иначе
                Инд2 = Инд2+1;
            КонецЕсли;
            
        КонецЦикла;
        
        Инд = Инд+1;
        
    КонецЦикла;
    
    // Удалим обнулившиеся строки
    // Удаляем только строки со всеми нулевыми суммами и нулевым количеством
    
    КолВо = Таб.Количество();
    Инд=0;
    Пока Инд<КолВо Цикл
        
        Строка  = Таб[Инд];
        
        НеНужноУдалять = Строка.Количество<>0;
        
        Если Не НеНужноУдалять Тогда
        
            Для Каждого КолСумма Из МассивСумм Цикл
                        
                НеНужноУдалять = НеНужноУдалять Или Строка[КолСумма]<>0;
                
            КонецЦикла;
        
        КонецЕсли;
        
        Если Не НеНужноУдалять Тогда
            Таб.Удалить(Строка);
            
            КолВо = КолВо-1;
        Иначе
            Инд=Инд+1;
        КонецЕсли;
        
    КонецЦикла;
    
    // Получили таблицу перемещений в требуемом формате
    ТаблицаПеремещений = Таб;    
    
    // Таблица перемещений содержит несколько несвязанных частей, относящихся к отдельным партиям - строкам таблицы ТаблицаТоваров
    
    // Обработка перемещений: разрыв контуров
    // Получим наборы смежных вершин для каждой вершины
    // Соотв СмежныеВершины Вершина, СмежныеВершины
    
    Источники = Новый Соответствие;
    Приемники = Новый Соответствие;
    МассивНачалДеревьев = Новый Массив;
    
    Для Каждого Строка Из ТаблицаПеремещений Цикл
        
        ПараметрыИсточника = Источники[Строка.Источник];
        Если ПараметрыИсточника = Неопределено Тогда
            СмежныеВершины= Новый Соответствие;
            ПараметрыИсточника = Новый Структура("Пройден, СмежныеВершины", Ложь, СмежныеВершины);
        КонецЕсли;
        
        ПараметрыИсточника.СмежныеВершины.Вставить(Строка.Приемник, ТаблицаПеремещений.Индекс(Строка)); // во вложенной структуре храним смежную вершину и номер строки перемещения
        
        Источники.Вставить(Строка.Источник, ПараметрыИсточника);
        
    КонецЦикла;
    
    // Чтобы рассчитать перемещения, заменим каждый связный граф перемещений его остовным деревом
    // Для этого обойдем их все, найдем и разорвем все контуры по предложенному выше правилу.
    Для Каждого Элемент Из Источники Цикл
        Если НЕ Элемент.Значение.Пройден Тогда // если от вершины еще не строился контур, обрабатываем
            
            //ПройденныеВершины = Новый Соответствие;
            //НомерВершины = Элемент.Ключ;
            //ПройденныеВершины.Вставить(НомерВершины, -1);
            
            ПройденныеВершины = Новый ТаблицаЗначений;
            ПройденныеВершины.Колонки.Добавить("Ключ");
            ПройденныеВершины.Колонки.Добавить("Значение");
            
            НоваяСтрока = ПройденныеВершины.Добавить();
            НоваяСтрока.Ключ = Элемент.Ключ;
            НоваяСтрока.Значение = -1;
            
            НомерВершины = Элемент.Ключ;
            
            РазорватьКонтуры(НомерВершины, Источники, ПройденныеВершины, ТаблицаПеремещений);
        КонецЕсли;
    КонецЦикла;
    
    // После этого таблица содержит незамкнутую последовательность перемещений.
    // Стоимость перемещений с количеством = 0 в таблице тоже должна быть приведена к 0.
    СтСумм = Новый Структура; // структура сумм
    
    Для Каждого Строка Из ТаблицаПеремещений Цикл
        
        Если Строка.Количество=0 Тогда
            
            Для Каждого КолСумма Из МассивСумм Цикл
                СтСумм.Вставить(КолСумма, -Строка[КолСумма]);
            КонецЦикла;
            
            ДобавитьЗаписиПоПеремещению(СоотвПараметровСостояний[Строка.Источник], СоотвПараметровСостояний[Строка.Приемник], СтСумм, СтруктураДопПараметров)
            
        Иначе
            
            Приемники.Вставить(Строка.Приемник, Строка.Приемник);
            
        КонецЕсли;
        
    КонецЦикла;
    
    // Теперь нужно выделить отдельные деревья, определить среднюю стоимость для каждого дерева,
    // и начиная с самого начала каждого дерева последовательно рассчитать стоимость для каждого состояния/перемещения
    
    // Найдем начало каждого дерева - его нет в приемниках
    
    _СоответствиеНачал = Новый Соответствие;
    
    Для каждого Строка Из ТаблицаПеремещений Цикл
        
        // Анализируем только ненулевые дуги
        Если Строка.Количество<>0 Тогда
            
            // Если источника нет среди приемников, значит это начало дерева
            Если Приемники[Строка.Источник]=Неопределено Тогда
                
                //*16.01.2017 ******** 1456 {
                //ВершинаНайдена = Ложь; // признак того, что вершина уже есть в массиве
                //
                //Для Каждого НачалоДерева Из МассивНачалДеревьев Цикл
                //    
                //    // Такая вершина уже имеется в списке начал
                //    Если Строка.Источник = НачалоДерева Тогда
                //        ВершинаНайдена = Истина;
                //        Прервать;
                //    КонецЕсли;
                //КонецЦикла;
                Если _СоответствиеНачал.Получить(Строка.Источник) = Неопределено Тогда
                    _СоответствиеНачал.Вставить(Строка.Источник);
                    МассивНачалДеревьев.Добавить(Строка.Источник);
                КонецЕсли;
                //**16.01.2017 ******** 1456 }
                
                
                //Если НЕ ВершинаНайдена Тогда
                //    МассивНачалДеревьев.Добавить(Строка.Источник);
                //КонецЕсли;
            
            КонецЕсли;
        КонецЕсли;
    КонецЦикла;
    
    // На данном этапе нужна информация о начальном состоянии и внешнем поступлении в каждую вершину
    
    // Будем использовать список вершин, для каждой из которых указаны смежные вершины - приемники и
    Вершины = Новый Соответствие; // здесь нам понадобится общее количество источников, приемники
    Для Каждого Строка Из ТаблицаПеремещений Цикл
        
        Если Строка.Количество=0 Тогда
            Продолжить;
        КонецЕсли;
        
        // Обработаем источник
        ПодчСтруктура = Вершины[Строка.Источник];
        Если ПодчСтруктура=Неопределено Тогда
            ПодчСтруктура = Новый Структура("КоличествоИсточников, Приемники, КоличествоРассчитанныхВходов", 0, Новый Соответствие, 0);
        КонецЕсли;
        
        СтСумм = Новый Структура; // структура сумм
        Для Каждого КолСумма Из МассивСумм Цикл
            СтСумм.Вставить(КолСумма, Строка[КолСумма]);
        КонецЦикла;
        
        ПодчСтруктура.Приемники.Вставить(Строка.Приемник, Новый Структура("Количество, СтруктураСумм", Строка.Количество, СтСумм)); // Вместе с вершиной-приемником запоминаем количество перемещения
        
        Вершины.Вставить(Строка.Источник, ПодчСтруктура);
        
        // Обработаем приемник
        ПодчСтруктура = Вершины[Строка.Приемник];
        Если ПодчСтруктура=Неопределено Тогда
103 Buster007
 
12.02.18
17:14
а, я подумал ты как-то ускорил решение СЛУ в запросе
104 Вафель
 
12.02.18
17:15
Ну что зип архив помог?
105 timurhv
 
12.02.18
17:22
(0) Нам интересно узнать постановку задачи, при которой необходимо загружать 80гб\день и перепроводить все.
И откуда эти 80гб берутся.
106 Tateossian
 
12.02.18
17:27
(103) А, у тебя РАУЗ. Это для партионки. Но у меня есть dll считающая СЛУ. делал когда то. Могу сбросить, на x86 найти не могу, надо пересобирать. На x64 есть.

    ИмяВременногоФайла = КаталогВременныхФайлов() + "AddInGauss.dll";
    Макет = Документы.ъъРасчетСебестоимости.ПолучитьМакет("ВК_Гаусс");
    
    Макет.Записать(ИмяВременногоФайла);
    
    ПодключитьВнешнююКомпоненту(ИмяВременногоФайла, "VKGauss", ТипВнешнейКомпоненты.Native);
    ВнешКомп = Новый ("AddIn.VKGauss.AddInGaussExtension");
    
    МассивОтветов = Новый Массив(Разрядность);

    ВнешКомп.СоздатьМатрицу(Разрядность);
    
    Для Инд = 0 По Разрядность-1 Цикл
        Для Инд2 = 0 По Разрядность-1 Цикл
            ВнешКомп.УстановитьЗначение(Инд, Инд2, МатрицаКоэффициентов[Инд][Инд2]);
        КонецЦикла;
        ВнешКомп.УстановитьСвободныйЧлен(Инд, СтолбецПравыхЧастей[Инд]);
    КонецЦикла;
    
    ВнешКомп.РешитьУравнение();
    
    Для Инд = 0 По Разрядность-1 Цикл
        МассивОтветов[Инд] = ВнешКомп.ПолучитьЗначение(Инд);        
    КонецЦикла;
    
    Возврат МассивОтветов;
107 Tateossian
 
12.02.18
17:27
(103) Заполняешь коэффициенты при неизвестных, столбец свободных членов и Решить().
108 Tateossian
 
12.02.18
17:28
(105) Каждый день база должна быть перепроведена по партиям. В результате все перепроведенные регистры накопления выгружаются в такой вот документ.
109 Вафель
 
12.02.18
17:28
гаусс - это же самый медленный способ
110 Tateossian
 
12.02.18
17:30
(109) Он самый оптимальный. На cpp какая разница. Для 1С деление и обращение по индексу - это самые тяжелые операции во всем расчете(((
111 Tateossian
 
12.02.18
17:31
(104) Нет, так как нужно использовать его методы без создания файла.

(103) Куда мне выложить?
112 Tateossian
 
12.02.18
17:36
Вот статейка насчет сериализации в JVM

htt ps:// habrahabr.r u/po st/60317/
113 Buster007
 
12.02.18
17:36
(111) не, компонента не интересна ) В компоненте все в разы быстрее считается, можно даже не оптимизировать практически код, как есть перенести, и уже будет прирост производительности.
114 Tateossian
 
12.02.18
17:39
(113) 1С не может в Bigdata и прочие Map&Reduce. Это приходится учитывать. Короче, не годится для сложных расчетных задач. А вообще все остальное в 1С прекрасно:)
115 Tateossian
 
12.02.18
17:40
(113) Я не вижу ничего плохого усиливать 1С приданными силами и средствами. Особенно, когда посмотрел на устройство инструментов разработчика от ТормозИТ.
116 Вафель
 
12.02.18
17:43
(111) Так на основании потока же можно
117 Tateossian
 
12.02.18
17:45
(116) Напиши, плз, как. Я не смог завести, хоть и понимаю как работают потоки.
118 Tateossian
 
12.02.18
17:47
(116) там видишь в чем проблема - вернуть ДД можно токлько в том случае, если создался ЗаписьZip файла не инициализированным. А чтобы передать объекту источник данных - можно только путь к файлу. То есть как бы он не асинхронный, этот метод. Может связку между чтением и записью зип...
119 H A D G E H O G s
 
12.02.18
17:47
(116) Нет. В поток можно записать результат, но не получить исходные данные.
120 H A D G E H O G s
 
12.02.18
17:48
Пишите в файл, чебынет?
121 Tateossian
 
12.02.18
17:49
(119) Почему, поток двунаправленный. Все зависит от того, к чему его подсоединять - к чтению или записи. Тебе нужно только спозиционироваться на начальном байте и сделать флуш буферу.
122 H A D G E H O G s
 
12.02.18
17:50
ррр, я сказал другими словами твою фразу в (118)
123 Tateossian
 
12.02.18
17:52
(120) Да это очень дорогое удовольствие I/O операции... Для каждого чиха. У меня памяти много много оперативной:) Плюс ко всему кластер на диске 64Кб, представь, если писать однокилобайтные (хоть и временные) файлы...
124 Вафель
 
12.02.18
17:55
напиши компоненту
125 Tateossian
 
12.02.18
17:57
(124) Скорее всего так и будет...
126 Вафель
 
12.02.18
18:00
можно кстати рам диск сделать и через него файлы гонять
127 Tateossian
 
12.02.18
18:01
(126) У меня база sql там. Точнее, самые hiload таблички.
128 Вафель
 
12.02.18
18:05
(127) я про (123)
129 Tateossian
 
12.02.18
18:14
(128) Я могу так решить эту проблему, но дело в том, что вообще ищу универсальное решение, будь хоть я в пределах своего продакшн сервера, или хоть на своем компе. Так как это упростит лично мне работу во многих практических случаях.
130 Вафель
 
12.02.18
18:15
(129) можно 7z или рар использовать, они могут без файлов
131 Вафель
 
12.02.18
18:15
А на сасом деле ты выбрал не правильный механизм хранения ссылок
132 Tateossian
 
12.02.18
18:16
(131) А как нужно было?
133 Вафель
 
12.02.18
18:17
Откуда у тебя ссылки такие длинные? ты что талблицы значений приводишь к строкам?
134 Tateossian
 
12.02.18
18:22
(133) Ключ записи регистра сведений без регистратора.
135 Вафель
 
12.02.18
18:24
а как 1сники сделали в своем версионировании?
136 Tateossian
 
12.02.18
18:31
(135) В хранилище лежат xml сериализованные, а измерение - ссылка на справочник или документ. Ссылка, понимаешь! А ее может не быть - удален документ, все, нет его:) Короче, не все задачи решает. В зазеркалье был пост, что они пилят платформенное версионирование. Вот это будет круто, но пока у меня даже еще конфа на совместимости:)
137 lodger
 
12.02.18
18:34
(135) сериализуют. сперва это было в xml и через темп-файл, потом json.
теперь этот жсон можно не писать в файл. (с недавних версий).
138 Вафель
 
12.02.18
18:36
(136) я предлагаю посмотреть как они сделали в платформе
139 lodger
 
12.02.18
18:37
(136) "удален документ, все, нет его:)" - ну и прекрасно. ссылка превращается в текст равный её гуиду. в представлении данных остается представление полученное перед удалением.
объекта нет, а следы его существования и жизни - есть. потом .уки не отмажутся - "ой не было такого объекта, вам показалось..."
140 Вафель
 
12.02.18
18:40
(139) основная проблема с регистрами, вот это я и предлагаю посмотреть в платформе. со ссылками проблемы нет
141 Tateossian
 
12.02.18
18:49
Посмотрел в последней БСП. Там фастИнфо сет. И только ссылочные типы.

// Возвращает сериализованный объект в виде двоичных данных.
//
// Параметры:
//  Объект - Любой - сериализуемый объект.
//
// Возвращаемое значение:
//  ДвоичныеДанные - сериализованный объект.
Функция СериализоватьОбъект(Объект) Экспорт
    
    ЗаписьXML = Новый ЗаписьFastInfoset;
    ЗаписьXML.УстановитьДвоичныеДанные();
    ЗаписьXML.ЗаписатьОбъявлениеXML();
    
    ЗаписатьXML(ЗаписьXML, Объект, НазначениеТипаXML.Явное);
    
    Возврат ЗаписьXML.Закрыть();

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

Поиграл я с FastInfoSet:

ЗаписьXML = Новый ЗаписьFastInfoset;
ЗаписьXML.УстановитьДвоичныеДанные();
ЗаписьXML.ЗаписатьОбъявлениеXML();

ЗаписатьXML(ЗаписьXML, Объект, НазначениеТипаXML.Явное);

Р = ЗаписьXML.Закрыть();

РазмерДДВБайтах = Р.Размер(); //172 байт  

Ы = ТиповыеОтчеты.СериализоватьОбъектXDTO(Объект);

ДлинаОбычнойXMLСтроки = СтрДлина(Ы);  //242 символа

СтрокаДвДанных = ПолучитьHexСтрокуИзДвоичныхДанных(Р); //
ДлинаСтрокиДД = СтрДлина(СтрокаДвДанных); //344симв

Он действительно самый компактный формат. Но его потом записывают в хранилище. А вот если привести к строке - ровно в два раза увеличивается количество символов. А если в байтах - то 172 байтами строками хранятся в 688 байт.
142 lodger
 
12.02.18
18:51
(141) а зачем дд в хекс в строку? дд записать не вариант?
143 Tateossian
 
12.02.18
19:00
(142) А как ты запросом эти ДД искать будешь?
Закон Брукера: Даже маленькая практика стоит большой теории.