DuckDB R 客户端的最新版本是 1.3.2。
安装
duckdb
: R 客户端
DuckDB R 客户端可以通过以下命令安装:
install.packages("duckdb")
详情请参阅安装页面。
duckplyr
: dplyr 客户端
DuckDB 通过 duckplyr
包提供了一个与 dplyr 兼容的 API。可以使用 install.packages("duckplyr")
命令安装。详情请参阅 duckplyr
文档。
参考手册
DuckDB R 客户端的参考手册可在 r.duckdb.org 查看。
基本客户端用法
标准的 DuckDB R 客户端实现了 R 的 DBI 接口。如果您还不熟悉 DBI,请参阅 使用 DBI 页面 获取介绍。
启动与关闭
要使用 DuckDB,您必须首先创建一个表示数据库的连接对象。连接对象将数据库文件作为参数,用于读写。如果数据库文件不存在,则会创建该文件(文件扩展名可以是 .db
、.duckdb
或其他任何)。特殊值 :memory:
(默认值)可用于创建**内存数据库**。请注意,对于内存数据库,数据不会持久化到磁盘(即,当您退出 R 进程时,所有数据都会丢失)。如果您想以只读模式连接到现有数据库,请将 read_only
标志设置为 TRUE
。如果多个 R 进程希望同时访问同一个数据库文件,则需要只读模式。
library("duckdb")
# to start an in-memory database
con <- dbConnect(duckdb())
# or
con <- dbConnect(duckdb(), dbdir = ":memory:")
# to use a database file (not shared between processes)
con <- dbConnect(duckdb(), dbdir = "my-db.duckdb", read_only = FALSE)
# to use a database file (shared between processes)
con <- dbConnect(duckdb(), dbdir = "my-db.duckdb", read_only = TRUE)
当连接超出作用域或使用 dbDisconnect()
显式关闭时,连接将隐式关闭。要关闭与连接关联的数据库实例,请使用 dbDisconnect(con, shutdown = TRUE)
查询
DuckDB 支持标准的 DBI 方法来发送查询和检索结果集。dbExecute()
用于不期望结果的查询,例如 CREATE TABLE
或 UPDATE
等;而 dbGetQuery()
用于生成结果的查询(例如 SELECT
)。下面是一个示例。
# create a table
dbExecute(con, "CREATE TABLE items (item VARCHAR, value DECIMAL(10, 2), count INTEGER)")
# insert two items into the table
dbExecute(con, "INSERT INTO items VALUES ('jeans', 20.0, 1), ('hammer', 42.2, 2)")
# retrieve the items again
res <- dbGetQuery(con, "SELECT * FROM items")
print(res)
# item value count
# 1 jeans 20.0 1
# 2 hammer 42.2 2
DuckDB 还在 R 客户端中通过 dbExecute
和 dbGetQuery
方法支持预处理语句。这是一个示例:
# prepared statement parameters are given as a list
dbExecute(con, "INSERT INTO items VALUES (?, ?, ?)", list('laptop', 2000, 1))
# if you want to reuse a prepared statement multiple times, use dbSendStatement() and dbBind()
stmt <- dbSendStatement(con, "INSERT INTO items VALUES (?, ?, ?)")
dbBind(stmt, list('iphone', 300, 2))
dbBind(stmt, list('android', 3.5, 1))
dbClearResult(stmt)
# query the database using a prepared statement
res <- dbGetQuery(con, "SELECT item FROM items WHERE value > ?", list(400))
print(res)
# item
# 1 laptop
警告:请**不要**使用预处理语句向 DuckDB 插入大量数据。请参阅下文了解更好的选项。
高效传输
要将 R 数据框写入 DuckDB,请使用标准的 DBI 函数 dbWriteTable()
。这会在 DuckDB 中创建一个表,并用数据框的内容填充它。例如:
dbWriteTable(con, "iris_table", iris)
res <- dbGetQuery(con, "SELECT * FROM iris_table LIMIT 1")
print(res)
# Sepal.Length Sepal.Width Petal.Length Petal.Width Species
# 1 5.1 3.5 1.4 0.2 setosa
也可以将 R 数据框“注册”为虚拟表,类似于 SQL VIEW
。这实际上并不会将数据传输到 DuckDB 中。下面是一个示例:
duckdb_register(con, "iris_view", iris)
res <- dbGetQuery(con, "SELECT * FROM iris_view LIMIT 1")
print(res)
# Sepal.Length Sepal.Width Petal.Length Petal.Width Species
# 1 5.1 3.5 1.4 0.2 setosa
注册后,DuckDB 会保留对 R 数据框的引用。这可以防止数据框被垃圾回收。当连接关闭时,该引用会被清除,但也可以使用
duckdb_unregister()
方法手动清除。
另请参阅数据导入文档,了解更多高效导入数据的选项。
dbplyr
DuckDB 还与 dbplyr / dplyr 包良好兼容,用于从 R 进行程序化查询构建。下面是一个示例:
library("duckdb")
library("dplyr")
con <- dbConnect(duckdb())
duckdb_register(con, "flights", nycflights13::flights)
tbl(con, "flights") |>
group_by(dest) |>
summarise(delay = mean(dep_time, na.rm = TRUE)) |>
collect()
使用 dbplyr 时,可以使用 dplyr::tbl
函数读取 CSV 和 Parquet 文件。
# Establish a CSV for the sake of this example
write.csv(mtcars, "mtcars.csv")
# Summarize the dataset in DuckDB to avoid reading the entire CSV into R's memory
tbl(con, "mtcars.csv") |>
group_by(cyl) |>
summarise(across(disp:wt, .fns = mean)) |>
collect()
# Establish a set of Parquet files
dbExecute(con, "COPY flights TO 'dataset' (FORMAT parquet, PARTITION_BY (year, month))")
# Summarize the dataset in DuckDB to avoid reading 12 Parquet files into R's memory
tbl(con, "read_parquet('dataset/**/*.parquet', hive_partitioning = true)") |>
filter(month == "3") |>
summarise(delay = mean(dep_time, na.rm = TRUE)) |>
collect()
内存限制
您可以使用memory_limit
配置选项来限制 DuckDB 的内存使用,例如:
SET memory_limit = '2GB';
请注意,此限制仅适用于 DuckDB 使用的内存,不影响其他 R 库的内存使用。因此,R 进程使用的总内存可能高于配置的 memory_limit
。
故障排除
在 macOS 上安装时的警告
在 macOS 上安装 DuckDB 可能会出现警告 unable to load shared object '.../R_X11.so'
Warning message:
In doTryCatch(return(expr), name, parentenv, handler) :
unable to load shared object '/Library/Frameworks/R.framework/Resources/modules//R_X11.so':
dlopen(/Library/Frameworks/R.framework/Resources/modules//R_X11.so, 0x0006): Library not loaded: /opt/X11/lib/libSM.6.dylib
Referenced from: <31EADEB5-0A17-3546-9944-9B3747071FE8> /Library/Frameworks/R.framework/Versions/4.4-arm64/Resources/modules/R_X11.so
Reason: tried: '/opt/X11/lib/libSM.6.dylib' (no such file) ...
> ')
请注意,这只是一个警告,因此最简单的解决方案是忽略它。或者,您可以从 R-universe 安装 DuckDB。
install.packages("duckdb", repos = c("https://duckdb.r-universe.dev", "https://cloud.r-project.org"))
您还可以通过 Homebrew 安装可选的 xquartz
依赖项。