Вход | Регистрация
    1  2  3  4   
1С:Предприятие :: 1С:Предприятие 7.7 и ранее

v7: Необходим быстрый поиск информации в больших CSV файлах

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

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

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

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

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

просто кто то херовый программист с ограниченным кругозором
   Garykom
 
234 - 11.05.21 - 15:10
(233)+ штатными средствами 1С 7.7 и операционной системы (начиная с winxp) все делается и намного быстрей
   Mikeware
 
235 - 11.05.21 - 15:11
(233) он просто жадный директор
   evgpinsk_
 
236 - 11.05.21 - 15:20
(233) Мне казалось это очевидно. Такие вопросы как в (0) задают крутые программисты??
   Djelf
 
237 - 11.05.21 - 15:28
(236) Да! "Гений 1С" подобные темы создает по 10 раз в день...
   Mikeware
 
238 - 11.05.21 - 15:30
(237) так то ж фикса. он не какой-то "крутой программист", он "гени[т]альный..."
   Garykom
 
239 - 11.05.21 - 15:36
(238) это я тоже фикса и что? ну это кроме фри
он просто засиделся на одном месте и почти утонул в болоте
   Mikeware
 
240 - 11.05.21 - 15:54
(239) ты фикса с Фиксиным не путай
   andrewalexk
 
241 - 12.05.21 - 20:26
   Mikeware
 
242 - 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
   Garykom
 
244 - 13.05.21 - 13:13
(243) Допили утилитку чтобы .DD или .DDS читал и данные засовывал в нужные/указанные sc* и продай ТС
   Garykom
 
245 - 13.05.21 - 13:14
(244)+ только вместо кучи параметров один файл настроек чтобы
   Mikeware
 
246 - 13.05.21 - 13:21
(245) и вместо файла - гуй
   Кирпич
 
247 - 13.05.21 - 13:29
(244) "в нужные/указанные sc*" Это не нужно и сложно(индексы и всё такое). Да автор свою проблему уже решил.
(245) Да в bat файл написать все параметры и хватит
   Garykom
 
248 - 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) взял, нехай будет
   Garykom
 
255 - 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
   Djelf
 
260 - 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
   Garykom
 
266 - 14.05.21 - 12:45
(258) >Раз "два" три;раз два три

эээ по правилам валидного CSV должно быть
"Раз ""два"" три";раз два три
   Кирпич
 
267 - 14.05.21 - 12:53
(266) так оно вроде и то и то съест
   Djelf
 
268 - 14.05.21 - 13:45
(265) Работает. И х32 и х64. Но создает dbf больше 2х гигов, понятно что это обходится с помощью --dbfcount, но может стоит автоматом, после достижения 2х гигов разбивать?
   Djelf
 
269 - 14.05.21 - 13:55
+(268) Или даже лучше ключ --split=len
   pechkin
 
270 - 14.05.21 - 14:09
а что на гитхабе не выложишь?
   Кирпич
 
271 - 14.05.21 - 14:19
Ну может потом сделаю автоматом. Просто думаю, что лучше фиксированное количество файлов. Потом просто знаешь количество файлов и не надо вычислять в 1с сколько их там нагенерило.
   Кирпич
 
272 - 14.05.21 - 14:20
(270) выложу. Потестирую немножко.
   Djelf
 
273 - 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 имел в виду приапменение на этапе чтения исходных данных... тогда можно впихнуть в память бОльший массив
   Djelf
 
278 - 14.05.21 - 15:57
(274) дедупликация? Выкидывание группы полей в отдельную таблицу с заменой ссылок на ключевое поле в исходной таблице.
Я попробовал нарисовать для таблицы которую прислал (0) на триггерах sqlite, не так плохо получилось ~2-3 минуты (переменных в sqlite нет, это иногда выбешивает).
(276) см. пост (162) для (0) потребуется отдельная колонка для индекса и ее придется добавить и файл может стать слишком большим!
   Djelf
 
279 - 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
   Djelf
 
282 - 14.05.21 - 16:52
(281) А ссылку то как получить на поле из новой/дополнительной таблицы в оригинальную?
   D3O
 
283 - 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) уже так и сделали
   Djelf
 
287 - 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
   Djelf
 
289 - 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
пардон за попробывать
   Djelf
 
293 - 14.05.21 - 17:26
(290) Не! Я же не смогу подменить поле на ключ при загрузке!
Эта штука бесплатная: http://www.sqliteexpert.com/download.html

Магазины. Их всего 174, их пишем в отдельную табличку, но их в csv очень много дублируется. Просто +экономия места и +поиск по ключу.
   Кирпич
 
294 - 14.05.21 - 17:37
(293) А. Дошло. Столбцы в строки переделать.
   Djelf
 
295 - 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) Ну это пусть автор извращется. Далеко не у каждого такие проблемы.
   Garykom
 
297 - 14.05.21 - 17:50
Вы только до http сервиса удобного с автоматическим обновлением там прайса и готовыми модулями для разных 1С не доберитесь случайно
   Кирпич
 
298 - 14.05.21 - 17:53
(287) Нифига ты ему забабахал. Нахаляву чтоли?
   Djelf
 
299 - 14.05.21 - 17:54
(296) Я просто обновлял в своей памяти работу с триггерами! Забывается же все постепенно...

(297) А в чем проблема прикрутить сервис на Golang? БД есть, как быстро заполнить уже понятно. Минут 10-15 работы ;)
   Garykom
 
300 - 14.05.21 - 17:56
(299) бесплатно? только если как пет-проекта для портфолио на гитхабе
  1  2  3  4   

Список тем форума
 
ВНИМАНИЕ! Если вы потеряли окно ввода сообщения, нажмите Ctrl-F5 или Ctrl-R или кнопку "Обновить" в браузере.