![]() |
|
Самый производительный способ выгрузки во внешние базы данных. kolts23381, Кирпич, laeg, Vostochnick, VKS, yuri_k, Веселый собака, Arbuz, Garykom, phabeZ, tan76, obs191
| ☑ | ||
---|---|---|---|---|
0
kolts23381
18.05.25
✎
18:19
|
Кто разрабатывал такую выгрузку. Пока остановился на CSV. Выгружаю с помощью скд, который при сохранении в текстовый формат дает csv файл. Это быстрее чем с помощью записи текста. Есть более производительные способы?
|
|||
1
Asmody
18.05.25
✎
18:28
|
А тебе повыпендриваться или есть реальная задача, что прям надо "быстро"?
|
|||
2
big
18.05.25
✎
18:48
|
(0) Отличие от текстового формата только в расширении имени файла )))
Если БД внешняя, то тогда и пиши туда напрямую безо всяких прокладок выгрузки-загрузки. |
|||
3
Garykom
гуру
18.05.25
✎
18:50
|
Думаю выпендривается
Ибо выгрузка в JSON из структур/массивов быстрей А еще быстрей банальная выгрузка в DT Как прочитать/распаковать DT это уже отдельный вопрос Другой вариант это прямая выгрузка из скуля |
|||
4
kolts23381
18.05.25
✎
19:08
|
Я реализовал с помощью csv и СКД. Может есть более быстрый способ выгрузки, не считая прямого обмена с базой данных.
(3) То есть запрос к базе данных, в цикле формируется структура, затем запись в файл? Основное время тратится на создание массива(структуры) данных. В чем преимущество? Памяти сколько будет отъедать? Пока не запишешь в файл структуру память будет использоваться |
|||
5
kolts23381
18.05.25
✎
19:12
|
Если что речь идет об отдельных таблицах. Должно выгружаться как есть, но пропускаются колонки с типом хранилище значения, но это детали. Интересует сам формат обмена
|
|||
6
breezee
18.05.25
✎
19:13
|
Через СУБД
|
|||
7
Мультук
гуру
18.05.25
✎
20:58
|
(0)
Вот короткий список риторических вопросов: Что выгружать ? Куда выгружать ? ("та" база счастлива от CSV ?) Сколько выгружать ? (транспорт файл ?) Как часто ? Зачем выгружать ? Нужно ли потом поддерживать/расширять этот формат выгрузки ? |
|||
8
kubik_live
18.05.25
✎
21:09
|
Я с dBaseIII уж 15 лет...
|
|||
9
kolts23381
18.05.25
✎
23:05
|
(7) Какой самый быстрый способ выгрузки данных во внешние базы данных из 1с вы знаете? Выгружать нужно результат какого либо запроса. На данный момент я выгружаю таблицы как есть в дереве метаданных. Это все не относится к вопросу. Данных много, выгружать нужно часто. Хотя бы раз в день. Опять же повторюсь, вопрос только в том какой способ выгрузки самый производительный. Есть допустим регистр партии. Нужно выгружать его во внешнюю базу данных. Процесс загрузки во внешнюю базу не интересует с ним все понятно
|
|||
10
Garykom
гуру
18.05.25
✎
23:40
|
CSV очень "тяжелый" формат с точки зрения преобразования данных
А так же разных неожиданных ошибок и багов Спец его не выберет со времен появления JSON Определить спец или нет очень легко Скажи как ты в строках служебные символы (запятая, точка с запятой, кавычки, переносы строки и прочие непечатные) будешь? Как будешь дата/время кодировать? Как будешь числа с каким разделителем? Как булево? А средства в 1С готовые платформенные для этого есть? А как быстро они работают? Для JSON есть на уровне платформы... |
|||
11
kolts23381
18.05.25
✎
23:59
|
(10)
Надо тестировать. Сделаю еще одну функцию для выгрузки в своей обработке. Как бы ты формировал JSON. Есть запрос, что дальше? У меня программно создается скд. Строки обрабатываются с помощью выражения представления поля. Числа и дата с помощью условного оформления, хотя тоже можно с помощью выражения представления, думаю что будет одинаково отрабатывать. По умолчанию при сохранении табличного документа в текстовый файл как раз таки создается tsv файл(разделитель табуляция) |
|||
12
timurhv
19.05.25
✎
02:00
|
(11) -> (4)
Сделайте замер времени без режим отладки из конфигуратора (просто пользовательский режим с сообщением о замере времени). Должно намного быстрее сформировать JSON, чем вы замеряли. Табличный документ тоже подтребляет ОЗУ на сервере, так что это не показатель. |
|||
13
kolts23381
19.05.25
✎
02:27
|
Действительно с JSON-ом получается раза в 2-2.5 быстрее. Но это в том случае если запрос выгружать в таблицу значений и таблицу затем сериализовать в json и записывать файл. Немного неудобный формат получается, нужно еще разбираться как это читать. Еще быстрее раза в два это ЗначениеВФайл, выгрузить запрос в ТЗ и записать с помощью это функции. Но тогда придется создать конвертер и не факт что будет выигрываться время.
|
|||
14
Hmster
19.05.25
✎
07:47
|
(0) ЗначениеВСтрокуВнутр если между двумя 1С
|
|||
15
timurhv
19.05.25
✎
08:35
|
(13) Можно еще в сторону ЗаписьFastInfoset посмотреть, в версионировании БСП его используют.
|
|||
16
Fish
гуру
19.05.25
✎
09:07
|
(13) С точки зрения чтения, JSON намного более удобный формат, чем CSV. (см 10)
|
|||
17
Krendel
19.05.25
✎
09:10
|
Загрузку мы добивали до 1/5 от производительнгсти дисковой подсистемы, выгрузка тоже должна быть по идее в этих же пределах
|
|||
18
Кирпич
19.05.25
✎
10:31
|
+(14) Делал результат запроса в ЗначениеВФайл(), потом этот файл преобразовывал в csv сторонней программой. Работало как пуля.
|
|||
19
Кирпич
19.05.25
✎
10:35
|
(16) JSON сложнее CSV. А чем сложнее формат, тем медленнее загрузка/выгрузка. Для тупой загрузки данных в таблицу БД, cмысла в JSON нет.
|
|||
20
kolts23381
19.05.25
✎
10:39
|
(19)К тому же json весит примерно в 10 раз больше в несжатом виде. Какой программой преобразовывали в csv
|
|||
21
Кирпич
19.05.25
✎
10:42
|
(20) "Какой программой преобразовывали в csv "
да какой. сам писал на паскале:) |
|||
22
kolts23381
19.05.25
✎
10:48
|
Какой подход использовали для преобразования, можете подсказать? Читали построчно, разбирали строку? Как в таком случае разбирали строку, с помощью регулярных выражений или нет?
|
|||
23
Кирпич
19.05.25
✎
10:59
|
(22) да ну просто парсер. нам не сложно. Просто разобрать такую абракадабру.
{"T",4,2,"S","Code","S","Description","S","000000001","S","1 ляля","S","000000002","S","2 ббб","S","000000003","S","3 ббббб"} любой школьник напишет или ИИ. |
|||
24
kolts23381
19.05.25
✎
12:55
|
Все-таки использовали регулярно или посимвольный разбор?
|
|||
25
Кирпич
19.05.25
✎
11:05
|
тут же всё понятно. "T" таблица, "4,2" - четыре строки две колонки и погнали
|
|||
26
Кирпич
19.05.25
✎
11:06
|
(24) посимвольно конечно. регулярки будет медленней
|
|||
27
Кирпич
19.05.25
✎
11:06
|
да и не нужны они тут
|
|||
28
Кирпич
19.05.25
✎
11:10
|
забил это в ИИ :)
Отлично! Ты хочешь написать **парсер на Go** для разбора структуры вида: ```json {"T",4,2,"S","Code","S","Description","S","000000001","S","1 ляля","S","000000002","S","2 ббб","S","000000003","S","3 ббббб"} ``` Это не стандартный JSON, а скорее **сериализованный массив значений**, где: - `"T"` — тип (возможно, "Table") - `4` и `2` — какие-то числа (например, количество строк и столбцов) - `"S"` — указывает, что следующее значение — строка (`S` = String) --- ## 🎯 Цель Превратить это выражение в понятную структуру, например: ```go type ParsedData struct { Type string Rows int Columns int Headers []string Data map[string]string // или []map[string]string в зависимости от формата } ``` --- ## ✅ Пример входных данных ```go input := []interface{}{"T", 4, 2, "S", "Code", "S", "Description", "S", "000000001", "S", "1 ляля", "S", "000000002", "S", "2 ббб", "S", "000000003", "S", "3 ббббб"} ``` > Для упрощения будем считать, что входной массив уже распарсен как `[]interface{}`. --- ## 🔧 Реализация парсера Вот готовый пример парсера на Go: ```go package main import ( "fmt" ) type ParsedData struct { Type string Rows int Columns int Headers []string // Заголовки колонок Data []map[string]string // Строки данных: ключ — заголовок, значение — значение } func parseCustomFormat(tokens []interface{}) (*ParsedData, error) { if len(tokens) < 5 { return nil, fmt.Errorf("слишком мало данных") } p := &ParsedData{} // Первое значение — тип if t, ok := tokens[0].(string); ok { p.Type = t } else { return nil, fmt.Errorf("первое значение должно быть строкой типа") } // Второе и третье — целые числа: Rows и Columns if r, ok := tokens[1].(int); ok { p.Rows = r } else { return nil, fmt.Errorf("второе значение должно быть целым числом") } if c, ok := tokens[2].(int); ok { p.Columns = c } else { return nil, fmt.Errorf("третье значение должно быть целым числом") } idx := 3 // Читаем заголовки for i := 0; i < p.Columns && idx+1 < len(tokens); i++ { if s, ok := tokens[idx].(string); ok && s == "S" { header, ok := tokens[idx+1].(string) if !ok { return nil, fmt.Errorf("ожидалась строка для заголовка %d", i) } p.Headers = append(p.Headers, header) idx += 2 } else { return nil, fmt.Errorf("ожидался 'S' перед заголовком") } } // Проверяем, что удалось прочитать все заголовки if len(p.Headers) != p.Columns { return nil, fmt.Errorf("не найдены все заголовки") } // Читаем данные for i := 0; i < p.Rows && idx+1 < len(tokens); i++ { row := make(map[string]string) for j := 0; j < p.Columns && idx+1 < len(tokens); j++ { if s, ok := tokens[idx].(string); ok && s == "S" { val, ok := tokens[idx+1].(string) if !ok { return nil, fmt.Errorf("ожидалась строка для значения [%d][%d]", i, j) } row[p.Headers[j]] = val idx += 2 } else { return nil, fmt.Errorf("ожидался 'S' перед значением [%d][%d]", i, j) } } p.Data = append(p.Data, row) } return p, nil } func main() { // Исходные данные в виде []interface{} input := []interface{}{ "T", 4, 2, "S", "Code", "S", "Description", "S", "000000001", "S", "1 ляля", "S", "000000002", "S", "2 ббб", "S", "000000003", "S", "3 ббббб", } result, err := parseCustomFormat(input) if err != nil { fmt.Println("Ошибка:", err) return } // Вывод результата fmt.Printf("Тип: %s\n", result.Type) fmt.Printf("Строк: %d | Колонок: %d\n", result.Rows, result.Columns) fmt.Printf("Заголовки: %v\n", result.Headers) fmt.Println("Данные:") for _, row := range result.Data { fmt.Println(row) } } ``` --- ## 📦 Результат выполнения: ```text Тип: T Строк: 4 | Колонок: 2 Заголовки: [Code Description] Данные: map[Code:000000001 Description:1 ляля] map[Code:000000002 Description:2 ббб] map[Code:000000003 Description:3 ббббб] map[Code:000000003 Description:3 ббббб] ← если rows > данных — будет повтор? ``` > ⚠️ В твоих данных только 3 строки, но указано `rows=4`. Если нужно — можно добавить проверку. --- ## ✅ Что умеет парсер: - Парсит тип (`T`) - Читает число строк и столбцов - Читает заголовки по метке `"S"` - Читает данные по строкам и привязывает к заголовкам - Выдает результат в удобной структуре --- ## 🚀 Что можно добавить: - Поддержку других типов, кроме `"S"` (например, `"I"` — integer, `"B"` — boolean) - Валидацию длины данных - Возможность сериализации обратно - Поддержку JSON/YAML вывода --- Если тебе нужно адаптировать это под конкретный протокол, формат или API — пиши, я помогу! 😊 |
|||
29
Кирпич
19.05.25
✎
11:13
|
ИИ конечно фигню написал, но примерный объем работ виден.
|
|||
30
kolts23381
19.05.25
✎
11:15
|
Я уже забивал в ИИ). Буду смотреть, спасибо
|
|||
31
Кирпич
19.05.25
✎
11:21
|
(30) Да на ИИ можно и не тратить время. За день сам напишешь (если конечно знаешь какой нибудь язык программирования). Если большие файлы, обязательно используй буферизацию или MMAP.
|
|||
32
kolts23381
19.05.25
✎
11:28
|
C++, есть опыт
|
|||
33
Кирпич
19.05.25
✎
11:45
|
(32) От это тебя угораздило. Неделю теперь будешь писать :)
|
|||
34
olegves
19.05.25
✎
12:59
|
(0) самый производительный - это репликация БД средствами скуля
|
|||
35
rsv
19.05.25
✎
13:05
|
(0) если источник ms sql , cоздайте в нем линкованый сервер на приемник. И обычным select into.
|
|||
36
rsv
19.05.25
✎
13:07
|
Linked Server
|
|||
37
H A D G E H O G s
19.05.25
✎
13:32
|
Запрос -> ТЗ -> ЗначениеВФайл -> ВнешняяКмпонентаНаДельфи которая преобразует формат 1С в csv -> bulkinsert из csv в БД.
|
|||
38
kolts23381
19.05.25
✎
13:58
|
(34) это да, но не хотелось бы связываться с прямыми запросами, не всегда есть доступ к базе данных. (37) Тоже пришел к такому выводу. Осталось сделать конвертер
|
|||
39
Garykom
гуру
19.05.25
✎
15:01
|
(29) ИИ написал не просто фигню а много фигни
На практике все намного проще в Go |
|||
40
Garykom
гуру
19.05.25
✎
15:04
|
Имхо ТС херней занимается
Если надо самый быстрый способ: То ПолучитьСтруктуруХраненияБазыДанных() и прямые запросы Если надо просто, удобно, гибко и достаточно быстро: Использовать JSON в платформе 1С и не выделываться |
|||
41
Garykom
гуру
19.05.25
✎
15:04
|
(37) объясни нахера промежуточные шаги, когда можно сразу из СУБД запросами прямыми???
|
|||
42
Garykom
гуру
19.05.25
✎
15:07
|
(41)+ пишется запрос на 1С, профайлером (есть ИР) ловится
напрямую исполняется в СУБД, результат в текст в удобном виде зачем еще ВК изобретать? или использовать официально не рекомендованный ЗначениеВФайл |
|||
43
Voronve
19.05.25
✎
15:09
|
(41) Грузани напрямую контрагентов в базу битрикса. А мы похохочем ...
|
|||
44
Garykom
гуру
19.05.25
✎
15:28
|
(43) 1. Конфу не указал
2. Самому что знаний не хватает для подобного? 3. Лично я сделаю на JSON и http-сервисах. И не буду выделываться с разными CSV, ЗначениеВФайл, ЗначениеВСтрокуВнутр, внешними компонентами и прочими извратами |
|||
45
kolts23381
19.05.25
✎
15:26
|
(42)Потому что к субд не всегда есть доступ. А если файловый вариант? JSON сложнее загружать в субд, тоже нужна прослойка, но согласен ее написать легче чем для внутреннего формата 1с(ЗначениеВФайл).
|
|||
46
Мультук
гуру
19.05.25
✎
15:32
|
(45)
"Файловый вариант" Сначала быстрей, быстрей -- напишем конвертер на Си, нет -- на Си, но с asm-вставками. А теперь оказывается выгрузка из файловой базы. |
|||
47
Garykom
гуру
19.05.25
✎
15:33
|
(45) к СУБД всегда есть доступ
если у тебя есть доступ в Конфигуратор, то можно выгнать всех нахрен, выгрузить в DT и загрузить ее в свою СУБД это если разовая выгрузка-загрузка а если постоянная - используйте стандартные общепринятые механизмы (json, http и т.д.) и наймите спецов вместо этого нубского лепета для bulk в СУБД есть специальные форматы и CSV там не главный, главный sql insert |
|||
48
kolts23381
19.05.25
✎
15:38
|
(46)Я ожидал этого сообщения. Решение должно быть универсальным. Мне не охота писать несколько вариантов - один быстрый, другой медленный третий еще какой-то
|
|||
49
Кирпич
19.05.25
✎
16:08
|
(44) как JSON и вебсервис поможет "быстро выгрузить из 1С"? Это же два галимых тормоза тормоза :)
|
|||
50
Кирпич
19.05.25
✎
16:11
|
И JSON этот по умолчанию будет в каждую строчку имена полей вставлять, что есть идиотизм. А если делать нормальный JSON, то он будет похож на CSV как однояйцевые близнецы.
|
|||
51
Кирпич
19.05.25
✎
16:14
|
(48) щас я суп доварю, сделаю тебе конвертор этот. заодно замерим у кого быстрее получится.
|
|||
52
scanduta
19.05.25
✎
17:20
|
(0) Данных недостаточно
выгрузка одноразовая или это периодический обмен? Таблица в плоском виде или более сложная структура? Какие системы участвуют в обмене? Если делается внутри между базами sql , тогда зачем будут нужны файлы если можно напрямую |
|||
53
tabarigen
19.05.25
✎
17:22
|
(34) 🤣 зато честно
|
|||
54
tabarigen
19.05.25
✎
17:24
|
если серьезно, то пост максимально не серьезный.
автор после своего потока сознания поставил знак вопроса и спросил тут. |
|||
55
Кирпич
21.05.25
✎
16:40
|
Вот заколбасил. Только имена полей пока тупо генерятся F1 F2 F3.... Неохота сейчас с ними возиться.
https://github.com/qxlreport/tocsv |
|||
56
Кирпич
20.05.25
✎
11:32
|
Потестил код из (55)
На моем стремительном i7-3770 3.40GHz и SSD гигабайтный файл в 10 млн записей из двух полей переделывает за 5 секунд вполне себе быстренько |
|||
57
Кирпич
20.05.25
✎
11:37
|
За какое время такую кучу сможет вывалить 1С через ЗначениеВФайл() науке пока не известно
|
|||
58
Кирпич
21.05.25
✎
16:54
|
подкрутил чтобы имена полей выводил такие же как и в запросе
кому надо, лежит здесь https://github.com/qxlreport/tocsv |
|||
59
Garykom
гуру
22.05.25
✎
02:27
|
Ммм тут мысля возникла
А есть возможность получить сформированную ВТ с данными в СУБД снаружи текущего сеанса? Я к чему, делать прямые запросы это весьма трудозатратно Но можно же слегка схитрить и подготовить временные таблички простой структуры, причем известной А затем их банально забрать из СУБД |
|||
60
kolts23381
22.05.25
✎
00:58
|
У меня на подходе своя версия на с++ ). (59) Скорей всего если использовать менеджер временных таблиц, то временная таблица будет существовать пока существует менеджер. Осталось узнать ее название.
В 8.3.12 таблица значений обозначается так: {"#",acf6192e-81ca-46ef-93a6-5a6968b78663, |
|||
61
timurhv
22.05.25
✎
01:12
|
(50) Ну добавьте в csv данные по контрагентам, номенклатуре, организации, складу, остаткам и тд. В JSON это все проще, можно отдельной сущностью описать.
(59) => (52) проще какую-то синхронизацию с самописной БД организовать, чем от 1С плясать если нужна скорость именно выгрузки. Актуализацию данных можно организовать через регистр сведений и рег.задание. Чет видал какие-то подобные хотелки по гос.контрактам чтобы данные выгружались не более 3 сек. |
|||
62
Кирпич
22.05.25
✎
07:39
|
(61) " В JSON это все проще, "
А загружать это потом как? SQL Server сам догадается, что в какие таблицы писать? CSV булькнул и готово |
Форум | Правила | Описание | Объявления | Секции | Поиск | Книга знаний | Вики-миста |