跳至主要内容

chDB 入门

在本指南中,我们将使用 chDB 的 Python 版本进行操作。我们将从查询 S3 上的 JSON 文件开始,然后基于 JSON 文件在 chDB 中创建表,并对数据进行一些查询。我们还将了解如何以不同的格式返回查询数据,包括 Apache Arrow 和 Panda,最后我们将学习如何查询 Pandas DataFrame。

设置

首先,让我们创建一个虚拟环境

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

查询 S3 中的 JSON 文件

现在,让我们看看如何查询存储在 S3 存储桶中的 JSON 文件。YouTube 点赞数据集包含超过 40 亿行截至 2021 年的 YouTube 视频点赞数据。我们将使用该数据集中的一个 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-String 传递。

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")

现在,我们可以使用CREATE...EMPTY AS技术基于 JSON 文件中的模式创建一个dislikes表。我们将使用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"]

查询 Pandas DataFrame

然后,我们可以从 chDB 查询该 DataFrame

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

您还可以阅读有关在查询 Pandas 开发人员指南中查询 Pandas DataFrame 的更多信息。

后续步骤

希望本指南能为您提供对 chDB 的良好概述。要了解有关如何使用它的更多信息,请参阅以下开发人员指南