Как стать автором
Обновить

Комментарии 40

Можно попробовать формат Apache Parquet :) А если данных очень много и они не помещаются в память, то Apache Spark

Посмотрел, интересная штука, и как раз для подобного класса задач. Правда, впечатление легкой не производит. Добавил в закладочки.

Spark, да, для совсем больших объёмов, и нужно время чтобы в нём разобраться. Но Parquet поддерживается в pandas, не так сложно читать и писать данные в этом формате. Я когда-то пытался в MS SQL сохранить 39 Гб зазипованных CSV-файлов. После долгих часов мучения жесткого диска открыл для себя Parquet :)

В 2009-ом году Майкрософт публиковал статьи как грузить в SQL Server терабайт данных из CSV (точнее там был "|" разделителем) за 30 минут. Они неплохое железо использовали, но то было 13 лет назад, нынче наверное можно повторить на самом обычном.

https://learn.microsoft.com/en-us/previous-versions/sql/sql-server-2008/dd537533(v=sql.100)

Железо у меня примерно восьмилетней давности. Да и серверное железо вряд ли можно сравнивать с домашним - немножечко другая архитектура, другое количество ядер, NUMA, другие шины...

У них получилось 1000 / 30 / 60 = 0.5556 Гб/сек. С парсингом текста.

У меня получилось 1.514 / 4.7 = 0.322 Гб/сек. Без парсинга текста, но с распаковкой.

Мне кажется, это сравнение ужа, ежа и сферического коня))

Не, это не сравнение, это про то что грузить 39Гб как в комменте выше в SQL не страшно. Сравнивать с тем экспериментом бессмысленно, там действительно всё другое, и железо, и вращающиеся диски вместо SSD, и парсинг, и, главное, задача - данные не только читались но и записывались.

Всё сходится :) В распакованном виде там было порядка 120-150 Гб (39 Гб это zip-архив с csv). Это было 6 лет назад на слабом компе с HDD. И если по ссылке загрузку 1 Тб на 32-процессорный сервер с 256 Гб RAM (это вообще какой-то монстр) подают как достижение, то ничего удивительного что у меня были с этим сложности. После отключения журналирования и кучи каких-то танцев с бубнами мне удалось загрузить эти данные. Но дальше началось веселье с выполнением запросов.

Я точно не помню как в итоге обучал модель. По-моему я сначала сохранил всё в Parquet. По сравнению с MS SQL скорость чтения и записи была просто космическая. Но этого было недостаточно потому что данные не помещались в память, пришлось использовать ещё Spark.

Не знаю изменилось ли что-то сейчас, но че-то я всё равно не рискнул бы использовать MS SQL для таких задач. Даже на современном компе с SSD. Может быть ClickHouse, как пишут в соседних комментариях... Он меня в своё время тоже поразил скоростью загрузки csv.

Но ведь для бигдаты есть просто куча форматов - avro, parquet, arrow.
При чём с поддержкой различных тулов и плюшек вроде zero copy. Зачем вручную бинари парсить?

>поискать более быструю библиотеку распаковки
lz4

В памяти после распаковки размер составляет 49 мегабайт.

Я, конечно, прошу прощения, но 1млн записей - это даже и близко не бигдата. В принципе, такие объемы я бы даже через sqlite попробовал, если уж "в лоб" решение - вам индексы все равно нужны, что бы вы не говорили. Если в файлах - так и pickle отбрасывать не надо.

А если бы вы взяли HDF5 формат сразу, то и статьи вообще могло не быть. Там все сразу есть из коробки и работает быстро. Посмотрите на него, он правда вам бы больше всего подошел.

Первое желание было поставить статье минус, но написано с разбором достаточно грамотно, так что не буду ставить оценку.

Я, конечно, прошу прощения, но 1млн записей - это даже и близко не бигдата.

В конце статьи эксперименты с 11 млн, но может быть гораздо больше.

pickle и sqlite точно не подойдет, а вот HDF5 - уже интереснее, спасибо.

Точнее 31 млн, а не 11.

У меня прямо сейчас есть SQLite табличка со 130млн записей, загрузил в SQLite т.к. иногда есть вопросы вида сколько файлов для такой-то страны или за определенный месяц. По индексу запросы вовзращает за десятки мс.

т.к. иногда есть вопросы вида сколько файлов для такой-то страны или за определенный месяц. По индексу запросы вовзращает за десятки мс.

Это немного не та задача.
Кстати, а можете попробовать выбрать 30 млн в одном запросе, и посмотреть время? Ну можно поменьше, 10-20 млн. Записа короткие, можно одно поле длинной символов 30-50. Тогда это будет похоже на мою задачу. Правда, у меня еще распаковка в процессе загрузки есть.

Обычно данные фетчятся с той скокростью которая нужна(после исполнения запроса).
Пример вывода лога для запроса, где возвращается 26 409 484 записей
500 rows retrieved starting from 1 in 87 ms (execution: 9 ms, fetching: 78 ms)

500 rows retrieved starting from 1 in 87 ms (execution: 9 ms, fetching: 78 ms)

Если я правильно понимаю это сообщение, то это очень медленно. 500 строк за 87 мс - это на все 26 409 484 записи будет 4595 секунд = 76 минут.

Нет, важное тут 9мс-время поиска этих 26 млн записей. Попробовал сейчас в лоб их всех достать в питон-23 с(1 поле). Преполагаю большую часть времени тратит питон на аллокацию объектов
Обычно ненадо доставать все записи, больгинство инофрмации я сделаю на sql.
К тому же при таком объеме если мне понадобится я ее помещу в память.

О том и речь, что вы говорите о совершенно другой задаче.

Мне же нужно, достать все 31 млн записей и положить их в память. У меня это заняло менее пяти секунд.

Причем по моим данным видно, что это время можно прилично уменьшить, может быть, даже в несколько раз - задействовав параллельную обработку.

Спасибо за эксперимент, это интересно)

Вы, действительно, давно не возвращались к СУБД. Посмотрите на колоночные решения. Взять тот же Clickhouse. С ним я привык жить в парадигме - всё что может быть посчитать на стороне бд должно быть там посчитано, а не таскать по сети и складывать в память миллиарды строк.

В трейдинге очень часто бывает задача типа "если функция от 1млн самых последних данных больше X, то ПРОДАВАЙ!!". И считать надо, в идеале, для каждого полученного ордера (бывают десятками в секунду в пике). Сложно представить как это можно в удаленной базе сделать и послать еще сигнал обратно в приложение. В базу обычно пишут уже отложенно пачками по 100-1000 записей чтобы анализировать, максимум, минутные интервалы уже.

Обычно именно для этого и держат все в памяти как раз того приложения, чтобы уменьшить задержку и реакцию.

На мой взгляд, вы немного подменили задачу. Если мы говорим про трейдинг когда сервис крутится на расстоянии 200 метров от биржи на прямом оптическом канале, то, в таком случае, нет необходимости быстро загружать пачку в миллиард строк. Предполагается, что эта пачка у вас уже есть в скользящем окне и она непрерывно пополняется каким нибудь сервисом потоковой доставки данных.

Ну, в общем-то да. Если мы загружаем исторические данные - то не так важно за полсекунды мы их прочитаем или за 5 секунд. Если это какие-то активные данные - то непонятно откуда они взялись в файле и почему - за любое время между сохранением и чтением они уже могут устареть.

Мое возражение было именно к вашему предложению все делать только в базе.

могу предположить что основная польза от решённой задачи не столько торговать, сколько ресерчить алгоритмы торговли, бектестить и в такой ситуации хочется быстро пробовать разный код альф в каком-нибудь Jupiter

Да, все верно. Для этого и нужно получить историю в память, и много.

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

Видимо я недостаточно явно сделал акцент в своём тезисе. Он был в контексте: "не таскать по сети и складывать в память миллиарды строк"

Решал точно такую же задачу. Может будет интересно. С тинькофф, писал все БД асинхронно с помощью питона. Точно не скажу по объему, но пару терабайт мог заполнится за несколько дней, может даже за один. Так же приходилось данные доставать для расчетов. Так вот тюнингованный postgresql оказался в десятки раз медленнее Марии. Быстрее всего на Монго. В итоге, достаточной производительности не смог на питоне добиться, особенно в расчетах. Перешел на плюсы. В БД храню только расчеты, что бы сделать быстрый старт при закрытии приложения. А также исторические расчеты, что-то наподобие используется в Биг Дата. После нескольких оптимизаций и добавления кэшей, а так же распараллеливания расчетов, теперь мощности хватает что бы в несколько раз усложнить алгоритм:)

Конечно, интересно!
А что за данные загружались, такой поток? Тики?

Да, чистый питон в расчетах на таком объеме очень медленный. Но numpy+numba делают его таким же быстрым в расчетах, как С++. В своем коде в расчетах я нигде не использую чистый питон, нет ни одного цикла на питоне, который идет по данным. Данные обрабатываются либо внутри numpy, либо код питона, ускоренный нумбой.

На крайняк всегда можно написать расширение на C/C++ и прицепить к питону. Чтобы и скорость высокая была, и интерфейс удобный

Верно! Буду обходить, пока можно, а если не получится - тогда расширение. Правда, я на Rust смотрю.

Только что-то пока все обходится, и чего-то неразрешимого на питоне в ближайшем будущем не видно)

Пока не могу, numba ее еще не поддерживает.

Не знаю как в питоне с Bzip2, но я бы попробовал его. Это splittable-формат, и может обрабатываться в параллель...

Есть его поддержка. Спасибо, сделал закладочку.

Почему не TSDB?

Думаете, будет быстрее?

Прям быстрее, вряд ли. Но меньше пришлось бы делать своих велосипедов.
Впрочем, не всегда у меня цель сделать их как можно меньше, иногда это развлечение)

Ну смотрите. Велосипеды обычно плохи тем, что на них тратится много времени и что они менее гибкие. Тут гибкость не нужна - формат менятся не будет. Максимум, что добавится - это формат для тиков. Получается, у моего велосипеда много объективных для этой задачи плюсов, и почти нет минусов.

В меня тут немного кидались тапками, предлагая заменить заводским велосипедом, но никто не привел реальной объективной причины, зачем это нужно делать.

Времени на разработку я потратил совсем немного, несколько дней. Времени разобраться с хорошим готовым решением ушло бы примерно столько же. И у этого решения была бы куча минусов.

Да, там появился бы опыт работы с решением X. Но и тут у меня тоже появился опыт работы с определенными вещами :)

Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации