Встречайте ноутбуки!

Исследование данных в SubQuery

|
Встречайте ноутбуки!

Каждый, кто работает с данными, знает этот момент. Вы открываете SQL-консоль, делаете быстрый SELECT, смотрите на результат и понимаете: вопросов стало больше, чем ответов. Хочется построить график, сверить выгрузку с файлом, который прислали в почте, посчитать что-то посложнее одного агрегата.

И вот тут начинается квест: копируем данные в CSV, открываем Jupyter, вспоминаем, какое окружение мы поднимали в прошлый раз, молимся, чтобы pandas согласился с версией numpy. Знакомо?

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

Что такое ноутбук в SubQuery

Ноутбук — это рабочее пространство, где вы пишете код по шагам и сразу видите результат каждого шага:

  • ноутбук состоит из ячеек, которые выполняются последовательно;
  • состояние сохраняется между ячейками: переменные, импортированные модули и загруженные пакеты доступны в следующих шагах;
  • доступны ячейки четырёх типов: Python, SQL, DuckDB и Markdown;
  • код и результаты выполнения автосохраняются — вернулись в ноутбук и видите последние результаты, а не пустые ячейки.

Самое интересное: Python и DuckDB исполняются прямо в вашем браузере через WASM-рантайм. Никаких отдельных серверов, никаких kernel-процессов на удалённой машине, никакого «а где мой jupyterhub». Открыл вкладку — работаешь.

Что можно делать в ноутбуке

SQL прямо из Python

Функция sq.query выполняет SQL на сервере и возвращает pandas.DataFrame:

df = await sq.query("select now() as ts")df.head()

Можно явно указать, к какому подключению уйдёт запрос:

df = await sq.query(    "select count(*) as cnt from analytics.orders",    connection_name="prod_clickhouse")

Обратите внимание на await — функция асинхронная. И да, секреты БД при этом остаются на сервере: из браузера до вашей СУБД напрямую никто не достучится. Тот же контур прав, что и у dbt.

Данные — обратно в базу

sq.query тянет данные из СУБД в Python. Но исследование редко заканчивается на чтении: почистили, посчитали, сверили — и итог хочется вернуть в базу, а не пересылать файлами. Для этого есть обратный билет — sq.insert_df:

result = await sq.insert_df("analytics.orders_checked", df_merged)result

Функция берёт pandas.DataFrame, сериализует его в parquet и через сервер SubQuery загружает в таблицу — опять же без прямого доступа из браузера к вашей СУБД и с тем же контуром прав, что и у sq.query. На выходе — DataFrame с числом вставленных строк:

   rows_inserted0            184

Подключение можно указать явно — как у sq.query:

await sq.insert_df(    "analytics.orders_checked",    df_merged,    column_names=["date", "amount"],    connection_name="prod_clickhouse",)

А column_names заодно отберёт из DataFrame только нужные колонки. Закольцевали: принесли → разобрались → вернули.

flowchart LR
    A[Таблица в СУБД] -->|sq.query| B[DataFrame в Python]
    B --> C[Исследование в pandas]
    C -->|sq.insert_df| D[Результат в таблице]

Честно про ограничения: sq.query отдаёт до 100 000 строк на выборку, а sq.insert_df принимает до 200 МБ в parquet. Для апдейта миллионов строк это не инструмент — но для результатов исследования и выгрузок, с которыми вы только что работали, — в самый раз.

Свои файлы — без ETL

Перетащите CSV, Parquet или JSON прямо в ноутбук — файл появится в панели Data Explorer и станет доступен:

  • в Python: pd.read_csv("sales.csv");
  • в DuckDB: select * from sq_local.sales.

Никаких промежуточных выгрузок, бакетов и скриптов «на перекинуть файл».

Работа с локальными файлами

Библиотеки

В Python-ячейках пакеты устанавливаются через sq.install:

await sq.install("matplotlib")import matplotlib.pyplot as plt

Pandas и numpy уже предзагружены — они готовы к работе сразу. Полный список доступных пакетов (а их около семидесяти: scikit-learn, xgboost, pyarrow, geopandas и так далее) — в документации.

Запросы к внешним API

Дёрнуть сторонний API прямо из ноутбука — можно. Обычно в браузере это спотыкается о CORS, а в WASM — ещё и о сетевые ограничения, но requests в ноутбуке ходит через прокси-сервер SubQuery, так что внешние вызовы работают как ни в чём не бывало.

await sq.install("requests", quiet=True)import requests response = requests.get(    "https://httpbin.org/get",    params={"param1": "value1"},    timeout=30,)response.json()

POST — с телом JSON:

response = requests.post(    "https://httpbin.org/post",    params={"param1": "value1"},    json={"name": "Alice", "role": "Developer"},    timeout=30,)response.json()

Не забывайте timeout — без него зависший API повесит ячейку. Подробности — в документации.

Результаты, которые приятно смотреть

Ячейка умеет показывать не только текстовый вывод, но и таблицы, изображения и графики. Последнее выражение ячейки выводится автоматически — как в хорошем jupyter.

Пример: от CSV до графика

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

flowchart LR
    A[CSV файл] --> B[DuckDB разведка]
    B --> C[SQL данные из СУБД]
    C --> D[Python сверка в pandas]
    D --> E[График matplotlib]
  1. Быстро глянем, что прислали, — DuckDB-ячейка:
select * from sq_local.sales limit 100
  1. Заберём данные из базы — Python-ячейка:
df_db = await sq.query(    "select date, amount from analytics.orders",    connection_name="prod_clickhouse")
  1. Сверим выгрузку с базой:
import pandas as pd df_local = pd.read_csv("sales.csv")merged = df_local.merge(df_db, on="date", suffixes=("_local", "_db"))merged.head()
  1. И построим график прямо в результате ячейки:
await sq.install("matplotlib")import matplotlib.pyplot as plt merged.plot(x="date", y=["amount_local", "amount_db"], figsize=(12, 5))plt.title("Выгрузка против базы")plt.show()

Всё это — в одном окне, без локальных окружений и перекладывания файлов туда-обратно.

График в ноутбке SubQuery

Публичные ноутбуки

Чтобы не начинать с чистого листа, в разделе ноутбуков есть две вкладки: «Мои» и «Публичные». Во второй мы собираем коллекцию примеров — с кодом и уже выполненными результатами ячеек. То есть можно сначала посмотреть, что получится на выходе, и только потом разбираться, как это устроено.

Понравился пример? Копируйте его в свой проект одной кнопкой — и работайте с ним уже на своих данных.

Например, вот демо-ноутбук с обучением ML-модели: пройдите по ссылке, нажмите кнопку, и копия появится прямо в вашем проекте.

Публичный ноутбук SubQuery

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

Что важно знать

Быть честными — наша политика, поэтому четыре особенности WASM-сессии, которые не должны вас удивить:

  1. Сессия живёт во вкладке браузера. Python и DuckDB работают на вашем компьютере, поэтому закрытие вкладки или перезагрузка страницы сбрасывает kernel-сессию. Код и результаты при этом сохранены, но переменные в памяти придётся восстановить повторным запуском ячеек.
  2. Память ограничена вкладкой браузера. Python и DuckDB живут в памяти вашего компьютера и лимитах браузера, поэтому очень большие датасеты в ноутбуке не покрутить. Миллиарды строк оставьте СУБД, а в ноутбук забирайте агрегаты и разумные выборки.
  3. Первая ячейка в сессии выполняется дольше — в этот момент поднимается WASM-рантайм. Все последующие работают заметно быстрее.
  4. sq.install ставит только пакеты из разрешённого каталога. Это осознанное ограничение безопасности; полный список — в документации.

Совет: ставьте библиотеки в первой ячейке ноутбука — тогда после перезагрузки страницы достаточно перезапустить её одну.

Попробуйте за пять минут

  1. Откройте проект и создайте ноутбук.
  2. Перетащите в него любой CSV, который уже «под рукой».
  3. Напишите две-три ячейки: разведка в DuckDB, выборка через sq.query, график в matplotlib.

Лень писать с нуля? Скопируйте готовый публичный ноутбук — например, с обучением ML-модели — и экспериментируйте уже на своих данных.

А дальше — куда идти:

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

Ну а лучше всего — откройте ноутбук, попробуйте и расскажите, что получилось 😉