В этом руководстве мы научимся быстро настраивать Python-версию chDB.
Начнем с выполнения запроса к 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 содержит более 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
, который возвращает DataFrame Pandas:
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
uploader viewCount likeCount dislikeCount
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
Вы также можете прочитать больше о запросах к DataFrames Pandas в руководстве для разработчиков по запросам к Pandas.
Следующие шаги
Надеюсь, это руководство дало вам хорошее представление о chDB.
Чтобы узнать больше о том, как его использовать, смотрите следующие руководства для разработчиков: