Имя: Пароль:
1C
 
Самый производительный способ выгрузки во внешние базы данных.
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 булькнул и готово
Пользователь не знает, чего он хочет, пока не увидит то, что он получил. Эдвард Йодан