В этом руководстве мы разберёмся, как быстро начать работу с вариантом 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:
Мы будем использовать ipython для выполнения команд далее в этом руководстве. Его можно запустить, выполнив:
В этом руководстве мы также будем использовать Pandas и Apache Arrow, поэтому установим и эти библиотеки:
pip install pandas pyarrow
Запрос к JSON‑файлу в S3
Теперь рассмотрим, как выполнять запросы к JSON‑файлу, который хранится в бакете S3.
Набор данных YouTube dislikes dataset содержит более 4 миллиардов строк о дизлайках под видео на YouTube до 2021 года.
Мы будем работать с одним из JSON‑файлов из этого набора данных.
Импортируйте 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'
)"""
)
Этот файл содержит чуть больше 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.
Чтобы узнать больше о том, как его использовать, см. следующие руководства для разработчиков: