Имя: Пароль:
1C
1C 7.7
v7: Необходим быстрый поиск информации в больших CSV файлах
0 evgpinsk_
 
01.05.21
13:07
Есть прайс в формате CSV площадки onliner.by
В нём 700 тыс позиций.
Раз в сутки прайс обновляется.

Стоит задача в 1с получать быстрый доступ к цене определённого товара из данного прайса (скорость желательна в пределах нескольких секунд).
В прайсе есть столбец "IDтовара" по которому будет осуществляться поиск.

Вопрос: Каким образом осуществлять поиск, через какие инструменты?
1 ДенисЧ
 
01.05.21
13:08
булкой в скуль-сервер и там искать.
2 Garykom
 
гуру
01.05.21
13:13
(1) Нахер?
Я бы индекс тупо построил пробежав один раз и вытащив id, и начало/конец символов нужных данных привязав их к id
3 evgpinsk_
 
01.05.21
13:14
(2) т.е. импортировать данные в dbf файл?
4 Garykom
 
гуру
01.05.21
13:15
(3) нафик в регистр запиши если 1Сник
5 evgpinsk_
 
01.05.21
13:15
(1) что за булка? )
6 Garykom
 
гуру
01.05.21
13:16
7 Garykom
 
гуру
01.05.21
13:16
(6)+ Но не советую разом весь файл в 700к, лучше по 10к порциями
8 1CnikPetya
 
01.05.21
13:17
(4) У человека 7ка, какой регистр )

Можно в Номенклатуру добавить периодический реквизит ПоложениеВПрайсе и обновлять его ежедневно.
9 Garykom
 
гуру
01.05.21
13:17
(8) Эээ я как то отвык уже от 77
10 ДенисЧ
 
01.05.21
13:18
(7) Как раз булка-то и нужна, чтобы сотнями тысчк писать, это же не инсерт
11 Garykom
 
гуру
01.05.21
13:18
(8) Не не никаких периодических это тормоза
Тогда да лучше dbf с индексом
12 evgpinsk_
 
01.05.21
13:19
Да, изначально у меня мысли были или DBF или MySql.
Но может ещё есть какие-то несложные инструменты?
13 Garykom
 
гуру
01.05.21
13:24
(12) экселем открываешь csv и сохраняешь как dbf - это можно автоматизировать
далее средствами 1С навешиваешь индекс и юзаешь
14 evgpinsk_
 
01.05.21
13:27
(13) CSV-Прайс просто не очень красивый формат имеет.
Цены магазинов идут в одной строке на товар. Сейчас столбцов в прайсе 180штук
https://prnt.sc/12cskh0
15 trdm
 
01.05.21
13:31
(2) ++
(13) ++
(14) и что? просто нормализуй dbf-ку.
16 evgpinsk_
 
01.05.21
13:31
В принципе можно ограничиться минимальными ценами ограниченного числа магазинов. Например читать только первые 20 столбцов.
Каким инструментом оптимально экспортировать из Excell в DBF?
17 Garykom
 
гуру
01.05.21
13:34
(16) дык сам эксель или либреофис и умеют сохранять в dbf
18 evgpinsk_
 
01.05.21
13:39
(17) С 2007 офиса уже не сохраняет в DBF
19 Garykom
 
гуру
01.05.21
13:44
(18) ыыыы
я на libreoffice давно перешел
20 Garykom
 
гуру
01.05.21
13:46
короче как бы делал я чтобы было очень шустро для 77
написал бы за полчаса простейшую консольную утилиту на go которая csv2dbf.exe
затем запускал бы ее с параметрами из 77 и все
21 Garykom
 
гуру
01.05.21
13:48
(20)+ самый смак это если файловая то прямо в специально созданную объекту в 1С прямо в dbf табличку писать
ну или для sql 1С 77 аналогично сразу в mssql табличку
22 Garykom
 
гуру
01.05.21
13:49
(21)+ а искал бы в 1С запросами, они там тупые но вполне шустрые
23 Garykom
 
гуру
01.05.21
13:52
(20) даже не полчаса а минут 20 с тестами
1. https://golangs.org/parsing-csv
2. https://github.com/LindsayBradford/go-dbf
24 Garykom
 
гуру
01.05.21
13:56
(23)+ даже есть готовое но не в ту сторону
https://github.com/lancecarlson/dbfcsv

и есть готовое на питоне
https://github.com/Kanahiro/dbfConverter
в обе стороны
25 trdm
 
01.05.21
14:04
(24) а питон может компилиться в екзешник.
26 Garykom
 
гуру
01.05.21
14:08
(25) там уже скомпилено
но имхо не люблю питон, пришлось вынужденно слегка выучить но не люблю, раздражает
27 Garykom
 
гуру
01.05.21
14:09
(26)+ для питон это как раньше бейсик был - язык для косячных дебилов
28 Garykom
 
гуру
01.05.21
14:11
(27)+ по этой же причине и js с нодой сча бесят, ибо эти косячные просто в веб приперлись и там начали говнокодить
TypeScript в этом плане сильно лучше
29 trdm
 
01.05.21
14:36
(26) сам не люблю, но иногда это самый оптимальный инструмент.
30 Djelf
 
01.05.21
16:10
(0) Лучше конечно конвертировать во что-то более вразумительное чем csv, об этом уже все написали.
Но можно и sqlite прикрутить: https://infostart.ru/public/805029/ (в 7м посте без СМ выложено).
31 evgpinsk_
 
01.05.21
16:13
(30) В CSV исходный прайс, который даёт площадка
32 Djelf
 
01.05.21
16:27
(31) И что из этого следует? Это было очевидно...
Ты прочитал что написано в описании по ссылке в (30)?
Быстрее возможно сделать, но скорость запроса будет примерно на 5% выше, т.к. накладные расходы у sqlite очень не высокие.
33 evgpinsk_
 
01.05.21
16:37
(32) Да, прочитал. Сейчас уже понял в (30) смысл 1го предложения.
sqlite у меня используется кое-где в конфигурации (прямые запросы к справочникам) - скорость изумительная.
По ссылке на инфостар - буду смотреть.
34 ДедМорроз
 
01.05.21
19:51
Csv файл - это файл последовательного доступа,поэтому его нужно хотя бы один раз прочитать весь.
И,если мы его читаем весь,то его можно скорректировать во что-то другое.
Я вот в нем логи анализировал,которые за час на несколько гигов набивались,и,нужно сказать,что читаешь и в какую-то sql-базу,так как там потом проще вести анализ.
Опять же,если там много колонок с ценами,то можно распределить по отдельным строкам,только нужно будет идентификатор товара придумать.
35 trdm
 
02.05.21
10:16
(30) Там только dll-ка, примера нет.
36 evgpinsk_
 
02.05.21
10:46
(35) Да, жаль )
37 Бертыш
 
02.05.21
12:12
(8) Не преувеличивайте коллега. Я в 2003 ем году делал эмуляцию регистра сведений для 7.7 на регистрах накопления
(0) CSV это текст. Грамотно составленное RegExp выражение в скрипте на пайтоне спасёт отца русской демократии. Весь то файл Вам зачем
38 evgpinsk_
 
02.05.21
13:07
(37) Как минимум нужно быть знакомым с пайтоном ).
поиск в CSV более медленный, чем с использованием индексов
39 ДедМорроз
 
03.05.21
00:20
(37) если искать только один раз,то да RegExp чем-то поможет,если искать несколько раз,то проще один раз распарсить.
40 acanta
 
03.05.21
09:00
А если искать постоянно? То есть использовать csv в качестве базы данных (лог файл, дописывается в конец) и отчеты собрать по нему?
41 Mikeware
 
03.05.21
11:04
(40) "дописывается в конец", и "собрать 1 отчет в несколько дней" (ну или "изредка поискать") - это не совсем "БД". Хотя некоторым критериям ("структурирована", "соответсвует схеме") соотвествует БД, но по "типизации", "произвольному доступу к полям" - не соотвествует. Из-за этого сложнее построить лополнительне структуры для улучшения поиска (индексы). поэтому "постоянный поиск" по цсв - плохая идея.
42 acanta
 
03.05.21
11:10
(41) но эксель открывает файлы csv и позволяет использовать пусть не все, но какие то механизмы обработки файлов баз данных...
43 Mikeware
 
03.05.21
11:19
(42) когда "эксель открывает файлы csv" ("импортирует", если быть точным) - он проделывает туеву хучу дополнительной работы. Например, разделяет "по полям", и "типизирует". Именно это приводит относительно регулярную текстовую структуру к регулярной таблице.
44 acanta
 
03.05.21
11:21
В чем разница между импортом екселя и булк инсертом sql?
45 Mikeware
 
03.05.21
11:24
(44) как посмотреть. с однй стороны ее почти нет (текст преобразовывается в регулярную таблицу), с другой разница большая в скорости, в объеме возможных преобразований, и полученном результате.
46 acanta
 
03.05.21
11:43
Но в случае екселя результат в оперативной памяти и возможно, во временном файле. А в случае sql только файл. Проблема в том, что оперативная память с наведением красоты медленнее или в том что исходный файл читают дважды и разные получатели?
47 Mikeware
 
03.05.21
11:50
(46) "Но в случае екселя результат в оперативной памяти и возможно, во временном файле." а возможно, и в постоянном.
"А в случае sql только файл." - а в случае sql в файл это попадет только после записи. но даже запись в файл не мешает висеть в кэше.

"Проблема в том, что оперативная память с наведением красоты медленнее или в том что исходный файл читают дважды и разные получатели?" - видимо, проблема в ДНК...
48 acanta
 
03.05.21
13:40
Или в том, в каком возрасте и в каком объеме изучать английский, чтобы то, что написано нашими программистами на современных языках программирования, имело хоть какой-то смысл?
49 Alex_
Alexsin_2020
 
03.05.21
13:49
можно на шарпе написать (будет время пошарю у себя я уже делал себе) но поиск в текстовых файлах

создаем индексный файл и ищем

но в любом случае боюсь что в пределах 1 секунды не сможет найти насколько помню 10 тысяч записей в пределах где то 30 сек ищет
50 Alex_
Alexsin_2020
 
03.05.21
13:50
это я делал для загрузки в 1С данных из сторонних источников так как 1С обычно долго думала
51 acanta
 
03.05.21
13:57
Вот я не понимаю смысла в полнотекстовом поиске в 1с. У клиентов после третьего повреждения отключила. По подстроке искать в нескольких колонках с представлениями и фильтровать по результатам динамический список?
Я понимаю, что ексель это может и это очень круто..
52 ДедМорроз
 
03.05.21
13:59
Excel определяет тип колонки на лету,а для создания таблицы его нужно указать,и если в разных строках есть разные типы,то для sql это очень печально.

Я делал базу данных на текстовых файлах,для создания индекса нужно запомнить только позиции начала строк в файле,а также выбрать целевые поля.
Если индекс работает эффективно и мы выбираем всего несколько записей,то распарсить строку с начала до перевода строки-это не критично по скорости.
При желании,можно даже допустить добавление строк в конец файла.
Если предположить,что наличие в начале строки специальног символа # означает,что строка игнорируется,то можно даже делать редактирование - если новая строка влазит по месту старой,то может остаться хвост комментария,а если не влазит,то она превращается в комментарий и новое значение пишется или в конец или на место комментария подходящего размера.
53 Alex_
Alexsin_2020
 
03.05.21
14:02
(0) если не затруднит напишите какой разделитель, и номер столбца где находится поле по которому ищем
54 Alex_
Alexsin_2020
 
03.05.21
14:02
+(53) а так же имена столбцов которые имеются в файле
55 evgpinsk_
 
08.05.21
09:56
(53) Вопрос ко мне?
Разделитель и поле поиска ведь может быть любым, это большого влияния на суть задачи не оказывает
56 ptiz
 
08.05.21
10:24
(16) Зачем тебе "из Excel в DBF", если можно из твоего файла сразу dbf создать средствами 7.7?
57 evgpinsk_
 
08.05.21
10:51
(56) Как именно?
58 ptiz
 
08.05.21
15:41
(57) А в чем затык? Чтение текста - через СоздатьОбъект("ADODB.Stream"). DBF создается с помощью СоздатьОбъект("XBase").
59 Кирпич
 
08.05.21
15:53
(57) Найди программиста и он тебе за часик сделает. Много денег не возьмет. Только не спрашивай, где искать программиста.
60 evgpinsk_
 
08.05.21
15:59
(56) Не очень красиво построчно читать и заносить в dbf. 700 тыс позиций и 185 столбцов не очень быстро отрабатываются
61 trdm
 
08.05.21
16:06
Сделал бы уже и забыл.
62 evgpinsk_
 
08.05.21
16:13
Да и на этом большом файле вываливается 1с:
https://prnt.sc/12od0q9

где-то после 50тыс строк
63 acanta
 
08.05.21
16:14
64536? размерность поля номер строки в ДБФ
64 evgpinsk_
 
08.05.21
16:15
(63) Нет. 48806 строк записалось. И затем ошибка
65 acanta
 
08.05.21
16:19
А сколько гигабайтов?
66 evgpinsk_
 
08.05.21
16:22
(65) 256Мб если CSV файл
этот же файл, сохранённый в xlsx - 91МБ
67 acanta
 
08.05.21
16:25
какие поля по размеру в ДБФ и сколько получилось в записанном ДБФ файле?
68 Кирпич
 
08.05.21
16:26
(66) Выложи файлик куда нибудь. Я тебе запилю конвертер. Один хрен дождь льёт весь день.
69 Кирпич
 
08.05.21
16:27
(66) А чо ты через excel не сохраняешь?
70 evgpinsk_
 
08.05.21
16:28
(67) В зависимости от количества столбцов, которые читаю. Т.е. ограничение идёт на размер самого dbf файла.
На момент возникновения ошибка файл процесса 1с занимает 1гб в оперативной памяти
71 acanta
 
08.05.21
16:30
ДБФ может записывать на диск сразу построчно, зачем в памяти?
72 evgpinsk_
 
08.05.21
16:30
(69) Насколько я понимаю: Ексель не сохраняет в dbf. До 2007 офиса сохранял, но он до 65к строк только умел читать
73 Кирпич
 
08.05.21
16:31
(62) А ты всё то не тащи в dbf. Только код(ну по чем искать потом) и номер строки в файле. Потом ищешь по коду в маленькой dbf и переходишь на нужную строку в файле.
74 Кирпич
 
08.05.21
16:32
файл читай через ADO (там даже драйвер для csv должен быть)
75 evgpinsk_
 
08.05.21
16:33
(73) Но почему ошибка при больших объёмах чтения всё-таки вылазит? Ради интереса понять. Вот код:
https://prnt.sc/12odpon
76 evgpinsk_
 
08.05.21
16:33
(74) Я и читаю через ADO, правда читаю xlsx но это не важно
77 trdm
 
08.05.21
16:34
(62) Скинь плз файло на почту, поиграюсь...
78 Кирпич
 
08.05.21
16:35
(75) нахрен там чота понимать. это всё никому не нужное. надо задачу решать
79 H A D G E H O G s
 
08.05.21
16:36
Ну 2 Гб файл превысил или сколько там на dbf ?
80 evgpinsk_
 
08.05.21
16:36
(77) CSV файл https://dropmefiles.com/9wccW
81 evgpinsk_
 
08.05.21
16:36
(79) так CSV файл текстом идёт всего 250Мб
82 evgpinsk_
 
08.05.21
16:37
(73) Да, такой вариант можно реализовать
83 acanta
 
08.05.21
16:37
84 H A D G E H O G s
 
08.05.21
16:37
(81) Там в dbf поля фиксированной длины и на них ты получишь избыточность
85 trdm
 
08.05.21
16:37
(75) Не стоит так делать, надо делать 2 dbf-ки, одну со структурой
code_t,code_m,prise
другую
code_m,title_m
86 trdm
 
08.05.21
16:38
(84) ++
87 H A D G E H O G s
 
08.05.21
16:39
Вы какой-то шлабудой занимаетесь.
88 trdm
 
08.05.21
16:48
+(85) а, нет, посложнее нужна структурка, но смысл тот же.
89 trdm
 
08.05.21
16:49
в зависимости от требуемой аналитики. но ничего сложного.
90 evgpinsk_
 
08.05.21
16:52
(84) Понял.
(85) А в чём плюс двух файлов?
91 trdm
 
08.05.21
16:53
(90) Нормализация базы данных. погугли.
92 evgpinsk_
 
08.05.21
16:54
Два файла только решить проблему размера dbf файла на 2Gb и всё? Скорость чтения ведь будет одинакова
93 trdm
 
08.05.21
17:00
это от задачи зависит. понятия не имею, какая тетализация нужна.
94 hhhh
 
08.05.21
17:41
(92) ну 700 тыс строк - это детский сад, мизер, там максимум 1 GB дотянешь, и то чисто теоретически.
95 Кирпич
 
08.05.21
18:13
(92) вот наговнокодил https://cloud.mail.ru/public/kbdr/R2Wz7Nays
там exe и исходники
кидаешь на csv2id.exe csv файл и рядом появляется маленький csv, в котором id товара и его смещение в большом csv
юзай этот маленький csv как хошь. хоть в dbf хоть куда. А большой читай через ADO Stream
96 H A D G E H O G s
 
08.05.21
18:18
(95) Ну елки - палки. Ну и где интерфейс?
97 H A D G E H O G s
 
08.05.21
18:24
1) bulk insert в таблицу SQL NewData
2) Сравнение с таблицей OldData
3) Дельту в таблицу DiffData
4) Удаление таблицы OldData
5) Переименование таблицы NewData в OldData
98 evgpinsk_
 
08.05.21
18:36
Подскажите ещё, туплю и не могу понять как правильно создавать индексный файл?
В чём отличие команд "ДобавитьИндекс" и "СоздатьИндексныйФайл"?

Как нужно исправить код :
    ДБФ = СоздатьОбъект("xbase");        
    ДБФ.ДобавитьПоле("KodOnliner","S",20,1);    
    ДБФ.ДобавитьПоле("minCost","N",12,2);    
    ДБФ.ДобавитьИндекс("KodOnliner", "NAME",1,0,0);
    ДБФ.СоздатьФайл("d:\33.dbf","d:\33.cdx");

недокументированная ошибка вылазит
99 evgpinsk_
 
08.05.21
18:41
(95) Мне наверное будет проще в 1с в цикле чтения CSV файла писать данные в два отдельных DBF файла. В одном будет id товара, а в другом его цены.
Лимит в 2гб не получу
100 evgpinsk_
 
08.05.21
18:44
(98) С ошибкой разобрался, в последнем параметре была :
ДБФ.ДобавитьИндекс("KodOnliner", "NAME",1,0,"");
101 acanta
 
08.05.21
18:47
Там еще авто сохранение было.
В сдх индексы все в одном файле, а в фокспро в отдельных.
102 Djelf
 
08.05.21
20:29
(96) Интерфейс это ерунда, при рабочем решении!
Кирпич нарисовал индекс, для этого, частного случая, в отдельном csv файле.
Этот вариант вполне работоспособен, 1С же же в 3й версии индексов своих логов подобный и применила.
И он должен быть быстрее раз в 10-100 любой конвертации в сторониие форматы!
103 Кирпич
 
08.05.21
20:38
(102) Не очень работоспособен. Чота ADO Stream кажись грузит весь файл в память и читать строку не получатся. Пускай уже грузит в dbf :) Разве что грузилку в dbf написать в отдельном exe(ради быстродействия)
104 acanta
 
08.05.21
21:02
Так к концу года глядишь и файловую версию 1с 8.3 на прямые запросы можно будет...
105 acanta
 
08.05.21
21:03
Простите за глупые вопросы, у них что, файловая база в csv, а индексные файлы в кеше?
106 Вафель
 
08.05.21
22:26
В любом случае чтобы получить строку по номеру нужно весь файл в память загрузить
107 Вафель
 
08.05.21
22:26
И каждый раз придётся это заново делать для каждого юзера
108 Garykom
 
гуру
08.05.21
22:49
(106) Зачем? Можно же файл считывать с нужной позиции символов-байт
Но да надо иметь внешний индекс с какой позиции нужная строка и длина строки
109 evgpinsk_
 
09.05.21
00:30
(102) Не совсем понял смысл использования скрипта exe для разделения одного большого CSV файла на два маленьких. Ведь всёравно для поиска данные нужно закинуть или в DBF или в другую баду данных, где через индекс можно будет производить быстрый поиск
110 Garykom
 
гуру
09.05.21
00:46
(109) Хочешь тупую идею?
Совсем тупую но вполне рабочую.

Банально одним проходом подели свой csv на 700 тысяч файлов, в каждом одна строка
А имя файла это твой id по которому искать будет банально, просто прочитать файл с этим именем
111 Garykom
 
гуру
09.05.21
00:47
(110)+ Тут конечно ограничение файловой системы может всплыть но маловероятно, миллионы вроде там ограничения файлов если не больше в одном каталоге
112 evgpinsk_
 
09.05.21
00:58
(110) По большому счёту любой формат хранения данных подходит, который позволяет искать через индекс.
Я уже реализовал построчное чтение xlsx в dbf через ADODB
Читать сразу CSV файл через ADODB у меня не получилось, и есть неудобная ручная операция - сохранение CSV в XLSX
113 Garykom
 
гуру
09.05.21
01:49
(112) Операции со строками и текстовыми файлами самые быстрые
Это так к сведению
Поэтому просто попробуй (110)
114 Кирпич
 
09.05.21
10:01
(106) Не строку по номеру, а смещение строки в файле. Но это работает, если есть средства перемещения по файлу.
Ну как бы эта задача решается загрузкой в дбф трёх полей. Просто с толку сбило недельное сидение автора над задачей. Я уж подумал ему все данные нужны или медленно работает или хрен знает почему он не хочет тупо грузить в дбф.
115 trdm
 
09.05.21
10:07
(112) Кажется есть провайдер, который может прямо из csv читать.
и не нужна прокладка.
https://www.connectionstrings.com/textfile/
116 Garykom
 
гуру
09.05.21
10:25
(114) просто ТС не программист а не пойми что
над смешной задачкой которая за пару-тройку часов решается сидит хз сколько
117 evgpinsk_
 
09.05.21
11:42
(116) А все кто задаёт вопросы на мисте должны быть программистами, а если нет значит - "не пойми что" ?
п.с. в (110) было менее глупо
118 acanta
 
09.05.21
11:48
Еще раз для программистов. В 7.7 дбф версии иногда случались сбои. Чаще всего они исправлялись методом переиндексации. В sql версии этих проблем не было.
В 8 ке как версии файловой, так и серверной случаются сбои и они чаще всего исправляются чисткой кэша. Следует ли из этого вывод, что в кэше 1с8 хранятся индексы  или какая то их часть, как в файловой так и в серверной версии?
119 Djelf
 
09.05.21
12:17
В продолжение поста в (30).
260мб csv -> 312мб sqlite, меньше минуты требуется

SELECT load_extension('sqlite3_mod_csv','sqlite3_extension_init');
DROP TABLE IF EXISTS vtPrice;
CREATE VIRTUAL TABLE vtPrice USING csvfile('d:\temp\price\catalog_prices_2021-05-08_13_05_50.csv',0,1);
ATTACH  'd:\temp\price\catalog_prices_2021-05-08_13_05_50.db3' as Price;
DROP TABLE IF EXISTS Price.Price;
CREATE TABLE Price.Price AS SELECT * FROM vtPrice;
-- 49000 мс
SELECT * FROM Price.Price WHERE c3='2326434' LIMIT 1;
-- 530мс
CREATE UNIQUE INDEX IF NOT EXISTS Price.idxCode ON Price (c3);
-- 1600 мс
SELECT * FROM Price.Price WHERE c3='2326434';
-- -12 мс
120 dmitryds
 
09.05.21
12:23
(0) вот это срач... а всего лишь один запрос сделать, как написано в (1)
https://docs.microsoft.com/ru-ru/sql/t-sql/statements/bulk-insert-transact-sql?view=sql-server-ver15
121 trdm
 
09.05.21
14:21
(120) не, в данном случае хрень.
122 trdm
 
09.05.21
14:25
(118) >  В sql версии этих проблем не было.

повезло тебе, а у меня раз SQL БД навернулась. С тех пор новые документы выгружаю сразу после записи..
123 Sysanin_1ц
 
09.05.21
14:46
(0) Панду ТС никто не предлагал? Если нет, то я буду первым
124 H A D G E H O G s
 
09.05.21
15:36
SQL
Вставка - 50 секунд

SELECT top 1 *
  FROM [tmp].[dbo].[catalog_prices]
  where [ID]='2326434'
32 мс

CREATE UNIQUE INDEX Priceidx ON catalog_prices (id);
103 мс

SELECT *
  FROM [tmp].[dbo].[catalog_prices]
  where [ID]='2326434'

1 мс
125 Djelf
 
09.05.21
15:53
(124) Те же яйца что в (119), только в профиль!
Выборка по индексу что так, что сяк будет 0-3 мс, и это не существенно.
Но есть и разница - на MSSQL придется что-то делать, а на SQLite нет!
Это небольшой профит, но он есть...
126 trdm
 
09.05.21
17:35
(124) (125) Там в cvs все равно ненормализованная таблица.
Затяните в лоб - запросы на извлечение будут сложными.
Нужна предобработка.
127 Djelf
 
09.05.21
20:27
(126) На таком объеме sqlite хорошо работает и без предобрабоки и без дедупликации.
Можно и это сделать, пару минут наверное займет (запрос уникальных значений у меня 5с занимает по любой колонке, ну +накладные, ну +несколько колонок, ну... за пару минут сработает)...
Но зачем? 300+ метров для sqlite не проблема, и в данном решении можно и без дедупликации обойтись
128 Кирпич
 
09.05.21
20:49
У меня на ноуте на создание файлика с нужными данными уходит <4 сек и <50 мс на поиск нужной строки в этом файлике тупым перебором(это открытие файлика, поиск и закрытие). Нафиг тут sql серверы не нужны.
129 evgpinsk_
 
09.05.21
22:36
(119) Пытался гуглить, но так и не понял, как этот код выполнять в 1с? (т.е. из csv быстро загнать данные в mysql)
либо что для меня лучше - из csv в dbf
если это делать средствами 1с через ADODB (построчно читать данные) - очень долго получается

п.с. ссылки на предыдущей странице на скрипт на гитхабе (csvTOdbf) - он у меня не отрабатывает мой конкретный CSV файл - на выходе dbf получается поломанным
130 hogik
 
10.05.21
02:40
«для меня лучше - из csv в dbf»(с)

Самый быстрый способ:
1) Создать пустой DBF нужной структуры в среде 1С.
2) Вызвать программу на  FoxPro в которой удаляется CDX и выполняется APPEND FROM.
http://www.foxclub.ru/rhproject/project/html/c426861f-e5ef-44ae-96a6-8dbc7a4a2ad5.htm
3) Создать CDX в среде 1С.

Пример закачки файла для «Проверка по списку недействительных российских паспортов».  
http://xn--b1afk4ade4e.xn--b1ab2a0a.xn--b1aew.xn--p1ai/info-service.htm?sid=2000
131 hogik
 
10.05.21
02:40
parameters p1
local p,t,s,f,r,k
set debug off
close all
on escape do figa
set sysmenu off
set safety off
set collate to "RUSSIAN"
set optimize off
t=chr(13)+chr(10)+"Для продолжения нажмите любую клавишу..."
f="list_of_expired_passports.csv"
r="Passport"
modify window screen title "Загрузка Серия+Номер" font "Courier",8 noclose
if vartype(p1)<>"C" then
    ? "Вызов: foxpass <Каталог>"
    wait t
    return 1
endif
p=alltrim(p1)
p=p+iif(right(p,1)="\","","\")
if file(p+f)=.F. then
    ? "Нет файла: "+p+f
    wait t
    return 1
endif
if file(p+r+".DBF")=.F. then
    ? "Нет файла: "+p+r+".DBF"
    wait t
    return 1
endif
if file(p+r+".CDX")=.T. then
    delete file (p+r+".CDX")
endif
s=seconds()
? "Обрабатывается:    "+p+f
use (p+r) exclusive
zap
append from (p+f) fields Code delimited with tab as 1251
k=reccount()
use
? "Загружено записей: "+alltrim(str(k,20,0))
? "Время выполнения:  "+alltrim(str((seconds()-s)/60,20,0))+" мин."
wait t
return 0
**********************************************************************
function figa
endfunc
**********************************************************************
132 Garykom
 
гуру
10.05.21
02:48
(130) (131) приколист где для начала он foxpro возьмет с учетом лицензии?
133 hogik
 
10.05.21
05:00
(132)
«приколист где для начала он foxpro возьмет с учетом лицензии?»(с)
Например, возьмёт runtime library для FoxPro и один EXE (исходный текст ниже) файл позволяющий выполнять исходные тексты.

parameters p0,p1,p2,p3,p4,p5,p6,p7,p8,p9
local f
if !empty(p0)
    f=upper(alltrim(p0))
    f=f+iif(right(f,4)==".PRG","",".PRG")
    if file(f)
        f=substr(f,1,len(f)-4)
        compile &f
        do case
            case empty(p1)
                do &f
            case empty(p2)
                do &f with p1
            case empty(p3)
                do &f with p1,p2
            case empty(p4)
                do &f with p1,p2,p3
            case empty(p5)
                do &f with p1,p2,p3,p4
            case empty(p6)
                do &f with p1,p2,p3,p4,p5
            case empty(p7)
                do &f with p1,p2,p3,p4,p5,p6
            case empty(p8)
                do &f with p1,p2,p3,p4,p5,p6,p7
            case empty(p9)
                do &f with p1,p2,p3,p4,p5,p6,p7,p8
            otherwise    
                do &f with p1,p2,p3,p4,p5,p6,p7,p8,p9
        endcase
    endif        
endif
134 evgpinsk_
 
10.05.21
10:20
Подтягивать ещё foxpro не очень бы хотелось. У меня всё работает, dbf создаю через ADO читая xls
Есть два нюанса, которые не нравятся и которые не знаю как решить:
1) Сейчас руками сохраняю из CSV в XLSX (читать напрямую через ADO файл CSV не получается)
2) Время выполнения чтения первых 7ми столбцов xlsx файла - 250 секунд, что терпимо.
Но если ещё читать и остальные 170 столбцов - очень долго простым перебором
135 trdm
 
10.05.21
10:58
(134) парси "в лоб". Без Excel. Ваще быстрее будет и не надо буде извращаться. И лишние инструменты отпадут и быстрее будет.
136 evgpinsk_
 
10.05.21
11:25
(135) Возможно да, но опять много времени тратить на переделку не хочется ), когда уже есть почти работающий инструмент
137 Garykom
 
гуру
10.05.21
12:23
(136) говно а не инструмент пока
а насчет "опять много времени тратить" еще раз повторю твоя задачка нормальным прогом решается за 2-3 часа
138 Garykom
 
гуру
10.05.21
12:36
(137)+ так как у тебя 77 то значит винда
а значит читать через http://www.script-coding.com/WSH/FileSystemObject.html#3.24.
OpenTextFile или OpenAsTextStream
если CSV без лишних разделителей ("," или ";") внутри полей то далее простейше
и делай что хочешь, хочешь индекс делай в DBF а читай из CSV или все в DBF перегоняй
139 evgpinsk_
 
10.05.21
12:41
(137) В чём конкретно говно ? )
Способ решения вполне нормальный выбран:
Через ADO читаем исходный файл с данными и закидываем его в DBF, далее по индексу поиск нужно товара в прайсе занимает милисекунды.

Проблемы две: время создания DBF файла через ADO 250 секунд если читать по минимуму только первые 8 столбцов (и критически долго - если все столбцы)
Приходится руками конвертировать из CSV в  XLSX

Решить эти две проблемы программисту занимает не 2-3 часа - а минут 5 :)
и в теории это мне известно,
вараинт А) либо вместо dbf использовать SQLlite как в примере (119), но гугл не даёт мне конкретного примера какой ситнтакис
в самой 1с этого кода из (119):
DROP TABLE IF EXISTS vtPrice;
CREATE VIRTUAL TABLE vtPrice USING csvfile('d:\temp\price\catalog_prices_2021-05-08_13_05_50.csv',0,1);
ATTACH  'd:\temp\price\catalog_prices_2021-05-08_13_05_50.db3' as Price;

вариант Б) использовать сторонню софтину CSVtoDBF - но не смог найти через гугл чтото работающее: либо платное, либо кряки с вирусами.
140 evgpinsk_
 
10.05.21
12:45
(138) Помню что полгода назад читал CSV файлы "в лоб"
и помню что тоже много нюансов вылазило, и количество строчек кода для лечения всех этих нюансов помню было точно не меньше 10-20.

Не хочется начинать пробовать чтобы опять упереться в какойто нюанс и сидеть над ним несколько часов.

Если не найду работаюший скрипт CSVtoDBF или не получу подсказку-пример как закинуть CSV  в SqLite (а это было бы полезно и для общего развития)
тогда уже буду думать по смене принятого алгоритма решения
141 Djelf
 
10.05.21
12:48
(140) Да я же тебе все запросы в sqlite в (119) написал. Это все работает.
Или тебе все это в код на 1С нужно обернуть? Там же простые запросы по очереди, ничего сложного...
142 evgpinsk_
 
10.05.21
12:49
(138) Проблема в том, что инструменты которые по этой ссылке для меня не знакомы. И если знающему эти инструменты их приминение занимает 1-2 минуты
то для меня сначала нужно будет потратить несколько часов на их изучение.

ну не программер я )
Трачу пару часов в неделю на решение каких то задач, т.к. мне это интересно. Но уровень знаний в большей степени только на уровне базового 1с
143 evgpinsk_
 
10.05.21
12:50
(141) Сами запросы в (119) мне понятны. Но да, к сожалению мне не понятно как это закинуть в 1с.
Примеров гугл на даёт (
144 evgpinsk_
 
10.05.21
12:54
И по ссылке (30) пример реализации "CSVtoDBF для больших массивов данных" в 1с тоже не доступен. Потратил час времени на поиск в гугле но зря
145 mistеr
 
10.05.21
12:54
700К это фигня, если честно. Любая in-memory БД и будет летать при наличии памяти. SQLite тоже справится.

А "пределах нескольких секунд" справится даже справочник в основной базе. Ночью обновляешь, днем читаешь.

Иля я проблемы не понимаю.
146 mistеr
 
10.05.21
12:55
Если проблема прочитать CSV и залить в справочник, то найма программиста, за 2-3 ч. сделает.
147 mistеr
 
10.05.21
12:55
(146) *найми*
148 evgpinsk_
 
10.05.21
12:57
(146) Понимаю что иногда читается между строк, но "прочитать CSV и залить в справочник" я и сам сделал.
Но штатное решение  занимает не один десяток минут на чтение всего CSV файла размером 267МЕГАбайт
149 mistеr
 
10.05.21
12:59
(148) Странно, но допустим. Это проблема? Раз в сутки можно и 20 минут выделить на это.
150 evgpinsk_
 
10.05.21
13:02
(149) Да, т.к. читать этот файл мне хотелось бы дважды в сутки и в рабочее время. Читается это в специальном сеансе Робота, где крутится 1с.
И если 1с зависает на 20-30 минут монопольно на чтение CSV файла, то в этом момент не работаю другие задачи (например чтения оналйн заявок с интернет-магазина)
151 Djelf
 
10.05.21
13:10
(142) Тогда понятно...
Ну ладно, вот тебе код на 1С

Функция КонвертерCSV2Sqlite(ИмяФайлаCSV)

    ИмяФайлаSqlite = Лев(ИмяФайлаCSV,СтрДлина(ИмяФайлаCSV)-4)+".db3";

    База=СоздатьОбъект("SQLiteBase");

    База.Открыть(ИмяФайлаSqlite);
    База.РазрешитьЗагрузкуРасширений(1);

    Запрос=База.НовыйЗапрос();

    Запрос.ВыполнитьЗапрос("PRAGMA synchronous = OFF");    
    Запрос.ВыполнитьЗапрос("PRAGMA journal_mode = MEMORY");

    Запрос.ВыполнитьЗапрос("SELECT load_extension('sqlite3_mod_csv','sqlite3_extension_init');");
    Запрос.ВыполнитьЗапрос("DROP TABLE IF EXISTS vtPrice;;");
    Запрос.ВыполнитьЗапрос("CREATE VIRTUAL TABLE vtPrice USING csvfile('"+ИмяФайлаCSV+"',2,1);");

    НачВремя = _GetPerformanceCounter();
    Запрос.ВыполнитьЗапрос("DROP TABLE IF EXISTS Price");
    Запрос.ВыполнитьЗапрос("CREATE TABLE Price AS SELECT * FROM vtPrice");
    КонВремя = _GetPerformanceCounter();
    ВсегоЗаписей = Запрос.ВыполнитьЗапрос("SELECT count(*) FROM Price;",0);
    ЗаписейВСекунду = Окр(ВсегоЗаписей/(1+КонВремя-НачВремя)*1000);
    
    Сообщить("Импорт завершен за "+(КонВремя-НачВремя)+" мс, загружено "+ВсегоЗаписей+" записей, загрузка "+ЗаписейВСекунду+" записей/с");
    Запрос.ВыполнитьЗапрос("DROP TABLE IF EXISTS vtPrice");

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


И код для консоли sqlite3.exe. Можешь в батник завернуть, как - ищи сам.


sqlite> .open target.db
sqlite> .load sqlite3_mod_csv.dll
sqlite> CREATE TABLE Price AS SELECT * FROM vtPrice;
sqlite> .timer on
sqlite> DROP TABLE IF EXISTS Price;
Run Time: real 0.473 user 0.140625 sys 0.328125
sqlite> CREATE TABLE Price AS SELECT * FROM vtPrice;
Run Time: real 48.485 user 41.171875 sys 4.734375
sqlite>


Без моего расширения файл, загрузить можно, но исходник в кодировке 1251, а sqlite работает в utf8, потребуется перекодирование, а у меня оно встроено.
152 evgpinsk_
 
10.05.21
13:15
(151) Спс, изучаю
153 Djelf
 
10.05.21
13:18
(152) А 1sqlite и sqlite3_mod_csv_03 забирай отсюда https://cloud.mail.ru/home/1sqlite/
154 evgpinsk_
 
10.05.21
13:55
(153)  Может быть из-за старой версии 1sqlite?
База.РазрешитьЗагрузкуРасширений(1);
{Обработка.ЗагрузкаДанныхОнлайнера.Форма.Модуль(16)}: Поле агрегатного объекта не обнаружено (РазрешитьЗагрузкуРасширений)

п.с. по ссылки на маил.ру - нет файлика
155 Djelf
 
10.05.21
14:58
(154) Конечно из-за старой, и очень-очень старой! В оригинальной версии Орефкова загрузка расширений была задумана, но не работает.
Вот правильная ссылка https://cloud.mail.ru/public/9znr/ZJ6ULE9aR
156 Вафель
 
10.05.21
15:08
Мускул поднять. Он умеет балк лоад из цвс
157 evgpinsk_
 
10.05.21
15:20
(155) Да, у меня была 1.0.2.3
Более свежая 1.0.2.6 решила проблему
158 evgpinsk_
 
10.05.21
15:22
За 37 секунд загружается CSV размером 700Мб в Sqlite базу
Сейчас буду изучать как его читать )
159 Djelf
 
10.05.21
15:43
(158) Это самое простое...

Запрос.ВыполнитьЗапрос("CREATE UNIQUE INDEX [idxGoods] ON [Price]([ID товара]);");
ТаблицаЗначений=Запрос.ВыполнитьЗапрос("SELECT * FROM Price WHERE [ID Товара]='12';");

Создаем уникальный индекс на код товара и запрос в ТЗ.
Тут есть заморочки с именами колонок!
Имя колонки из-за того что в нем пробелы - в квадратных скобках, а тип значения колонки [ID Товара] - строка, поэтому в одинарных кавычках.
160 mistеr
 
10.05.21
15:53
(159) Поскольку ТС не совсем программист, нужно отдельно отметить, что индекс создается один раз после загрузки.


А параметры умеет это расширение?
161 Djelf
 
10.05.21
15:57
(160) Таблица же дропается перед загрузкой, проблем не будет, но можно написать и так:
Запрос.ВыполнитьЗапрос("CREATE UNIQUE INDEX IF NOT EXISTS [idxGoods] ON [Price]([ID товара]);");
Какие-то параметры умеет https://infostart.ru/public/805029/ там написано что умеет.
162 evgpinsk_
 
10.05.21
16:02
(160) Да, заметил ). Через Попытку Исключение
обрабатываю.

И ещё чисто теоретический вопрос ради интереса:
в самом CSV файле нет отдельного столбца, которое нужно индексировать для поиска.
индекс нужно строить по части поля столбца, который содержит путь к файлу:
http://catalog.onliner.by/cartridges/xerox_compat/0006r01179

и индексируемым значением для поиска будет текст за последним слешем: "0006r01179"

простой вариант решения - сделать предобработку CSV файла, выделив в нём это нужное значение части поля в отдельный столбец.
Вопрос- так и делать , либо движок sqlite может решить эту задачи своими средствами?
163 mistеr
 
10.05.21
16:05
(161) Я имел в виду, что не при каждом поиске индекс создавать. :)
164 mistеr
 
10.05.21
16:08
(162) Добавить колонку, сделать UPDATE SET <колонка> = <выделить нужную часть>
165 evgpinsk_
 
10.05.21
16:11
(163) Так Djelf это понял и привёл пример как анализировать есть ли созданный индекс
(164) Вопрос как выделить нужную часть. Нужно взять всё то правее относительного последнего / в анализируемой строке.
sql язык умеет найти эту последнюю часть текста?
166 Djelf
 
10.05.21
16:12
(163) Индекс же в файле хранится, т.е. в движке sqlite, а не в обвязке для 1C - 1sqlite/
(162) Может, движок sqlite поддерживает индексы на основе выражения, но я этот вариант не пробовал.
Может сработать, а может и нет. Выделение части из строки не очень простой вариант индекса. Лучше отдельный столбец и в него что-то нужно запихнуть.
Либо, не парится, а искать по like, это вероятно не будет слишком медленно...
167 evgpinsk_
 
10.05.21
16:17
в теории like может выдать лишние варианты поиска.
Значит буду делать предобработку CSV
168 mistеr
 
10.05.21
16:30
(165) Нет, последнюю не получится, только первую. Лучше при загрузке выделить.
169 Djelf
 
10.05.21
16:30
(167) У тебя семь пятниц на неделе, сначала ты пишешь "В прайсе есть столбец "IDтовара" по которому будет осуществляться поиск."
Теперь у тебя "индекс нужно строить по части поля столбца, который содержит путь к файлу:"
Нельзя настолько менять условия задачи по ходу дела!

Интересно сколько времени у тебя займет предобработка твоего 700метрового csv...
Видимо задача стоит не ускорять загрузку файла, а наоборот - замедлять! ;)
170 Djelf
 
10.05.21
16:35
(168) Это в больших базах sql не очень сложно, можно и в sqlite например так: https://github.com/mayflower/sqlite-reverse-string
Т.е. реверсируем строку, ищем разделитель, вычитаем, дополняем, выкусываем. Бинго!
Либо пишем свой велосипед...
P.S. давно уже перестал удивляться почему поиск "с начала" везде сделан, а "поиск с конца" почти нигде.
171 mistеr
 
10.05.21
16:38
(170) Либо просто загружаем нормальные данные :)
172 Djelf
 
10.05.21
16:39
И!!! (162) Код товара в файле уникален. А вот код "0cb435a" в строке "http://catalog.onliner.by/cartridges/hp_compat/0cb435a" уникален?
Точно-точно уверен? Ты генерацию этого кода у onliner.by смотрел? В техподдержку писал? Они точно гарантируют уникальность?
173 evgpinsk_
 
10.05.21
16:47
(169) Ну изначально я ведь не знал каким будет итоговое решение )
Поэтому и выразился фигурально про ID товара

Да, уже понимаю, что предобработка тоже время кушать будет, если в лоб решать )

(172) Да, эта часть поля тоже будет уникальным индексом.

Я в DBF файл выгружал и по нему строился индекс. И мой весь движок работы с онлайнером построенном именно на этом индексе (последняя часть html строки товара)
а IDтовара есть только в этом CSV файле и парсить в других местах я его не могу.
174 Arbuz
 
10.05.21
17:07
(170) Ух ты ж! Жемчужина в навозе... А есть собранное? Там же что-то с кодировками в 1C и sqlite?
175 Djelf
 
10.05.21
17:54
(174) Маловато что-то жемчужин в этом * завалялось, подсыпем еще чуток...

Запрос.ВыполнитьЗапрос("ALTER TABLE Price ADD COLUMN СуперКлюч;");
Запрос.ВыполнитьЗапрос("UPDATE Price SET СуперКлюч = replace([Ссылка на товар], rtrim([Ссылка на товар], replace([Ссылка на товар], '/', '')), '');");
Запрос.ВыполнитьЗапрос("CREATE UNIQUE INDEX [idxСуперКлюч] ON [Price]([СуперКлюч]);");
тз=Запрос.ВыполнитьЗапрос("SELECT * FROM Price WHERE СуперКлюч = '006r01177'");
176 evgpinsk_
 
10.05.21
19:37
(175) Это круто.
Но не пойму что за функция Rtrim (par1,par2,par3,par4)  ?

Классически она отсекает пробелы справа в передаваемом параметре и у неё один параметр
177 evgpinsk_
 
10.05.21
19:50
(176) Ошибся, правильно так:
Rtrim (par1,par2)
но всё равно не понятно
178 Djelf
 
10.05.21
20:08
(177) Это магия sql! rtrim не так работает...

Выбери "раз": http://catalog.onliner.by/cartridges/xerox_compat/0006r01046
Убери разделители, это "два": http:catalog.onliner.bycartridgesxerox_compat0006r01046
Откуси справа от того что было в "раз", тем что получилось в "два" сверяя посимвольно справа, это "три": http://catalog.onliner.by/cartridges/xerox_compat/
Замени то что было в "раз" тем что получилось в "три" и получи конфетку: 0006r01046


Кстати, замени

Запрос.ВыполнитьЗапрос("CREATE VIRTUAL TABLE vtPrice USING csvfile('"+ИмяФайлаCSV+"',2,1);");
на
Запрос.ВыполнитьЗапрос("CREATE VIRTUAL TABLE vtPrice USING csvfile('"+ИмяФайлаCSV+"',2,1,'','');");

у меня там косячёк нашелся, без указания этих двух пустых параметров, значения в колонках кое-где съезжают ;(
179 evgpinsk_
 
10.05.21
20:53
(178) "у меня там косячёк нашелся, без указания этих двух пустых параметров, значения в колонках кое-где съезжают ;("

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

Сейчас буду пробовать решить через замену в числовых столбцах запятой на точку
180 Djelf
 
10.05.21
21:11
(179) Ладно, тогда SpecialEdition с отключенной запятой для разделителя: https://cloud.mail.ru/public/yvfM/hHZQEV13a
181 evgpinsk_
 
10.05.21
21:17
(180) Работает )
Параллельно загуглил как через PowerShell производить автозамену в текстовых файлах
182 Djelf
 
10.05.21
21:38
(180) Этот модуль отсюда взят http://www.ch-werner.de/sqliteodbc/
Я там много всякого наковырял, видимо не тестировал с разделителем запятая, либо не попадались такие файлы...
Давно дело было. Оригинальный и вылетал постоянно и тоже что-то с параметрами чудил не понятно. Мой хотя бы не вылетает ;)
Формат csv не сильно стандартизированный - слишком много опций нужно учесть чтобы прочесть ВСЕ возможные варианты.
183 andrewalexk
 
11.05.21
10:12
:)
можно еще проще - без создания избыточных сущностей в сикульной или файловой базе
через команду dos
findstr /I /g:
в текстовый файл
184 Garykom
 
гуру
11.05.21
10:23
я конечно все понимаю но тут вышло не программирование а какое то шамано-эникейство из разрядо дендрофекальных
причем технологии/инструменты вроде и ничего но применяют их через одно место, вместо нормального программирования
185 Djelf
 
11.05.21
10:30
(184) А что не так?
Чем отличается подключение расширения к sqlite от подключения расширения к 1С 8.3?
И чем отличается подключение внешней таблицы от подключения внешних источников данных к 1С 8.3?
Те же яйца, только в профиль...
186 Garykom
 
гуру
11.05.21
10:39
(185) Не люблю когда на конкретную технологию/софт затачиваются без крайней необходимости не для разовой задачи
Лучше все что можно делать своим кодом, чтобы при необходимости легко с dbf на sqlite или mssql или даже posgtresql перейти
187 Garykom
 
гуру
11.05.21
10:43
(186)+ В случае ТС раз у него 77 то смотря файловая или sql надо это и юзать
Т.е. отдельно модуль чтения CSV, отдельно загоняние в DBF (тут для файловой можно хак, создать в 1С 7.7 табличку и ее заполнять внешним а искать/читать уже из базы) или в MSSQL (для SQL версии аналогичный хак можно)
По сути все встроенное и никаких левых лишних инструментов
188 Garykom
 
гуру
11.05.21
10:44
(187)+ Справочник в 1С 7.7 создаем под данные, заполняем его снаружи (как таблицу DBF или MSSQL) а юзаем внутри 1С
189 Djelf
 
11.05.21
11:00
(186) Ты про sqlite3_mod_csv? Ну, да, увы. Сколько не смотрел реализаций этой виртуальной таблицы для sqlite - все они кривые, а из 1251 вообще не умеют импортировать.
В этом модуле, я заново глянул, параметры разделителя были заявлены, но не реализованы.
Можно на Goland слепить аналогично расширение для sqlite - код будет значительно проще, чем на си.
(187) Чем хаки лучше ВК к 1С?

И... в этом файле же 176 колонок! Он целиком в dbf не помещается!
Т.е. нужен не один, а штук 5 справочников...
А дебупликация будет довольно затратной.
Даже на sqlite дедупликация названий магазинов пару минут занимает, а уж на языке 1С - вечность.

Ну а так, да булк-инсерт в mssql и все.
Но и тут тот-же самый булк-инсерт, только в sqlite!
А механизм расширений к sqlite это не хак, это стандартный и часто используемый механизм sqlite...
190 evgpinsk_
 
11.05.21
13:06
(184) Можно чуть более конкретней, как именно читать из CSV в dbf или справочник 1с 200МБ текста за пару минут?
Я вроде как и спрашивал про это в (0), т.к. не знал
191 Djelf
 
11.05.21
13:08
+(189) Специально для любителей Golang. Бинарник и исходники: https://cloud.mail.ru/public/r1Mi/gC37i35yg
А также для сторонников оборачивать все в скрипты...


Оригинальный проект здесь: https://github.com/wiremoons/csv2sql

Все немногочисленные изменения в diff.txt
+ загрузка из кодировки windows-1251
+ замена разделителя на точку с запятой
+ замена двойной кавычки экранирования на одинарную, используемую в sqlite
+ экранирование одинарной кавычки внутри поля

csv2sql.exe -f catalog_prices_2021-05-08_13_05_50.csv -t price
14c
sqlite3.exe prices.db3 ".read SQL-catalog_prices_2021-05-08_13_05_50.sql"
63c
192 evgpinsk_
 
11.05.21
13:12
А  Djelf-у отдельный большой респект, даже не столько в помощи по конкретной задаче, сколько в раскрытии самих технологий. Для меня и думаю для многих именно это самое важное.
193 Garykom
 
гуру
11.05.21
13:28
(190) файлик делится на несколько в несколько потоков (по числу ядер проца) пишется
194 Garykom
 
гуру
11.05.21
13:30
(191) У тебя учетки что ли нет на гитхабе? Заведи, форкни и свои изменения туда
195 evgpinsk_
 
11.05.21
13:35
(193) И это не будет "шамано-эникейство" ? ))
Если делать штаными средствами в лоб, то вместо 30 минут потратим 20 ? )
196 Garykom
 
гуру
11.05.21
13:36
(195) Это не шаманство в отличие от разных извратов с екселями и прочими а обычное программирование
Фоновые задания даже в 1С есть в 8.3 и многопоточность используют очень часто
И не 20 минут а в лучших случаях можно за пару минут
197 evgpinsk_
 
11.05.21
13:46
(196) В данной теме итоговое решение - не имеет отношения к екселю а использует импорт данных из исходного CSV в 1sqlite.
Напомню что исходный CSV файл - это 230Мб текста, около 700тыс строк и динамические столбцы с ценами магазинов на товары.
Просто импорт первых 7ми столбцов в лоб занимает несколько минут, что терпимо, если же также в лоб читать и обрабатывать все остальные 170 столбцов - время критически растёт.
И делить файл на части - это и есть костыльное решение проблемы. Всё равно оно будет больше 10минут.
Во всей этой теме я увидел конкретный дельный совет, (который смог понять) только от  Djelf.
Возможно тут были и другие решения, но я как-то их не заметил
198 Garykom
 
гуру
11.05.21
13:53
(197) просто у кого то "Смотрю в книгу — вижу фигу" ))

а бесплатно за другого (он же зп получает наверно да?) готовый код кодить мне влом, писал только советы как можно
199 RomanYS
 
11.05.21
13:55
(196) Разве у ТСа ни клюшки? В 8.3 и стандартных средств будет достаточно чтобы быстро прочитать текстовый файл и найти нужную строку
200 pechkin
 
11.05.21
13:56
(199) вопрос в скорости
201 Garykom
 
гуру
11.05.21
13:57
(199) Да у ТС 77, но это не запрещает юзать параллельную загрузку в несколько потоков
202 Garykom
 
гуру
11.05.21
13:59
(201)+ Чисто технически даже если файловая на dbf то зная размер записи и их кол-во легко можно разделить файл на куски, и отдельно их записать в несколько потоков
203 RomanYS
 
11.05.21
14:01
(200) ЧтениеТекста и строковые функции в снеговике достаточно быстрые. Я так понимаю задачи распарсить весь файл нет, нужно найти только конкретные ID
204 Garykom
 
гуру
11.05.21
14:02
(203) там файл csv 700к строк 260 метров
205 RomanYS
 
11.05.21
14:04
(204) гиговых файлах делал тысячи замен подстрок. Затыков в производительности не было
206 pechkin
 
11.05.21
14:04
(203) в среднем нужно будет читать половину файла каждый раз. в худшем - весь
207 RomanYS
 
11.05.21
14:07
(206) что значит "каждый раз"? Файл же каждый раз новый, естественно не прочитав файл информации не получишь
208 Mikeware
 
11.05.21
14:26
(207) он же не "одну позицию" в каждом новом файле ищет...
при каждом поиске - полфайла в среднем. это дофига.
209 Garykom
 
гуру
11.05.21
14:29
(208) Поэтому надо сделать индекс, куда его засунуть пофиг и читать не весь файл а сразу нужное место его
Для этого для простоты и сразу сделать индекс банально расфигачить один 260 метровый файл на 700к мелких файликов в каждой одна строка а имя файлика это поле для поиска ))
210 RomanYS
 
11.05.21
14:30
(208) Сколько позиций? Если их не сотни, то можно читать файл и в каждой прочитанной строке искать по списку ИД.
211 Mikeware
 
11.05.21
14:33
(209) ну так два пути - 1)читать текстовый файл, делать к нему индекс, и пользоваться. 2)грузить текстовый файл в табличку, индексировать, и пользоваться. (какая уж это табличка - Sqlite, любого SQL, dbf (или сразу в объектном виде)) - уже непринципиально
212 Mikeware
 
11.05.21
14:33
(210) сколько строк - столько позиций
213 RomanYS
 
11.05.21
14:33
(200) вот тупой замер построчного чтения указанного файла и поиска одной подстроки на средненьком ноуте
Пока Стр <> Неопределено Цикл    680 076 раз    1,944879 сек
Стр = Чт.ПрочитатьСтроку();    680 075    раз    12,735628 сек
Поз = СтрНайти(Стр, "012345");    680 075    раз    4,440355 сек
214 RomanYS
 
11.05.21
14:36
(212) А! Ему все данные нужны... тогда понятно зачем мутить с промежуточной базой.
Я думал, ему какие-то конкретные ID из всего файла
215 Garykom
 
гуру
11.05.21
14:38
(214) И у него 7.7
216 Mikeware
 
11.05.21
14:39
(214) ну ему прайс приходит, он хочет либо продавать "не дешевле" (или не сильно дороже), или "перекупаться". Эх, прям как в середине 90-х...
217 Garykom
 
гуру
11.05.21
14:39
(215)+ Ему уже несколько вариантов предложено
От загрузки в dbf/sql (причем можно и в саму 1С) до разбиения на файлики и поиск это тупо открыть файл с нужным именем
218 Mikeware
 
11.05.21
14:39
(215) индекс для текстового можно и на клюшках построить.
219 Garykom
 
гуру
11.05.21
14:40
(218) Файл такой штатными без внешних не прочитаешь на 77
220 Mikeware
 
11.05.21
14:40
(217) а ФС не сдохнет?
221 Mikeware
 
11.05.21
14:41
(219) да и насрать. я никогда не был адептом "вах, неодобреные БоГом ВК -низянизянизя"
222 RomanYS
 
11.05.21
14:42
(215) Это понятно. Я отчасти поэтому в ветку не заглядывал, казалось что всё это костылестроение из-за невозможности быстро прочитать текстовый файл в клюшках.
223 Garykom
 
гуру
11.05.21
14:43
(220) А не похер?
Да и не должна, у меня в папке windows свежеустановленной 209к файлов
224 Mikeware
 
11.05.21
14:53
(223) ну если только по подпапкам разбивать... такая "ленивая прединдексация"...
225 ДенисЧ
 
11.05.21
14:56
(220) (224) Ты что, собрался файлик посимвольно по разным файлам раскидывать?
226 Garykom
 
гуру
11.05.21
15:02
(225) есть смысл раскидать по подпапкам с учетом символов индекса
для "нечеткого поиска"
227 Djelf
 
11.05.21
15:04
Просто оставлю это здесь...
sqlite 35% Faster Than The Filesystem https://www.sqlite.org/fasterthanfs.html
228 Garykom
 
гуру
11.05.21
15:06
(227) с этим никто не спорит
только in memory еще быстрей и что? а фс на ramdrive ?
229 Mikeware
 
11.05.21
15:06
(225) не, не посимвольно... имя файла=имени номенклатуры. содержимое файла - строка цен.
т.е. по сути, перекладывание проблем индексации на ФС.
230 evgpinsk_
 
11.05.21
15:07
Читаю последние сообщения и не догоняю ).
Вот ведь теоретическое нормальное решение (211) , которое в теории было понятно и в (0)
Вопрос стоял только в технической реализации.
Как технически быстро запихнуть 230Мб текста в dbf или sql.

Зачем тут мудрить с разбитием исходного CSV на несколько подфайлов?? Зачем такие заморочки.
Когда парсинг через НУЖНЫЙ инструмент занимает до 1й минуты.

Нужные инструменты это или существующие готовые скрипты CSVtoDBF - но я находил только платные.
Если делать это руками штатными средствами 1с - тогда это десятки минут.
Либо предложенный 1sqlite который CSVtoDB3 делает меньше чем за 60 секунд
231 Garykom
 
гуру
11.05.21
15:08
(229) это я несколько раз и предлагал
232 evgpinsk_
 
11.05.21
15:08
(229) Да, либо "имя файла=имени номенклатуры"
233 Garykom
 
гуру
11.05.21
15:09
(230) >Если делать это руками штатными средствами 1с - тогда это десятки минут.

просто кто то херовый программист с ограниченным кругозором
234 Garykom
 
гуру
11.05.21
15:10
(233)+ штатными средствами 1С 7.7 и операционной системы (начиная с winxp) все делается и намного быстрей
235 Mikeware
 
11.05.21
15:11
(233) он просто жадный директор
236 evgpinsk_
 
11.05.21
15:20
(233) Мне казалось это очевидно. Такие вопросы как в (0) задают крутые программисты??
237 Djelf
 
11.05.21
15:28
(236) Да! "Гений 1С" подобные темы создает по 10 раз в день...
238 Mikeware
 
11.05.21
15:30
(237) так то ж фикса. он не какой-то "крутой программист", он "гени[т]альный..."
239 Garykom
 
гуру
11.05.21
15:36
(238) это я тоже фикса и что? ну это кроме фри
он просто засиделся на одном месте и почти утонул в болоте
240 Mikeware
 
11.05.21
15:54
(239) ты фикса с Фиксиным не путай
241 andrewalexk
 
12.05.21
20:26
242 Mikeware
 
13.05.21
12:00
243 Кирпич
 
13.05.21
12:30
А я, кстати, настрочил утилитку csv2dbf. Cоздает dbf из csv. Может делить csv вдоль и поперек(вынимать отдельные столбцы и делить на несколько dbf файлов). Работает шустро. Файл автора (700 тыс строк и 175 столбцов) обрабатывает за 5 секунд.

Usage: C:\temp\csv2dbf\csv2dbf.exe [<options>] <input csv file name> [<out dbf file name>]
Options:
-h  --help show help
-b  --showtime - show execution time
-d  --delimiter -column delimiter ("," or ";" or "tab" default ";")
-p  --skipfirst - skip first line in csv
-t  --dbfcount=<number> - split all records to <number> dbf files
-c  --cols=<number,number,...> - take columns only from the list <number,number,...>
-n  --colnames=<string,string,...> - list of columns for dbf (number of column names must match cols parameter)
Examples:
  1) csv2dbf --skip=true --split=3 --cols=3,4,8 --colnames=ID,NAME,PRICE c:\temp\price.csv c:\temp\price.dbf
  2) csv2dbf -s true -p 3 -c 3,4,8 -n ID,NAME,PRICE c:\temp\price.csv c:\temp\price.dbf
  3) csv2dbf --cols=1,2,3,8,9 c:\temp\price.csv c:\temp\price.dbf
  4) csv2dbf c:\temp\price.csv
244 Garykom
 
гуру
13.05.21
13:13
(243) Допили утилитку чтобы .DD или .DDS читал и данные засовывал в нужные/указанные sc* и продай ТС
245 Garykom
 
гуру
13.05.21
13:14
(244)+ только вместо кучи параметров один файл настроек чтобы
246 Mikeware
 
13.05.21
13:21
(245) и вместо файла - гуй
247 Кирпич
 
13.05.21
13:29
(244) "в нужные/указанные sc*" Это не нужно и сложно(индексы и всё такое). Да автор свою проблему уже решил.
(245) Да в bat файл написать все параметры и хватит
248 Garykom
 
гуру
13.05.21
13:36
(247) Так и индекс создавай заодно
249 Злопчинский
 
13.05.21
13:37
(243) глумишься? ссылка на скачивание - где? ;-)
250 Кирпич
 
13.05.21
13:41
(249) Ссылки еще нету. Завтра красоту наведу и покажу. Сегодня у меня покос травы.
251 Злопчинский
 
13.05.21
13:46
Покос Травы, Газон Засеян - армяне что ли в гости приезжают?
252 Кирпич
 
13.05.21
14:33
(251) Тёща
253 Кирпич
 
13.05.21
18:42
(249) От она https://dropmefiles.com/qNnNg

Usage: csv2dbf.exe [<options>] <input csv file name> [<out dbf file name>]
Options:
-h  --help show help
-b  --showtime - show execution time
-d  --delimiter - column delimiter ("," or ";" or "tab" default ";")
-p  --skipfirst - skip first line in csv
-t  --dbfcount=<number> - split all records to <number> dbf files
-c  --cols=<number,number,...> - take columns only from list <number,number,...>
-n  --colnames=<string,string,...> - list of columns for dbf (number of column names must match cols parameter)
Examples:
  1) csv2dbf --skipfirst --dbfcount=3 --cols=3,4,8 --colnames=ID,NAME,PRICE c:\temp\price.csv c:\temp\price.dbf
  2) csv2dbf -p 3 -c 3,4,8 -n ID,NAME,PRICE c:\temp\price.csv c:\temp\price.dbf
  3) csv2dbf --cols=1,2,3,8,9 c:\temp\price.csv c:\temp\price.dbf
  4) csv2dbf c:\temp\price.csv
254 Злопчинский
 
13.05.21
18:48
(253) взял, нехай будет
255 Garykom
 
гуру
13.05.21
18:56
(253) кинь на гитхаб исходники допилю
и у тебя корректно разбирает если разделитель внутри строковых полей?
256 Кирпич
 
13.05.21
19:10
(255) попробуй. Я сильно не тестировал
257 Кирпич
 
13.05.21
19:20
Такое должна разбирать
"Раз два ;три";"раз ""два"" три"
258 Кирпич
 
13.05.21
20:08
Один косяк нашел.
Вот такое не корректно разбирает
Раз "два" три;раз два три
259 Кирпич
 
13.05.21
20:10
260 Djelf
 
14.05.21
11:07
(259) Нереально быстро пережевывает!
Я так понимаю csv весь в память сначала забирается, т.е. ограничение на объем есть?
261 Кирпич
 
14.05.21
11:56
(260) ага. потом доработаю
262 Кирпич
 
14.05.21
11:57
но вряд ли у кого гиговые csv бывают
263 Кирпич
 
14.05.21
12:08
ну и тупо 64 битный exe сделать можно
264 Кирпич
 
14.05.21
12:31
Добавил x64 и с ковычками подшаманил. Теперь разбирает такую пургу
"one" two;"one two";one "two";100
"on""e""" two;"one two";one "tw""zzz""o";"200"
"on""e""" two;"one two";one "tw""zzz""o";Иванов "200"
"on""e""" two;"one two";one "tw""zzz""o";"Иванов" "200"

https://dropmefiles.com/okW1r

На счет памяти. Я использую memory-mapped https://docs.microsoft.com/en-us/dotnet/standard/io/memory-mapped-files. Но я тупо весь файл маплю. Не охота было заморачиваться кусками.
265 Кирпич
 
14.05.21
12:33
266 Garykom
 
гуру
14.05.21
12:45
(258) >Раз "два" три;раз два три

эээ по правилам валидного CSV должно быть
"Раз ""два"" три";раз два три
267 Кирпич
 
14.05.21
12:53
(266) так оно вроде и то и то съест
268 Djelf
 
14.05.21
13:45
(265) Работает. И х32 и х64. Но создает dbf больше 2х гигов, понятно что это обходится с помощью --dbfcount, но может стоит автоматом, после достижения 2х гигов разбивать?
269 Djelf
 
14.05.21
13:55
+(268) Или даже лучше ключ --split=len
270 pechkin
 
14.05.21
14:09
а что на гитхабе не выложишь?
271 Кирпич
 
14.05.21
14:19
Ну может потом сделаю автоматом. Просто думаю, что лучше фиксированное количество файлов. Потом просто знаешь количество файлов и не надо вычислять в 1с сколько их там нагенерило.
272 Кирпич
 
14.05.21
14:20
(270) выложу. Потестирую немножко.
273 Djelf
 
14.05.21
15:17
(271) Разбивка на фиксированное количество кусков имеет право на жизнь.
Но вот например так: нужно потом добавить пару колонок, и можно примерно вычислить какой изначальный объем потребуется, чтобы перебора не было.
А точно количество файлов не так существенно, это перебором в каталоге легко вычисляется...

Вот дедупликацию бы прикрутить! О... это было бы мегакруто!
274 Кирпич
 
14.05.21
15:39
чо такое дедупликация
275 Кирпич
 
14.05.21
15:39
?
276 Кирпич
 
14.05.21
15:42
"Но вот например так: нужно потом добавить пару колонок, и можно примерно вычислить какой изначальный объем потребуется, чтобы перебора не было. "
это вабще не понял
277 Злопчинский
 
14.05.21
15:51
(274) https://ru.wikipedia.org/wiki/Дедупликация
- видимо Djelf имел в виду приапменение на этапе чтения исходных данных... тогда можно впихнуть в память бОльший массив
278 Djelf
 
14.05.21
15:57
(274) дедупликация? Выкидывание группы полей в отдельную таблицу с заменой ссылок на ключевое поле в исходной таблице.
Я попробовал нарисовать для таблицы которую прислал (0) на триггерах sqlite, не так плохо получилось ~2-3 минуты (переменных в sqlite нет, это иногда выбешивает).
(276) см. пост (162) для (0) потребуется отдельная колонка для индекса и ее придется добавить и файл может стать слишком большим!
279 Djelf
 
14.05.21
16:22
+(278) ИМХО ключ примерно такой "--dedup=code43,code44:code.dbd:into:code43"
280 Кирпич
 
14.05.21
16:47
(278) Ну выгрузи какие надо столбцы в одну таблицу, другие столбцы в другую. Запусти просто несколько раз  с разными параметрами. Одновременно запустишь пару-тройку csv2dbf, будет то же время :)
281 Кирпич
 
14.05.21
16:48
(280) Типа
-c 1,2,3,4,5 test.csv test1.dbf
-c 1,6,7,6,9 test.csv test2.dbf
282 Djelf
 
14.05.21
16:52
(281) А ссылку то как получить на поле из новой/дополнительной таблицы в оригинальную?
283 D3O
 
14.05.21
16:54
(0) вдруг никто еще не предлагал - пробовать затягивать в sqlite - под 7.7 он в отличнейшей обертке есть от Орефкова, кажется. скорее всего сам sqlite имеет механизм подключения к csv. а уж дальше с его помощью все должно получиться крайне быстро.
284 Кирпич
 
14.05.21
16:54
(282) Ну у тебя же есть ключевое поле. Копируй его во все таблицы
285 Кирпич
 
14.05.21
16:59
Для (0) можно просто обойтись разделением на несколько dbf и потом, для поиска, искать во всех dbf по очереди.
286 Кирпич
 
14.05.21
17:01
(283) уже так и сделали
287 Djelf
 
14.05.21
17:02
(284) Посмотри что у меня получается: https://cloud.mail.ru/public/HUSG/y6xkTfR9S
Так быстрее будет...
288 Кирпич
 
14.05.21
17:06
(287) Куда еще быстрее? 5 сек и получаем 4 dbf. 5 секунд на индексирование ключевого столбца в dbf. 10 секунд в день - вполне приемлемо. У нас же не олимпиада по быстрой загрузке csv
289 Djelf
 
14.05.21
17:09
(288) Я не про время импорта написал, а про дудупликацию (про структуру импортируемых таблиц).
А если бы была Олимпиада, то ты, без вариантов, победитель. Скорость, импорта, повторяю, невероятная!
290 Кирпич
 
14.05.21
17:15
(289) у меня на этом компе не чем смотреть sqlite базы
ну вот же ддедупликация. Не?

-c 1,2,3,4,5 test.csv test1.dbf
-c 1,6,7,8,9 test.csv test2.dbf

ключ в столбце 1
291 Кирпич
 
14.05.21
17:23
Надо в sqlite попробывать еще. Может тоже секунд за 10 всосёт
292 Кирпич
 
14.05.21
17:23
пардон за попробывать
293 Djelf
 
14.05.21
17:26
(290) Не! Я же не смогу подменить поле на ключ при загрузке!
Эта штука бесплатная: http://www.sqliteexpert.com/download.html

Магазины. Их всего 174, их пишем в отдельную табличку, но их в csv очень много дублируется. Просто +экономия места и +поиск по ключу.
294 Кирпич
 
14.05.21
17:37
(293) А. Дошло. Столбцы в строки переделать.
295 Djelf
 
14.05.21
17:47
(294) Это был следующий (второй) этап дедупликации, на первом было бы достаточно свернуть Раздел,Производитель и т.п.
Магазины же в кросс-таблице, это без дополнительного скрипта сложно сделать. Можно, но не универсально.

Для sqlite свертка магазинов как то так выглядит:

        ЗапросТриггераПрайс = "";
        Для НомерМагазина=1 По КоличествоМагазинов Цикл
            ЗапросТриггераПрайс = ЗапросТриггераПрайс+"
            |INSERT OR IGNORE INTO Прайс(
            |    Магазин,
            |    Товар,
            |    Цена,
            |    СрокДоставки
            |) VALUES (
            |    (SELECT Код FROM Магазины WHERE new.[Магазин "+НомерМагазина+"] IS NOT NULL AND Наименование = new.[Магазин "+НомерМагазина+"] LIMIT 1),
            |    (SELECT Код FROM Товары WHERE new.[Магазин "+НомерМагазина+"] IS NOT NULL AND Код = new.[ID товара] LIMIT 1),
            |    new.[Цена "+НомерМагазина+"],
            |    new.[Срок доставки "+НомерМагазина+"]
            |);"
        КонецЦикла;
296 Кирпич
 
14.05.21
17:50
(295) Ну это пусть автор извращется. Далеко не у каждого такие проблемы.
297 Garykom
 
гуру
14.05.21
17:50
Вы только до http сервиса удобного с автоматическим обновлением там прайса и готовыми модулями для разных 1С не доберитесь случайно
298 Кирпич
 
14.05.21
17:53
(287) Нифига ты ему забабахал. Нахаляву чтоли?
299 Djelf
 
14.05.21
17:54
(296) Я просто обновлял в своей памяти работу с триггерами! Забывается же все постепенно...

(297) А в чем проблема прикрутить сервис на Golang? БД есть, как быстро заполнить уже понятно. Минут 10-15 работы ;)
300 Garykom
 
гуру
14.05.21
17:56
(299) бесплатно? только если как пет-проекта для портфолио на гитхабе
301 Кирпич
 
14.05.21
18:01
Если извращаться со всякими дедупликациями, то для этого питон есть. Надо попробовать чо получится по времени.
302 Djelf
 
14.05.21
18:02
(300) Это же только для себя, любимого забесплатно! Тут нужно недели две на согласование API и ABI... А это совсем не бесплатно ;)
303 Кирпич
 
14.05.21
18:09
Гы. Сколько параметров должно быть у csv2dbf

https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.read_csv.html
304 Garykom
 
гуру
14.05.21
18:20
(303) поэтому и сразу написал выноси в файл настроек операции и только один параметр у csv2dbf - имя файла настроек
305 Djelf
 
14.05.21
18:23
(303) Мне кажется и этого не хватит, на все креативные файлы....
306 evgpinsk_
 
16.05.21
13:33
(287) Уж ты, упустил ветку. Да, очень не плохие вещи )
Больше для себя, что бы не пропало:
https://drive.google.com/drive/folders/1fndNmavzk9KQJ9DUcQPOzdgQXwa02Mcm?usp=sharing

красивая БД:
https://prnt.sc/12zs75d
307 evgpinsk_
 
16.05.21
13:45
(265) Тоже круто - exe для чтения CSV в DBF
И этот способ попроще для многих чем 1sqlite использовать )
308 ДедМорроз
 
16.05.21
17:42
База sqlite сама по себе не быстрая,т.к.в отличие от dbf имеет страничную структуру.
Лучше сунуть нос в сторону ms sql express и в нем bulk insert.
309 Кирпич
 
16.05.21
18:05
(308) Глупости говорите. Sqlite Побыстрее ms sql express будет. А страничная структура к быстродействию вообще не имеет никакого отношения. Sqlite не предназначена для многопользовательской работы и клиент-сервера. Если её использовать только для чтения (как и нужно автору), то она быстрая как чёрт.
310 ДедМорроз
 
16.05.21
23:12
Журнал регистрации 1с в некоторых версиях на sqlite,и что-то быстроты там не видно.
311 trdm
 
17.05.21
06:50
(308) да, она временами не быстрая. Транзакцию надо использовать.
312 trdm
 
17.05.21
06:53
(0) > Необходим быстрый поиск информации в больших CSV файлах
Надо напомнить, то csv файлы - текстовые, и доступ там последовательный. Т.е. что-бы что-то найти надо пробежать практически весь файл. Тогда как реляционки с индексами - имеют произвольный сопоб доступа.
313 Кирпич
 
17.05.21
07:59
(310) ну вот как раз пример как не надо использовать sqlite
314 Garykom
 
гуру
17.05.21
08:00
(312) Хочу напомнить что зависит от размера csv файла
На размере как у ТС можно весь закинуть в память и даже полным сканированием достаточно быстро "в пределах нескольких секунд" находить
315 Garykom
 
гуру
17.05.21
08:01
(314)+ В смысле сейчас когда объем памяти даже офисных машинок от 8 гигов это норма
Раньше согласен приходилось извращаться с какими то базами и индексами, сейчас можно решать задачу тупо в лоб
316 evgpinsk_
 
17.05.21
08:57
(314) Вот как-раз следующий вопрос частично касается этого.
Я замарочился (пришлось вспоминать синтаксис SQL) и привёл db3 базу исходного CSV файла к нормализованному виду:
вместо одной таблицы, в которой цены магазинов в столбцах одной тоблицы, использую 5 табличек.
https://prnt.sc/130xbq3
Таблица Прайс имеет вид:
идТовара   (создан индекс по полю)
идМагазина
Цена

Но не пойму механизм использования индекса. Почемуто этот запрос:
    ТекстЗапроса="SELECT Магазины.Наименование, Прайс.Цена, Прайс.СрокДоставки
    |FROM (Прайс INNER JOIN Товары ON Прайс.Товар = Товары.Код) INNER JOIN Магазины ON Прайс.Магазин = Магазины.Код
    |WHERE (((Товары.СуперКлюч)='"+СокрЛП(ТМЦ.МодельНаОнлайнере)+"'))";

не использует индекс, т.к. время его отработки у меня составляет 370 милиСек
что в 20 раз больше чем обычный запрос
Select
к ненормализованной исходной таблице price.db3  - около 15 милиСек

Вопрос : что я сделал не так?
317 evgpinsk_
 
17.05.21
09:05
(314) В моём случаем поиск "несколько секунд" - это многовато. Пользователь находится в счёте, и нажимает кнопку на товарах, чтобы быстро посмотреть цены конкурентов.
Здесь отклик желателен в милисекунды
318 Ёпрст
 
17.05.21
09:16
(316) код, канечна адок.
Хотя бы where перенеси в join, для начала
319 Djelf
 
17.05.21
09:21
(316) Для начала запусти analyze, затем, если не сработает explain query plan select...
Ну и лучше не использовать inner join, а использовать left join, т.е. сначала отобрать Товары по ключу, а потом уже к таблице товары клеить Прайс.
320 evgpinsk_
 
17.05.21
09:27
(318) Не силён в составлении sql запросов. Понимаю, но с нуля сложновато их писать. Беру код, который строит msAccess, и он именно так написал код
Графическое представление
https://prnt.sc/130yoc1
я не вижу здесь ошибки, запрос построен помоему верно.
и вот текстом этот же запрос:

SELECT Прайс.Товар, Прайс.Магазин, Прайс.Цена
FROM (Прайс INNER JOIN Магазины ON Прайс.Магазин = Магазины.Код) INNER JOIN Товары ON Прайс.Товар = Товары.Код
WHERE (((Товары.КодОнлайнера)="Экземпляр"));
321 Garykom
 
гуру
17.05.21
09:30
(316) Нафик нормализовывать если это не требуется?
322 evgpinsk_
 
17.05.21
09:32
(321) Согласен, просто нравится когда красиво, да и не забыл ещё немного уроки института )
Тут вопрос больше теоретический, каким образом работаем механизм использования индексов СУБД "SQLiteBase"

В простейшем случае когда выборка из одной таблицы - он используется. Но когда в запросе несколько таблиц, почемуто нет.
Ведь явно его както в коде 1с не нужно задавать?

Если ответ с ходу не виден - тогда можно забить
323 acanta
 
17.05.21
09:35
А индекс может отвалиться из за вот этих вот сокрлп() и т.п.?
324 evgpinsk_
 
17.05.21
09:37
(323) Разве сокрЛП() имеет отношение к индексу?. Функция просто в текст запроса передаёт верно параметр
325 evgpinsk_
 
17.05.21
09:39
(319) Поменял на left join, стало быстрее,
    ТекстЗапроса="SELECT Магазины.Наименование, Прайс.Цена, Прайс.СрокДоставки
    |FROM (Прайс LEFT JOIN Товары ON Прайс.Товар = Товары.Код) LEFT JOIN Магазины ON Прайс.Магазин = Магазины.Код
    |WHERE (((Товары.СуперКлюч)='"+СокрЛП(ТМЦ.МодельНаОнлайнере)+"'))";

но индексы всё равно не используются.
Сейчас Результат возвращается за 2800 милиСЕк
Напомню что из ненормализоваенной таблицы по ключу Товары.СуперКлюч
результат возвращается за 28 милисекунд
326 Djelf
 
17.05.21
09:46
(325) Что по твоему делает этот код? FROM (Прайс LEFT JOIN Товары ON Прайс.Товар = Товары.Код)
Он перебирает весь прайс и ко всему прайсу клеит товары. И только потом ставит фильтр на Товары.СуперКлюч
Наоборот пиши: FROM Товары LEFT JOIN Прайс ON Прайс.Товар = Товары.Код
327 evgpinsk_
 
17.05.21
09:48
А не может быть медленный поиск связан с тем что в нормализованной таблице 'прайсы' строк в пять раз больше чем в не нормализованной? Маловероятно но всё же.
328 evgpinsk_
 
17.05.21
09:48
(326) понял через час приеду и попробую исправить
329 Кирпич
 
17.05.21
10:01
(327) Конечно может. Особенно если индексов нет.
330 Djelf
 
17.05.21
10:14
Да есть у него индекс по товару. Это оптимизатор sqlite дурит...
Что-то я помню такого странного поведения. Решается плюсом перед Товары.Код.
FROM Товары LEFT JOIN Прайс ON Прайс.Товар=+Товары.Код
331 trdm
 
17.05.21
10:32
(321) > Нафик нормализовывать если это не требуется?
Бест практих под хайлоад
332 Garykom
 
гуру
17.05.21
10:40
(331) хайлоад это отказ от sql, использование in-memory database и баз типа ключ-значение
причем делают всевозможные значения на которые навешивают нужное явно отказываясь от нормализации в угоду скорости ответа
333 Garykom
 
гуру
17.05.21
10:42
(332)+ в случае 1С 7.7 это написание ВК, которая грузит CSV в оперативку и затем мгновенно отвечает
334 trdm
 
17.05.21
11:05
(332) нет, это набор правил для разруливания высоких нагрузок.
Отказ от скуля тут не принципиален.
335 trdm
 
17.05.21
11:06
+ ты же в курсе, что скуль сам загоняет наиболее юзабельные части данных в оперативку?
336 Кирпич
 
17.05.21
11:14
(333) Для этого и ВК не надо. Есть же WSH. Да и грузить всё в память несчастной семерки это жестоко.
337 evgpinsk_
 
17.05.21
12:42
(326) (330)
Мне предполагается что действительно "дурит оптимизатор sqlite  SQL кода "
перенёс в MSAccess эти таблицы (прайс 2,1млн строк, товары 700тыс строк)
и этот же запрос в нём отрабатывается мгновенно, десятые доли секунды
SELECT Товары1.СуперКлюч, Магазины1.Наименование AS Магаз, Товары1.Наименование AS Товар, Прайс1.Цена, Прайс1.СрокДоставки
FROM (Прайс1 INNER JOIN Товары1 ON Прайс1.Товар = Товары1.Код) INNER JOIN Магазины1 ON Прайс1.Магазин = Магазины1.Код
WHERE (((Товары1.СуперКлюч)="usb08087805"));

он же в графической форме:
https://prnt.sc/1315k2x
338 evgpinsk_
 
17.05.21
13:06
(318) > Хотя бы where перенеси в join, для начала

   ТекстЗапроса="SELECT Магазины.Наименование, Прайс.Цена, Прайс.СрокДоставки
    |FROM (Прайс INNER JOIN Товары ON Прайс.Товар = Товары.Код) INNER JOIN Магазины ON Прайс.Магазин = Магазины.Код
    |WHERE (((Товары.СуперКлюч)='"+СокрЛП(ТМЦ.МодельНаОнлайнере)+"'))";

было бы интересно попробовать, но не знаю как )
нужно решать через Запрос в Запросе?
339 Djelf
 
17.05.21
13:07
(337) Еще раз повторяю - поставь + перед Товары1.Код
Т.е. на так  ON Прайс1.Товар = Товары1.Код, а вот так  ON Прайс1.Товар = +Товары1.Код
340 Ёпрст
 
17.05.21
13:11
(338) че как ? выкинь where и в своём inner join воткни and Товары.СуперКлюч =
341 Ёпрст
 
17.05.21
13:15
или так, хотя бы:


|SELECT Магазины.Наименование, Прайс.Цена, Прайс.СрокДоставки
|from Товары
|left join Прайс on Прайс.Товар = Товары.Код
|left join Магазины on Прайс.Магазин = Магазины.Код
|WHERE Товары.СуперКлюч ='"+СокрЛП(ТМЦ.МодельНаОнлайнере)+"'";
342 evgpinsk_
 
17.05.21
13:54
(339) Забыл отписать, плюсики не меняют ситуацию, индекс не задействуется
(340) (341)  сейчас попробую
343 evgpinsk_
 
17.05.21
14:16
(341) Это помогло, вместо 2000 мсек стало 300мсек
не уверен  что это правильный результат, т.к. напомню в не оптимизированном сплошном прайсе из одной таблицы поиск длится 15 милисек
344 evgpinsk_
 
17.05.21
14:21
п.с. Сейчас заметил свою ошибку, я в таблице Прайс забыл сделать индекс по полю Магазин
а оно используется в join

Хотя странно, добавление индекса по полю Магазин не повлияло на скорость - сейчас теже 300 милисек

Итого имеем , что поиск в базе из 3х оптимизированных таблиц в 20 раз медленнее (0,3сек) чем в одной сплошной таблице (0,015сек).
п.с.с. Вопрос имеет чисто теоретический интерес, на него можно смело забить )
345 Djelf
 
17.05.21
14:45
(342) Та какую версию 1sqlite то используешь? Небось какую-то древнюю? Возьми мою сборку посвежее https://cloud.mail.ru/public/9znr/ZJ6ULE9aR
В старых версиях довольно плохой планировщик, он очень плохо переваривает inner join.
Более новая должна давать результат примерно соответствующий (343). Вот теперь плисик туда добавь и станет 1-2 микросекунды.
Но ты же посмотрел explain query plan select... как я советовал.
У тебя план запроса примерно такой
id    parent    notused    detail
3    0    0    SEARCH TABLE Товары USING INTEGER PRIMARY KEY (rowid=?)
6    0    0    SCAN TABLE Прайс
Индекс по товару в Прайсе не используется. А не используется потому что во-первых это не очень хороший индекс (много дублей), а во вторых без плюсика, который подавляет использование ключевого индекса в Товарах sqlite дуркует.

Но можно не только плюсиком заставить sqlite использовать этот индекс, вот так вот должно работать, см. план ниже
LEFT JOIN Прайс INDEXED BY Товар ON Прайс.Товар = Товары.Код

id    parent    notused    detail
4    0    0    SEARCH TABLE Товары USING INTEGER PRIMARY KEY (rowid=?)
7    0    0    SCAN TABLE Прайс USING INDEX Товар
346 Djelf
 
17.05.21
14:49
(344) При запросе используется только один индекс! Индекс по Магазину никак не мог изменить скорость выборки.
Ну и чему ты в (344) удивляешься? Ясное дело, что запрос к плоской таблице по уникальному индексу будет быстрее.
347 pechkin
 
17.05.21
14:56
(346) 2 разных индекса никак не могут использоваться для поиска записи
348 evgpinsk_
 
17.05.21
14:57
(345) Чудеса бывают, плюсик помог на свежей версии 1sqlite )

    ТекстЗапроса="SELECT Магазины.Наименование, Прайс.Цена, Прайс.СрокДоставки
    |FROM Товары    
    |LEFT JOIN Прайс ON Прайс.Товар = +Товары.Код
    |LEFT JOIN Магазины ON Прайс.Магазин = +Магазины.Код
    |WHERE Товары.СуперКлюч ='"+СокрЛП(ТМЦ.МодельНаОнлайнере)+"'";

поиск стал вместо 300 мСек 30 мСек
а когда добавил индекс и на Магазин то 8 мСек
:)
349 evgpinsk_
 
17.05.21
15:01
(347) Верно. просто значит первая попытка без кеша (поэтому более медленная)
Добавление индекса по полю Магазин - не увеличивает скорость
сейчас она стала 8мСек

помогла свежая версия 1sqLite и плюсики в тексте запроса
350 Djelf
 
17.05.21
15:07
(349) Базу то скинь, с которой работаешь. 30мс в (348) ИМХО слишком долго! Должно быть 0-1мс.
351 evgpinsk_
 
17.05.21
15:10
Ну и самый прикол что поиск длиться теже 8 мСек в моём первоначальном запросе из (316)  :)

    ТекстЗапроса="SELECT Магазины.Наименование, Прайс.Цена, Прайс.СрокДоставки
    |FROM (Прайс INNER JOIN Товары ON Прайс.Товар = Товары.Код) INNER JOIN Магазины ON Прайс.Магазин = Магазины.Код
    |WHERE (((Товары.СуперКлюч)='"+СокрЛП(ТМЦ.МодельНаОнлайнере)+"'))";
352 evgpinsk_
 
17.05.21
15:12
(350) Сейчас результат на любых вариантах Select  - 8мСек

30мСек в (348) - был глюк первого запуска. Заметил что иногда первый запускает тормозит. Потом все пыпытки стабильно 7-9 мСек
353 evgpinsk_
 
17.05.21
15:16
https://dropmefiles.com/ec9WK
оптимизированная база.
в ней же таблица Price - исходная не нормализированная
354 Djelf
 
17.05.21
15:18
(351) Это не прикол, в версиях Орефкова движок sqlite 3.7.11, а начиная с движка 3.8.0 поменялся оптимизатор: https://runebook.dev/ru/docs/sqlite/queryplanner-ng
С 1С 7.7 он работал криво, насколько помню в 3.14.0 починили работу нового планировщика с виртуальными таблицами (которыми являются таблицы 1С 7.7).
355 evgpinsk_
 
17.05.21
15:19
(346) > Ну и чему ты в (344) удивляешься? Ясное дело, что запрос к плоской таблице по уникальному индексу будет быстрее.
Не знал, тогда действительно в моём частном случае правильней и проще держать плоскую базу.
Найти нужную строку по коду товара, и в ней уже выбрать цены магазинов из столбцов
356 Djelf
 
17.05.21
15:31
(355) Тут не понятно что будет быстрее.
Ты же можешь с нормализованной таблицей получать цены в разрезе магазин, а с плоской нет.
Если тупо "товар" -> "строка прайса" -> "список магазинов с ценами", возможно плоская будет быстрее, даже при учете того что разбирать колонки придется в 1С.
357 Злопчинский
 
17.05.21
15:38
исходить надо из перспектив среднесрочных. если создаваемый инструмент важен - то следует делать сразу правильно, это в будущем окупится.
358 evgpinsk_
 
17.05.21
15:45
(356) > Ты же можешь с нормализованной таблицей получать цены в разрезе магазин, а с плоской нет.

с плоской нет - средствами SQL
но ведь элементарно получив строку из базы, потом ручками вытянуть цены магазина по названию колонк (они формализованы: Магазин1, Магазин2)

(357) согласен, но в моём  случае врядли будет усложнение именно этой задачи в будущем (хотя кто его знает).

п.с. Вынашиваю очень долго не простую задачу по импорту прайсов поставщиков в базу 1с.
Есть не совсем простые вопросы по теоретической части. /уже както подымал тему ранее/
Соберусь с мыслями и попробую поднять новую тему ещё раз )
359 Djelf
 
17.05.21
15:53
(358) А ты попробуй, без нормализации, вытянуть цены по одному из магазинов.
Но есть же не только магазины, но и срок доставки! Вот тебе еще и один повод для нормализации базы.
360 evgpinsk_
 
17.05.21
16:10
(359) Да, по магазину очень не просто. В моём частном случае эта задача не стоит. Нужен просто анализ рынка для конкретному товару
361 evgpinsk_
 
17.05.21
16:33
(359) срок доставки - не мешает использовать плоскую таблицу. Это ведь такой же параметр как и цена
362 Djelf
 
17.05.21
16:38
(361) Ты де уже добился приемлемой скорости? Даже 300мс это ерунда, стало 30мс, это уже более чем приемлемо. Забудь (на время).
363 evgpinsk_
 
17.05.21
18:16
(362) Да, всё ок. Уже 8 милисекунд. Для этой задачи это с большим запасом
Выдавать глобальные идеи — это удовольствие; искать сволочные маленькие ошибки — вот настоящая работа. Фредерик Брукс-младший