Сломал много копий в поисках решения для быстрого получения длинных историй цен для большого количества активов в Python. Ещё имел смелость желать работать с ценами в numpy-массивах, а лучше сразу в pandas.
Стандартные подходы в лоб работали разочаровывающе, что приводило к выполнению запроса к БД в течение 30 секунд и более. Не желая мириться, я нашёл несколько решений, которые полностью меня удовлетворили.
Ноги растут из объектной природы Python. Ведь у него даже целые числа являются объектами, что крайне отрицательно влияет на скорость работы. Менять язык я категорически не хотел.
Первым решением была группировка истории цен силами PostgreSQL, что приводило к незначительной просадке производительности на стороне БД, но ускоряло задачу примерно в ~3 раза. Подробнее метод описан в другой статье.
Итогом появилось понимание, что в Python надо каким-то образом получить весь набор данных одним куском, хотя бы строкой. И разобрать по numpy-массивам или сразу в pandas.
Итоговые результаты:
Решение в лоб для PostgreSQL
Делаем группировку данных в sql-запрос. Пример:
Готовые пакеты Python
Python хорош своим сообществом, которое сталкивается со схожими проблемами. Для нашей цели подойдут следующие:
На выходе данные разбираются в pandas.DataFrame() или numpy.ndarray().
Так как warp_prism написан на C, он имеет существенное преимущество по скорости парсинга данных. Но одновременно с этим имеет существенный недостаток — ограниченную поддержку типов данных. То есть он парсит int, float, date и str, но не numeric. У odo подобных ограничений нет.
Для использования необходимо описать структуру таблицы и запрос с помощью пакета sqlalchemy:
warp_prism.to_arrays() - подготовка python-словаря с numpy-массивами.
Что можно сделать с ClickHouse?
PostgreSQL всем хорош, кроме аппетита с размеру хранилища и необходимости настройки шардинга для больших таблиц. ClickHouse сам шардирует, хранит всё компактно, а работает молниеносно. Для примера таблица на PostgreSQL размером ~5Gb в ClickHouse умещается в ~1Gb. Использование ClickHouse для хранения цен описываю в другой статье.
К моему огорчению odo не помог, хоть для sqlalchemy есть расширение clickhouse. Воспоминания о скорости работы clickhouse в консоли меня навели на идею обращения к БД через создание отдельного процесса. Я знаю, что это долго и ресурсозатратно, но результаты оказались выше всяких похвал.
Запрос к HTTP-порту ClickHouse
Результаты чуть ухудшились при обращении непосредственно к порту 8123, где отвечает БД:
Но не обошлось без ложки дёгтя.
Ложка дёгтя с ClickHouse
БД впечатлила на больших выборках, но на маленьких результаты разочаровали. В ~20 раз хуже odo. Но это издержки на дополнительный обвес с запуском процесса или обращением по HTTP.
Результаты:
Заключение
Данной статьёй погоня за ускорением взаимодействия между Python и базами данных закончена. Для PostgreSQL при стандартных полях и необходимости универсального доступа к ценам лучшим способом является использование пакета warp_prism от Quantopian. При необходимости хранить большие объёмы истории и высокой частоте запросов большого количества строк идеально подойдёт ClickHouse.
Стандартные подходы в лоб работали разочаровывающе, что приводило к выполнению запроса к БД в течение 30 секунд и более. Не желая мириться, я нашёл несколько решений, которые полностью меня удовлетворили.
Ноги растут из объектной природы Python. Ведь у него даже целые числа являются объектами, что крайне отрицательно влияет на скорость работы. Менять язык я категорически не хотел.
Первым решением была группировка истории цен силами PostgreSQL, что приводило к незначительной просадке производительности на стороне БД, но ускоряло задачу примерно в ~3 раза. Подробнее метод описан в другой статье.
Итогом появилось понимание, что в Python надо каким-то образом получить весь набор данных одним куском, хотя бы строкой. И разобрать по numpy-массивам или сразу в pandas.
Итоговые результаты:
Решение в лоб для PostgreSQL
Делаем группировку данных в sql-запрос. Пример:
Готовые пакеты Python
Python хорош своим сообществом, которое сталкивается со схожими проблемами. Для нашей цели подойдут следующие:
- odo — создан для оптимизации скорости передачи данных из одного источника в другой. Полностью на Python. С PostgreSQL взаимодействует через SQLAlchemy.
- warp_prism — C-расширение, используемое проектом Quantopian для получения данных из PostgreSQL. В основе заложен функционал odo.
На выходе данные разбираются в pandas.DataFrame() или numpy.ndarray().
Так как warp_prism написан на C, он имеет существенное преимущество по скорости парсинга данных. Но одновременно с этим имеет существенный недостаток — ограниченную поддержку типов данных. То есть он парсит int, float, date и str, но не numeric. У odo подобных ограничений нет.
Для использования необходимо описать структуру таблицы и запрос с помощью пакета sqlalchemy:
warp_prism.to_arrays() - подготовка python-словаря с numpy-массивами.
Что можно сделать с ClickHouse?
PostgreSQL всем хорош, кроме аппетита с размеру хранилища и необходимости настройки шардинга для больших таблиц. ClickHouse сам шардирует, хранит всё компактно, а работает молниеносно. Для примера таблица на PostgreSQL размером ~5Gb в ClickHouse умещается в ~1Gb. Использование ClickHouse для хранения цен описываю в другой статье.
К моему огорчению odo не помог, хоть для sqlalchemy есть расширение clickhouse. Воспоминания о скорости работы clickhouse в консоли меня навели на идею обращения к БД через создание отдельного процесса. Я знаю, что это долго и ресурсозатратно, но результаты оказались выше всяких похвал.
Запрос к HTTP-порту ClickHouse
Результаты чуть ухудшились при обращении непосредственно к порту 8123, где отвечает БД:
Но не обошлось без ложки дёгтя.
Ложка дёгтя с ClickHouse
БД впечатлила на больших выборках, но на маленьких результаты разочаровали. В ~20 раз хуже odo. Но это издержки на дополнительный обвес с запуском процесса или обращением по HTTP.
Результаты:
Заключение
Данной статьёй погоня за ускорением взаимодействия между Python и базами данных закончена. Для PostgreSQL при стандартных полях и необходимости универсального доступа к ценам лучшим способом является использование пакета warp_prism от Quantopian. При необходимости хранить большие объёмы истории и высокой частоте запросов большого количества строк идеально подойдёт ClickHouse.