Забудьте о SQLite, используйте вместо этого DuckDB — И поблагодарите меня позже
Мы, программисты, склонны по умолчанию использовать SQLite, когда необходимо работать в локальных средах со встроенной базой данных. Хотя большую часть времени он работает нормально, это всё равно что проехать 100 км на велосипеде: вероятно, не самый лучший вариант.
Впервые я узнал о DuckDB в сентябре 2022 года, находясь в PyCon Spain в Гранаде. Теперь, после 6 месяцев использования этого инструмента, я не могу без него жить. И я хочу внести свой вклад в сообщество, предоставив моим коллегам-программистам и специалистам, связанным с данными, введение в эту фантастическую аналитическую систему баз данных.
В этой статье я рассмотрю следующие основные моменты:
- Введение в DuckDB: что это такое, почему вы должны его использовать и когда это принесёт свои плоды.
- Интеграция DuckDB с Python.
Давайте начинать!
Что такое DuckDB?
Если вы зайдёте на веб-сайт DuckDB[1], первое, что вы увидите на их домашней странице: DuckDB – это встроенная система управления базами данных SQL OLAP.
Давайте попробуем расшифровать это предложение, потому что в нём содержится пара тяжёлых к пониманию моментов.
- Встроенный SQL означает, что функции DuckDB выполняются в вашем приложении, а не во внешнем процессе, к которому подключается ваше приложение. Другими словами: нет ни клиента, отправляющего инструкции, ни сервера для их чтения и обработки. SQLite работает таким же образом, в то время как PostgreSQL, MySQL этого не делают.
- OLAP расшифровывается как онлайн-аналитическая обработка, а Microsoft определяет её как технологию, которая организует большие бизнес-базы данных и поддерживает комплексный анализ. Её можно использовать для выполнения сложных аналитических запросов без негативного влияния на транзакционные системы[2]. Другим примером системы управления базами данных OLAP является Terradata.
Таким образом, DuckDB – отличный вариант, если вы ищете бессерверную систему управления базами данных для осуществления анализа. Я настоятельно рекомендую вам ознакомиться с фантастической рецензируемой статьёй доктора Марка Раасвельдта и доктора Ханнеса Мюлейзена [3] – двух наиболее важных разработчиков DuckDB — чтобы увидеть пробел, который DuckDB пытается заполнить.
Кроме того, это система управления реляционными базами данных (СУБД), которая поддерживает SQL. Вот почему мы сравниваем его с другими СУБД, которые имеют те же характеристики, что и SQLite или PostgreSQL.
Почему именно DuckDB?
Теперь мы знаем роль DuckDB в индустрии баз данных. Но почему мы должны выбирать его из множества других вариантов, которые у нас есть?
Универсального решения не существует, когда речь заходит о системах управления базами данных, и DuckDB не является исключением. Мы рассмотрим некоторые из его функций, чтобы помочь вам решить, когда вам стоит его использовать.
Короче говоря, это высокопроизводительный инструмент. Как показано на их странице GitHub[4]: “Он разработан таким образом, чтобы быть быстрым, надёжным и простым в использовании”. Вдаваясь в подробности:
- Он создан для поддержки рабочих нагрузок аналитических запросов (OLAP). Они делают это путём векторизации выполнения запросов (ориентированного на столбцы), в то время как другие СУБД, упомянутые ранее (SQLite, PostgreSQL …), обрабатывают каждую строку последовательно. Вот почему его производительность повышается.
- DuckDB использует лучшую особенность SQLite: простоту. Простота установки и встроенная работа в процессе – вот что выбрали разработчики DuckDB для этой СУБД, увидев успех SQLite благодаря этим функциям. Кроме того, DuckDB не имеет внешних зависимостей или серверного программного обеспечения для установки, обновления или обслуживания. Как уже было сказано, он полностью встроен, и это имеет дополнительное преимущество в виде высокоскоростной передачи данных в базу данных и из неё.
- Полноценность. Он поддерживает сложные запросы в SQL, обеспечивает гарантии транзакций (свойства ACID, о которых вы наверняка слышали), поддерживает вторичные индексы для ускорения запросов… И, что более важно, он глубоко интегрирован в Python и R для эффективного интерактивного анализа данных. Он также предоставляет API для C, C++, Java…
- Бесплатный и с открытым исходным кодом. Лучше этого и быть не может.
Вот официальные преимущества DuckDB.
Но есть и другие, и я хочу выделить ещё одно: DuckDB не обязательно должен заменять Pandas. Они могут работать рука об руку, и, если вы такой же фанат Pandas, как я, вы можете создать эффективный SQL на Pandas с помощью DuckDB.
Это потрясающе!
Вы можете найти более полные объяснения на веб-сайте DuckDB[1].
Когда использовать DuckDB?
Это действительно будет зависеть от ваших предпочтений, но давайте вернёмся к статье, выпущенной её соучредителями [3] (я настоятельно рекомендую вам прочитать её, в ней всего 4 страницы, и она будет очень полезна для вас).
Они объясняют, что существует явная потребность в встраиваемом управлении аналитическими данными. SQLite встроен, но он слишком медленный, если мы хотим использовать его для исчерпывающего анализа данных. Они продолжают: “эти потребности проистекают из двух основных источников: интерактивного анализа данных и “передовых” вычислений”.
Итак, вот 2 лучших варианта использования DuckDB:
- Интерактивный анализ данных. Большинство специалистов по обработке данных теперь используют библиотеки R или Python, такие как dplyr или Pandas, в своих локальных средах для работы с данными, которые они извлекают из базы данных. DuckDB предлагает возможность использования SQL efficiency для нашей локальной разработки без риска для производительности. И вы можете воспользоваться этими преимуществами, не отказываясь от своего любимого языка программирования (подробнее об этом позже).
- Передовые вычисления. Используя определение Википедии, “Передовые вычисления – это парадигма распределённых вычислений, которая приближает вычисления и хранение данных к источникам данных”. [5]
DuckDB может быть установлен и использован в различных средах: Python, R, Java, node.js , Julia, C++… Здесь мы сосредоточимся на Python, и вскоре вы увидите, насколько он прост в использовании.
Использование DuckDB с Python (введение)
Откройте свой терминал и перейдите в нужный каталог, потому что мы вот-вот начнём. Создайте новую виртуальную среду — или нет — и установите DuckDB:
pip install duckdb==0.7.1
Удалите или обновите версию, если вам нужна другая.
Теперь перейдём к самому интересному! Чтобы сделать всё более интересным, я буду использовать реальные данные, которые я нашёл на Kaggle о самых популярных песнях Spotify за всё время [6]. А работать я буду с типичным Jupyter Notebook.
Лицензия: CC0: Public Domain
Поскольку полученные нами данные представлены в виде двух CSV-файлов — Features.csv и Streams.csv – нам нужно создать новую базу данных и загрузить их в неё:
import duckdb
# Create DB (embedded DBMS)
conn = duckdb.connect('spotiStats.duckdb')
c = conn.cursor()
# Create tables by importing the content from the CSVs
c.execute(
"CREATE TABLE features AS SELECT * FROM read_csv_auto('Features.csv');"
)
c.execute(
"CREATE TABLE streams AS SELECT * FROM read_csv_auto('Streams.csv');"
)
Точно так же мы создали совершенно новую базу данных, добавили две новые таблицы и заполнили их всеми данными. Всё с помощью 4 простых строк кода (5, если мы примем во внимание импорт). Круто, да?
Давайте покажем содержимое из таблицы streams:
c.sql("SELECT * FROM streams")
Давайте начнём выполнять некоторые аналитические задачи. Например, я хочу знать, сколько песен вошло в топ-100 до 2000 года. Вот один из способов сделать это:
c.sql('''
SELECT *
FROM streams
WHERE regexp_extract("Release Date", '\d{2}$') > '23'
''')
Ранее я упоминал, как легко работать с DuckDB и Pandas одновременно. Вот способ сделать то же самое, но с использованием Pandas:
df = c.sql('SELECT * FROM streams').df()
df[df['Release Date'].apply(lambda x: x[-2:] > '23')]
Всё, что я делаю, это преобразую в DataFrame исходный запрос, а затем применяю фильтр способом Pandas. Результат тот же, но как насчёт их производительности?
>>> %timeit df[df['Release Date'].apply(lambda x: x[-2:] > '23')]
434 µs ± 25.6 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
>>> %timeit c.sql('SELECT * FROM streams WHERE regexp_extract("Release Date", \'\d{2}$\') > \'23\'')
112 µs ± 25.3 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
Вы это видите? Операция была довольно простой: мы применяли простой фильтр к таблице из 100 строк. Но время выполнения с использованием Pandas почти в 4 раза быстрее, если сравнить его с реализацией DuckDB.
Представьте, если бы мы попробовали провести более исчерпывающую аналитическую операцию… Улучшение могло бы быть огромным.
Я думаю, что нет особого смысла приводить больше примеров, потому что это введение в DuckDB затем было бы преобразовано во введение к SQL. А это не то, чего я хочу.
Но не стесняйтесь экспериментировать с любым набором данных, который у вас может быть, и начните использовать SQL в вашей базе данных DuckDB. Вы быстро увидите его преимущества.
Чтобы закончить с этим кратким вступлением, давайте экспортируем последний результат (песни до 2000 года) в виде файла parquet – потому что они всегда являются лучшей альтернативой традиционным CSV. Опять же, это будет чрезвычайно просто:
c.execute('''
COPY (
SELECT
*
FROM
streams
WHERE
regexp_extract("Release Date", '\d{2}$') > '23'
)
TO 'old_songs.parquet' (FORMAT PARQUET);
''')
Всё, что я сделал, это заключил предыдущий запрос в квадратные скобки, а DuckDB просто копирует результат запроса в файл old_songs.parquet.
И вуаля.
Заключение
DuckDB изменил мою жизнь, и я думаю, что это могло бы произойти и со многими другими людьми.
Я надеюсь, что эта статья была интересной и информативной. Это не должно было быть учебником или руководством, поэтому я не особо углублялся в примеры кода, но я считаю, что их достаточно, чтобы понять основные моменты.
Ресурсы
[1] DuckDB
[2] Online analytical processing (OLAP) — Azure Architecture Center
[3] Mark Raasveldt and Hannes Mühleisen. 2019. DuckDB: an Embeddable Analytical Database. In 2019 International Conference on Management of Data (SIGMOD ’19), June 30-July 5, 2019, Amsterdam, Netherlands. ACM, New York, NY, USA, 4 pages. https: //doi.org/10.1145/3299869.3320212
[4] DuckDB — GitHub
[5] Edge computing — Wikipedia
[6] Most Streamed Songs (of all time) — Kaggle