前文介绍了,通过 PostgreSQL + PL/Python 实现数据湖的访问。
今天研究了下,DuckDB 借助 Jinja 模板 也可以轻松实现数据湖的访问。
准备知识
-
-
-
-
-
如果你还没有安装 Superset, 建议看下这篇文章, Apache Superset 2.0 来了。
-
需要安装好 DuckDB 、 duckdb-engine 还有 deltalake,
pip install duckdb-engine deltalake
代码
-
superset-config.py 部分
# activate Jinja templating
FEATURE_FLAGS = {
# . . . . .
"ENABLE_TEMPLATE_PROCESSING": True
}
def delta_table(table_name):
from deltalake import DeltaTable
dt = DeltaTable(table_name)
return dt.file_uris()
JINJA_CONTEXT_ADDONS = {
'delta_table': delta_table
}
-
SQL 语句
SELECT * from read_parquet({{delta_table('/Users/steven/data/iris')}})
其中 /Users/steven/data/iris 为 delta lake 表, 做过一次追加
实现代码如下
import pandas as pd
iris = pd.read_csv('/Users/steven/data/iris.csv')
from deltalake.writer import write_deltalake
# 第一次写入
write_deltalake( '/Users/steven/data/iris',iris)
# 第二次追加
write_deltalake( '/Users/steven/data/iris',iris,mode='append')
# 查看最新版本parquet 文件列表
from deltalake import DeltaTable
dt = DeltaTable('/Users/steven/data/iris')
dt.file_uris()
返回
最新版本 DuckDB 对分区表的支持
昨天文章写到这的时候,我以为结束了,今天突然想到,如果数据分区了怎么办, 很幸运,最新的 DuckDB 也支持, 如果想体验这个功能,需要安装 0.4.1 版本(当前版本为 duckdb-0.4.1.dev1057)
pip install -U --pre duckdb -i https://mirrors.aliyun.com/pypi/simple/
# Attempting uninstall: duckdb
# Found existing installation: duckdb 0.3.2
# Uninstalling duckdb-0.3.2:
# Successfully uninstalled duckdb-0.3.2
# Successfully installed duckdb-0.4.1.dev1057
分区测试代码,
# 把iris以Species分区数据写到数据湖
write_deltalake( '/Users/steven/data/iris1',iris,partition_by=['Species'])
# 读取
from deltalake import DeltaTable
dt = DeltaTable('/Users/steven/data/iris1')
dt.file_uris()
# 返回
这个时候 superset 的 SQL lab 里需要这样写了(需要用到 parquet_scan
函数以及 参数 HIVE_PARTITIONING=true
),
SELECT * from parquet_scan({{delta_table('/Users/steven/data/iris1')}},HIVE_PARTITIONING=true)
如果不加参数 HIVE_PARTITIONING=true
会丢失分区列
当然即使没有分区,也可以写上这个参数。
附 DuckDB 读取 Parquet
原文 https://duckdb.org/docs/data/parquet
单文件读取
DuckDB 以函数的形式包含一个高效的 Parquet 阅读器 read_parquet
。
SELECT * FROM read_parquet('test.parquet');
如果您的文件以 结尾 .parquet
,则 read_parquet 语法是可选的。系统会自动推断您正在读取 Parquet 文件。
SELECT * FROM 'test.parquet';
与 CSV 文件不同,Parquet 文件是结构化的,因此阅读起来很明确。无需向此函数传递任何参数。该 read_parquet
函数将找出文件中存在的列名和列类型并发出它们。
多文件读取和全局
DuckDB 还可以读取一系列 Parquet 文件并将它们视为单个表。请注意,这只适用于 Parquet 文件具有相同架构的情况。您可以使用列表参数、glob 模式匹配语法或两者的组合来指定要读取的 Parquet 文件。
列表参数
read_parquet 函数可以接受文件名列表作为输入参数。有关列表的更多详细信息,请参阅嵌套类型文档。
-- read 3 parquet files and treat them as a single table
SELECT * FROM read_parquet(['file1.parquet', 'file2.parquet', 'file3.parquet']);
glob 语法
输入到 read_parquet 函数的任何文件名可以是精确的文件名,也可以使用 glob 语法来读取与模式匹配的多个文件。
通配符 | 描述 |
---|---|
* |
匹配任意数量的任意字符(包括无) |
? |
匹配任何单个字符 |
[abc] |
匹配括号中的一个字符 |
[a-z] |
匹配括号中给定范围内的一个字符 |
这是一个读取文件夹中所有以结尾的文件的 .parquet
示例 test
:
-- read all files that match the glob pattern
SELECT * FROM read_parquet('test/*.parquet');
glob 列表
glob 语法和列表输入参数可以结合起来扫描满足多种模式之一的文件。
-- Read all parquet files from 2 specific folders
SELECT * FROM read_parquet(['folder1/*.parquet','folder2/*.parquet']);
部分读取
DuckDB 支持将投影下推到 Parquet 文件本身。也就是说,查询 Parquet 文件时,只读取查询所需的列。这允许您只读取您感兴趣的 Parquet 文件的一部分。这将由系统自动完成。
DuckDB 还支持将过滤器下推到 Parquet 阅读器中。当您将过滤器应用于从 Parquet 文件扫描的列时,过滤器将被下推到扫描中,甚至可以使用内置区域图跳过文件的某些部分。请注意,这取决于您的 Parquet 文件是否包含区域图。
过滤器和投影下推提供了显著的性能优势。有关更多信息,请参阅 DuckDB 博客文章[1]。
插入和视图
您还可以将数据插入表中或直接从 parquet 文件创建表。这将从 parquet 文件加载数据并将其插入数据库。
-- insert the data from the parquet file in the table
INSERT INTO people SELECT * FROM read_parquet('test.parquet');
-- create a table directly from a parquet file
CREATE TABLE people AS SELECT * FROM read_parquet('test.parquet');
如果您希望将数据保存在 parquet 文件中,但又想直接查询 parquet 文件,您可以在该 read_parquet
函数上创建一个视图。然后,您可以像查询内置表一样查询 parquet 文件。
-- create a view over the parquet file
CREATE VIEW people AS SELECT * FROM read_parquet('test.parquet');
-- query the parquet file
SELECT * FROM people;
参考资料
博客文章: https://duckdb.org/2021/06/25/querying-parquet.html
原文始发于微信公众号(alitrack):Superset 通过DuckDB连接数据湖
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/62728.html