Перейти к основному содержанию
Перейти к основному содержанию

Начало работы с chDB

В этом руководстве мы разберёмся, как быстро начать работу с вариантом chDB для Python. Мы начнём с выполнения запроса к JSON‑файлу в S3, затем создадим таблицу в chDB на основе этого JSON‑файла и выполним несколько запросов к данным. Мы также посмотрим, как возвращать результаты запросов в различных форматах, включая Apache Arrow и Pandas, и, наконец, узнаем, как выполнять запросы к DataFrame библиотеки Pandas.

Настройка

Сначала создадим виртуальное окружение:

python -m venv .venv
source .venv/bin/activate

А теперь установим chDB. Убедитесь, что у вас версия 2.0.3 или выше:

pip install "chdb>=2.0.2"

Теперь установим IPython:

pip install ipython

Мы будем использовать ipython для выполнения команд далее в этом руководстве. Его можно запустить, выполнив:

ipython

В этом руководстве мы также будем использовать Pandas и Apache Arrow, поэтому установим и эти библиотеки:

pip install pandas pyarrow

Запрос к JSON‑файлу в S3

Теперь рассмотрим, как выполнять запросы к JSON‑файлу, который хранится в бакете S3. Набор данных YouTube dislikes dataset содержит более 4 миллиардов строк о дизлайках под видео на YouTube до 2021 года. Мы будем работать с одним из JSON‑файлов из этого набора данных.

Импортируйте chdb:

import chdb

Мы можем выполнить следующий запрос, чтобы описать структуру одного из файлов JSON:

chdb.query(
  """
  DESCRIBE s3(
    's3://clickhouse-public-datasets/youtube/original/files/' ||
    'youtubedislikes_20211127161229_18654868.1637897329_vid.json.zst',
    'JSONLines'
  )
  SETTINGS describe_compact_output=1
  """
)
"id","Nullable(String)"
"fetch_date","Nullable(String)"
"upload_date","Nullable(String)"
"title","Nullable(String)"
"uploader_id","Nullable(String)"
"uploader","Nullable(String)"
"uploader_sub_count","Nullable(Int64)"
"is_age_limit","Nullable(Bool)"
"view_count","Nullable(Int64)"
"like_count","Nullable(Int64)"
"dislike_count","Nullable(Int64)"
"is_crawlable","Nullable(Bool)"
"is_live_content","Nullable(Bool)"
"has_subtitles","Nullable(Bool)"
"is_ads_enabled","Nullable(Bool)"
"is_comments_enabled","Nullable(Bool)"
"description","Nullable(String)"
"rich_metadata","Array(Tuple(
    call Nullable(String),
    content Nullable(String),
    subtitle Nullable(String),
    title Nullable(String),
    url Nullable(String)))"
"super_titles","Array(Tuple(
    text Nullable(String),
    url Nullable(String)))"
"uploader_badges","Nullable(String)"
"video_badges","Nullable(String)"

Также можно посчитать число строк в этом файле:

chdb.query(
  """
  SELECT count()
  FROM s3(
    's3://clickhouse-public-datasets/youtube/original/files/' ||
    'youtubedislikes_20211127161229_18654868.1637897329_vid.json.zst',
    'JSONLines'
  )"""
)
336432

Этот файл содержит чуть больше 300 000 записей.

chdb пока не поддерживает передачу параметров запроса, но мы можем извлечь путь и передать его через f-строку.

path = 's3://clickhouse-public-datasets/youtube/original/files/youtubedislikes_20211127161229_18654868.1637897329_vid.json.zst'
chdb.query(
  f"""
  SELECT count()
  FROM s3('{path}','JSONLines')
  """
)
Примечание

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

Настройка формата вывода

Формат вывода по умолчанию — CSV, но его можно изменить с помощью параметра output_format. chDB поддерживает форматы данных ClickHouse, а также собственные форматы, включая DataFrame, который возвращает объект Pandas DataFrame:

result = chdb.query(
  f"""
  SELECT is_ads_enabled, count()
  FROM s3('{path}','JSONLines')
  GROUP BY ALL
  """,
  output_format="DataFrame"
)

print(type(result))
print(result)
<class 'pandas.core.frame.DataFrame'>
   is_ads_enabled  count()
0           False   301125
1            True    35307

Или если нам нужна таблица Apache Arrow:

result = chdb.query(
  f"""
  SELECT is_live_content, count()
  FROM s3('{path}','JSONLines')
  GROUP BY ALL
  """,
  output_format="ArrowTable"
)

print(type(result))
print(result)
<class 'pyarrow.lib.Table'>
pyarrow.Table
is_live_content: bool
count(): uint64 not null
----
is_live_content: [[false,true]]
count(): [[315746,20686]]

Создание таблицы из JSON-файла

Теперь рассмотрим, как создать таблицу в chDB. Для этого нам нужно использовать другой API, поэтому сначала импортируем его:

from chdb import session as chs

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

sess = chs.Session("gettingStarted.chdb")

Далее создадим базу данных:

sess.query("CREATE DATABASE IF NOT EXISTS youtube")

Теперь мы можем создать таблицу dislikes на основе схемы из файла JSON, используя приём CREATE...EMPTY AS. Мы будем использовать настройку schema_inference_make_columns_nullable, чтобы типы столбцов не были автоматически сделаны Nullable.

sess.query(f"""
  CREATE TABLE youtube.dislikes
  ORDER BY fetch_date 
  EMPTY AS 
  SELECT * 
  FROM s3('{path}','JSONLines')
  SETTINGS schema_inference_make_columns_nullable=0
  """
)

Затем мы можем использовать оператор DESCRIBE, чтобы изучить схему:

sess.query(f"""
   DESCRIBE youtube.dislikes
   SETTINGS describe_compact_output=1
   """
)
"id","String"
"fetch_date","String"
"upload_date","String"
"title","String"
"uploader_id","String"
"uploader","String"
"uploader_sub_count","Int64"
"is_age_limit","Bool"
"view_count","Int64"
"like_count","Int64"
"dislike_count","Int64"
"is_crawlable","Bool"
"is_live_content","Bool"
"has_subtitles","Bool"
"is_ads_enabled","Bool"
"is_comments_enabled","Bool"
"description","String"
"rich_metadata","Array(Tuple(
    call String,
    content String,
    subtitle String,
    title String,
    url String))"
"super_titles","Array(Tuple(
    text String,
    url String))"
"uploader_badges","String"
"video_badges","String"

Далее заполним таблицу:

sess.query(f"""
  INSERT INTO youtube.dislikes
  SELECT * 
  FROM s3('{path}','JSONLines')
  SETTINGS schema_inference_make_columns_nullable=0
  """
)

Мы также можем выполнить оба этих шага за один раз, используя конструкцию CREATE...AS. Давайте создадим другую таблицу с использованием этой конструкции:

sess.query(f"""
  CREATE TABLE youtube.dislikes2
  ORDER BY fetch_date 
  AS 
  SELECT * 
  FROM s3('{path}','JSONLines')
  SETTINGS schema_inference_make_columns_nullable=0
  """
)

Выполнение запроса к таблице

Теперь давайте сделаем запрос к таблице:

df = sess.query("""
  SELECT uploader, sum(view_count) AS viewCount, sum(like_count) AS likeCount, sum(dislike_count) AS dislikeCount
  FROM youtube.dislikes
  GROUP BY ALL
  ORDER BY viewCount DESC
  LIMIT 10
  """,
  "DataFrame"
)
df
                             загрузчик  количествоПросмотров  количествоЛайков  количествоДизлайков
0                             Jeremih  139066569     812602         37842
1                     TheKillersMusic  109313116     529361         11931
2  LetsGoMartin- Canciones Infantiles  104747788     236615        141467
3                    Xiaoying Cuisine   54458335    1031525         37049
4                                Adri   47404537     279033         36583
5                  Diana and Roma IND   43829341     182334        148740
6                      ChuChuTV Tamil   39244854     244614        213772
7                            Cheez-It   35342270        108            27
8                            Anime Uz   33375618    1270673         60013
9                    RC Cars OFF Road   31952962     101503         49489

Предположим, что затем мы добавим в DataFrame дополнительный столбец, чтобы вычислить отношение числа лайков к числу дизлайков. Мы могли бы написать следующий код:

df["likeDislikeRatio"] = df["likeCount"] / df["dislikeCount"]

Выполнение запросов к DataFrame Pandas

Затем мы можем выполнять запросы к этому DataFrame из chDB:

chdb.query(
  """
  SELECT uploader, likeDislikeRatio
  FROM Python(df)
  """,
  output_format="DataFrame"
)
                             uploader  likeDislikeRatio
0                             Jeremih         21.473548
1                     TheKillersMusic         44.368536
2  LetsGoMartin- Canciones Infantiles          1.672581
3                    Xiaoying Cuisine         27.842182
4                                Adri          7.627395
5                  Diana and Roma IND          1.225857
6                      ChuChuTV Tamil          1.144275
7                            Cheez-It          4.000000
8                            Anime Uz         21.173296
9                    RC Cars OFF Road          2.051021

Также вы можете подробнее узнать о выполнении запросов к DataFrame в Pandas в руководстве для разработчиков по запросам в Pandas.

Дальнейшие шаги

Надеемся, это руководство дало вам хорошее общее представление о chDB. Чтобы узнать больше о том, как его использовать, см. следующие руководства для разработчиков: