Installation
duckdb
: R API
可以使用以下命令安装DuckDB R API:
install.packages("duckdb")
详情请参阅安装页面。
duckplyr
: dplyr API
DuckDB 提供了一个与 dplyr 兼容的 API,通过 duckplyr
包实现。可以使用 install.packages("duckplyr")
进行安装。详情请参阅 duckplyr
文档。
参考手册
DuckDB R API 的参考手册可在 R.duckdb.org 获取。
Basic API Usage
标准的DuckDB R API实现了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)
Querying
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 API 中使用 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
你可以使用memory_limit
配置选项来限制DuckDB的内存使用,例如:
SET memory_limit = '2GB';
请注意,此限制仅适用于DuckDB使用的内存,不会影响其他R库的内存使用。
因此,R进程使用的总内存可能高于配置的memory_limit
。
Troubleshooting
在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
依赖项。