DoubleCloud 即将停止运营。迁移到 ClickHouse,并享受限时免费迁移服务。立即联系我们 ->->

博客 / 产品

欢迎,chDB

author avatar
ClickHouse 团队
2023 年 8 月 31 日

chDB.png

欢迎,chDB。

在 ClickHouse,我们经常谈论社区和开源。这种对话中蕴含着一种信念,即有时最酷、最令人兴奋的想法来自我们的社区。出于这个原因,我们已开始在每月举行的 ClickHouse 社区电话会议上,重点介绍社区正在创造的一些惊人成果。

本月,我们有机会重点介绍 chDB

chDB 由 ClickHouse 社区贡献者 AuxtenLorenzo Mangani 开发,并在 社区 的帮助下完成。chDB 是一个由 ClickHouse 提供支持的嵌入式 SQL OLAP 引擎。更简单地说,它使 ClickHouse 引擎可以作为“开箱即用”的 Python 模块使用,允许用户直接在代码中利用 ClickHouse 的全部功能和性能。

这种数据库交互模型在数据科学家和数据工程师中越来越受欢迎,近年来 DuckDB 等项目也越来越受欢迎。虽然 ClickHouse 是一款功能齐全的用于实时分析的 OLAP 数据库,能够在托管 PB 级数据的多节点架构中运行,并且仍然提供亚秒级的查询响应时间,但我们也意识到,很多分析是在用户笔记本电脑和工作站上执行的,尤其是在处理较小的数据集时。这些数据交互在许多项目阶段都很常见,无论是早期数据探索、一次性 ETL 任务、开发和测试,还是对较小数据集的简单 SQL 查询,这些查询需要 SQL 但不需要服务器的强大功能。借助 Python(通常是这些任务的首选语言),chDB 提供了一流的集成,并允许用户在代码中利用 ClickHouse。

为什么要嵌入 ClickHouse?

一段时间以来,ClickHouse 一直提供 clickhouse-local。它提供了一个可本地执行的二进制文件,用户可以使用 ClickHouse 的全部功能来查询本地和远程文件(例如,在 S3 中)。clickhouse-local 提供了完整的客户端控制台,以及通过 stdout 传递查询和响应以集成到脚本中的方法,它解决了上述常见的临时数据任务,并避免了用户部署完整服务器的需要。我们继续投资 clickhouse-local,它受益于与服务器相同的核心代码,并尤其受益于最近的改进,例如更快的 Parquet 查询。

虽然 clickhouse-local 已经证明非常受欢迎,尤其是在简单的 SQL 查询就足够的情况下非常强大,但我们也了解到 Python 无处不在,并且通常是数据任务的首选工具。例如,用户经常需要将 SQL 集成到更广泛的逻辑中,尤其是在 Python 作为训练和调用机器学习模型的最流行方法的情况下。chDB 解决了这个问题,允许用户将 ClickHouse 与 Pandas 等标准数据操作和分析库一起使用。

首先引起我们注意的一件事是 chDB 如何解决了将 ClickHouse 作为 Python 模块提供的挑战:**如何** 对我们来说与 **为什么** 一样重要。一个简单的实现可能会将 clickhouse-local 二进制文件直接包含在 Python 包中,并通过类似于 popen 的东西通过 stdin 和 stdout 传递查询和响应。这种管道方法虽然可能对一次性脚本简单且足够,但存在一些缺点,例如

  1. 为每个查询启动一个独立的进程会稍微影响性能,导致查询时间增加约 10 到 50 毫秒。
  2. 不可避免地会出现 SQL 查询结果的多个副本。
  3. 与 Python 的集成有限,难以实现 Python UDF 并支持 Pandas DataFrame 上的 SQL。

对团队来说,最重要的是它缺乏优雅 ????

diagram python and clickhouse.png

团队花费了大量时间(以及他的农历新年)来实现健壮且高性能的集成。chDB 并非依赖管道,而是与 ClickHouse 的读写缓冲区紧密集成,以 通过 MemoryView 交换查询和结果。这解决了上述挑战,确保代码中可以使用 ClickHouse 的单个进程,避免代价高昂的内存复制,并固有地支持并行管道而不会阻塞。

diagram chdb.png

对于有兴趣的人,我们打算在后续博客中发布一篇更深入的客座博客,深入探讨实现过程以及 auxen 和 Lorenzo 面临的一些挑战。或者,如果您等不及详细内容,只需访问 开源仓库

一些快速示例

在 Python 代码中使用 chDB 非常简单。与任何其他 Python 模块一样,快速 pip install 即可开始使用。

pip install chdb

ClickHouse 的一个流行功能是能够查询存储在对象存储(如 S3)中的各种文件格式。下面,我们使用 s3 表函数查询 流行的英国房产价格数据集(表示为一组 Parquet 文件)。请注意,我们不需要指定文件的结构或格式 - ClickHouse 的模式推断会自动处理此问题。

注意:我们使用 CSVWithNames 格式显式请求响应中的列标题 - 默认的 CSV 会省略这些标题。

import chdb

data = chdb.query("SELECT * FROM s3('https://datasets-documentation.s3.eu-west-3.amazonaws.com/uk-house-prices/parquet/house_prices_2*.parquet') LIMIT 5","CSVWithNames")
print(data)
"price","date","postcode1","postcode2","type","is_new","duration","addr1","addr2","street","locality","town","district","county"
62000,9339,"SS6","8PN",2,0,1,"50","","CHURCH ROAD","RAYLEIGH","RAYLEIGH","ROCHFORD","ESSEX"
53500,9400,"SS6","8PW",2,0,1,"10","","LODGE CLOSE","RAYLEIGH","RAYLEIGH","ROCHFORD","ESSEX"
55950,9430,"SS6","8PX",2,0,1,"56","","GROVE ROAD","RAYLEIGH","RAYLEIGH","ROCHFORD","ESSEX"
50000,9198,"SS6","8PX",2,0,1,"58","","GROVE ROAD","RAYLEIGH","RAYLEIGH","ROCHFORD","ESSEX"
109995,9152,"SS6","8PY",3,1,1,"18","","THE RAMPARTS","RAYLEIGH","RAYLEIGH","ROCHFORD","ESSEX"

Pandas 库几乎无处不在,用于 Python 中的数据操作和分析,数据框是有效表示表格数据的主要方法。利用 chDB 与此库的集成非常简单。下面,我们执行一个简单的聚合,以计算自 2000 年以来伦敦每年的平均房价。

pip install pyarrow pandas matplotlib
import chdb
import matplotlib.pyplot as plt
from matplotlib.ticker import MaxNLocator

df = chdb.query("SELECT toYear(date::Date32) AS year, round(avg(price)) AS price "
                 "FROM s3('https://datasets-documentation.s3.eu-west-3.amazonaws.com/uk-house-prices/parquet/house_prices_20*.parquet') WHERE town = 'LONDON' GROUP BY year ORDER BY year","Dataframe")

df['year'] = df['year'].astype(int)
plt.plot(df['year'], df['price'], marker='o', linestyle='-', color='b', label='Price')
plt.xlabel('Year')
plt.ylabel('Price')
plt.legend()
plt.gca().xaxis.set_major_locator(MaxNLocator(integer=True))
plt.show(block=True)

simple_chart.png

用户还可以使用 chDB 查询现有的表格结构(如 Pandas 数据框),从而使用 ClickHouse SQL 简化和加速代码。在下面的示例中,我们使用一些虚拟日期填充数据框,然后重复上述查询。请注意查询中使用的 __table__ 语法。

import chdb.dataframe as cdf
from datetime import datetime, timedelta
import pandas as pd
import random

# Populate the DataFrame with random house sales data
data = []
start_date = datetime(2010, 1, 1)
end_date = datetime(2023, 12, 31)
for _ in range(10000):
   date = start_date + timedelta(days=random.randint(0, (end_date - start_date).days))  # Random date
   price = random.randint(100000, 1000000)  # Random price between 100000 and 1000000
   data.append({'date': date, 'price': price})
df = pd.DataFrame(data)



tbl = cdf.Table(dataframe=df)
df = tbl.query('SELECT toYear(date::Date32) AS year, round(avg(price)) AS price FROM __table__ GROUP BY year ORDER BY year')

print(df)
	year 	price
0   2010  562323.0
1   2011  557704.0
2   2012  556884.0
3   2013  553141.0
4   2014  550012.0
5   2015  555865.0
6   2016  560128.0
7   2017  558746.0
8   2018  560938.0
9   2019  559185.0
10  2020  565041.0
11  2021  535593.0
12  2022  540023.0
13  2023  543916.0

最后,用户还可以以 ClickHouse 支持的众多格式中的任何一种查询和返回数据。下面,我们查询英国房价数据集的 gzip CSV 样本,并以 Arrow 格式返回结果。

import chdb

res = chdb.query(
   f"SELECT town, district, count() AS c, round(avg(price)) AS price "
   f"FROM s3('https://datasets-documentation.s3.eu-west-3.amazonaws.com/uk-house-prices/csv/house_prices.csv.gz') "
   f"GROUP BY town, district HAVING c >= 100 ORDER BY price DESC LIMIT 10",
   "ArrowTable")

print(res)
pyarrow.Table
town: binary
district: binary
c: uint64 not null
price: double
----
town: [[4C4F4E444F4E,4C4F4E444F4E,4C4F4E444F4E,56495247494E4941205741544552,4C45415448455248454144,4C4F4E444F4E,4E4F525448574F4F44,57494E44534F52,57494E444C455348414D,434F4248414D]]
district: [[43495459204F46204C4F4E444F4E,43495459204F4620574553544D494E53544552,4B454E53494E47544F4E20414E44204348454C534541,52554E4E594D454445,454C4D425249444745,43414D44454E,544852454520524956455253,425241434B4E454C4C20464F52455354,535552524559204845415448,454C4D425249444745]]
c: [[729,9605,6549,379,262,7399,150,111,232,925]]
price: [[3212987,2888615,2447372,2115944,2085028,1619476,1493810,1360590,1323741,1307596]]

有关更多示例,请参阅 chDB 存储库,作者在其中提供了 常见问题和任务的解决方案。

不仅仅是 Python

虽然最初的重点是提供 Python 绑定,但 chDB 很快从社区的兴趣和贡献中受益。针对 RustNodeJSGolang 的绑定正在积极开发中!我们很高兴看到这项工作以及他们将解锁的潜在应用。

chDB 已经开启了一些有趣可能性的大门。除了使使用 ClickHouse 的 AWS Lambda 函数 更易于编写和部署 之外,chDB 的服务器版本 提供了一种无状态体验,有助于测试函数并在无需编写任何 Python 代码的情况下执行快速数据分析。Lorenzo 甚至演示了它在 fly.io 上运行,使用 简单的配方 提供了一个免费的 用于查询远程文件的 SQL 查询引擎

未来

自 chDB 创建以来,其发展速度令人印象深刻。最近,向 Python 绑定添加会话允许用户通过创建表来在查询之间持久化状态,其中 可以插入和查询数据。这将 ClickHouse MergeTree 和稀疏索引 的全部功能带入了 Python 代码,并有望开启本地分析的新规模!

社区计划将这些会话扩展到其他绑定,包括对用户定义函数 (UDF) 的支持。除了确保 chDB 及时更新以支持最新版本的 ClickHouse 之外,团队甚至还抽出时间最近添加了 ARM64/AARCH64 支持。

我们期待着见证 chDB 的发展,并希望了解您已经如何使用它。

最后,对于希望在我们的每月社区电话会议上突出显示其基于 ClickHouse 的项目的用户,请联系 [email protected]

立即开始使用 ClickHouse Cloud 并获得 300 美元的积分。在 30 天试用期结束时,您可以继续使用按需付费计划,或 联系我们 了解有关我们基于容量的折扣的更多信息。访问我们的 定价页面 以获取详细信息。

分享此帖子

订阅我们的新闻通讯

随时了解功能发布、产品路线图、支持和云产品!
正在加载表单...
关注我们
Twitter imageSlack imageGitHub image
Telegram imageMeetup imageRss image