R-Client
Installation Um den DuckDB-R-Client zu verwenden, besuchen Sie die R-Installationsseite.
Die aktuelle stabile Version des DuckDB-R-Clients ist 1.5.5
Installation
duckdb: R-Client
Der DuckDB-R-Client kann mit dem folgenden Befehl installiert werden:
install.packages("duckdb")Details finden Sie auf der Installationsseite und bei CRAN.
duckplyr: dplyr-Client
DuckDB bietet eine dplyr-kompatible API über das Paket duckplyr. Es kann mit install.packages("duckplyr") installiert werden. Details finden Sie in der duckplyr-Dokumentation.
Referenzhandbuch
Das Referenzhandbuch für den DuckDB-R-Client ist unter r.duckdb.org verfügbar.
Grundlegende Client-Nutzung
Der Standard-DuckDB-R-Client implementiert die DBI-Schnittstelle für R. Falls Sie mit DBI noch nicht vertraut sind, finden Sie auf der Seite Using DBI eine Einführung.
Start und Beenden
Um DuckDB zu verwenden, müssen Sie zuerst ein Verbindungsobjekt erzeugen, das die Datenbank repräsentiert. Das Verbindungsobjekt nimmt als Parameter die Datenbankdatei entgegen, aus der gelesen und in die geschrieben werden soll. Wenn die Datenbankdatei nicht existiert, wird sie erstellt (die Dateierweiterung kann .db, .duckdb oder etwas anderes sein). Der Sonderwert :memory: (der Standard) kann verwendet werden, um eine In-Memory-Datenbank zu erzeugen. Beachten Sie, dass bei einer In-Memory-Datenbank keine Daten auf die Festplatte geschrieben werden (d. h. alle Daten gehen verloren, wenn Sie den R-Prozess beenden). Wenn Sie sich mit einer bestehenden Datenbank im Nur-Lese-Modus verbinden möchten, setzen Sie das Flag read_only auf TRUE. Der Nur-Lese-Modus ist erforderlich, wenn mehrere R-Prozesse gleichzeitig auf dieselbe Datenbankdatei zugreifen möchten.
library("duckdb")# to start an in-memory databasecon <- dbConnect(duckdb())# orcon <- 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)Verbindungen werden implizit geschlossen, wenn sie außer Scope gehen, oder explizit mit dbDisconnect(). Um die mit der Verbindung verknüpfte Datenbankinstanz herunterzufahren, verwenden Sie duckdb_shutdown() auf dem von duckdb() zurückgegebenen Treiberobjekt.
Abfragen
DuckDB unterstützt die Standard-DBI-Methoden zum Senden von Abfragen und Abrufen von Ergebnissets. dbExecute() ist für Abfragen gedacht, bei denen keine Ergebnisse erwartet werden, etwa CREATE TABLE oder UPDATE usw., und dbGetQuery() ist für Abfragen gedacht, die Ergebnisse liefern (z. B. SELECT). Im Folgenden ein Beispiel.
# create a tabledbExecute(con, "CREATE TABLE items (item VARCHAR, value DECIMAL(10, 2), count INTEGER)")# insert two items into the tabledbExecute(con, "INSERT INTO items VALUES ('jeans', 20.0, 1), ('hammer', 42.2, 2)")
# retrieve the items againres <- dbGetQuery(con, "SELECT * FROM items")print(res)# item value count# 1 jeans 20.0 1# 2 hammer 42.2 2DuckDB unterstützt im R-Client auch Prepared Statements mit den Methoden dbExecute und dbGetQuery. Hier ein Beispiel:
# prepared statement parameters are given as a listdbExecute(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 statementres <- dbGetQuery(con, "SELECT item FROM items WHERE value> ?", list(400))print(res)# item# 1 laptopWarning Verwenden Sie Prepared Statements nicht, um große Datenmengen in DuckDB einzufügen. Siehe unten für bessere Optionen.
Effizienter Transfer
Um einen R-Data-Frame in DuckDB zu schreiben, verwenden Sie die Standard-DBI-Funktion dbWriteTable(). Damit wird eine Tabelle in DuckDB erzeugt und mit dem Inhalt des Data Frames befüllt. Zum Beispiel:
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 setosaEs ist auch möglich, einen R-Data-Frame als virtuelle Tabelle zu „registrieren“, vergleichbar mit einer SQL-VIEW. Dabei werden Daten noch nicht tatsächlich in DuckDB übertragen. Im Folgenden ein Beispiel:
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 setosaDuckDB behält nach der Registrierung eine Referenz auf das R-Data-Frame. Das verhindert, dass das Data Frame vom Garbage Collector eingesammelt wird. Die Referenz wird gelöscht, wenn die Verbindung geschlossen wird, kann aber auch manuell mit der Methode
duckdb_unregister()gelöscht werden.
Weitere Optionen für den effizienten Datenimport finden Sie in der Dokumentation zum Datenimport.
dbplyr
DuckDB funktioniert auch gut mit den Paketen dbplyr / dplyr zur programmatischen Abfragekonstruktion aus R. Hier ein Beispiel:
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()Bei Verwendung von dbplyr können CSV- und Parquet-Dateien mit der Funktion dplyr::tbl gelesen werden.
# Establish a CSV for the sake of this examplewrite.csv(mtcars, "mtcars.csv")
# Summarize the dataset in DuckDB to avoid reading the entire CSV into R's memorytbl(con, "mtcars.csv") |> group_by(cyl) |> summarise(across(disp:wt, .fns = mean)) |> collect()# Establish a set of Parquet filesdbExecute(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 memorytbl(con, "read_parquet('dataset/**/*.parquet', hive_partitioning = true)") |> filter(month == "3") |> summarise(delay = mean(dep_time, na.rm = TRUE)) |> collect()Speicherlimit
Sie können die Konfigurationsoption memory_limit verwenden, um den Speicherverbrauch von DuckDB zu begrenzen, z. B.:
SET memory_limit = '2GB';Beachten Sie, dass dieses Limit nur auf den von DuckDB verwendeten Speicher angewendet wird und den Speicherverbrauch anderer R-Bibliotheken nicht beeinflusst.
Daher kann der gesamte vom R-Prozess verwendete Speicher höher sein als das konfigurierte memory_limit.
Fehlerbehebung
Warnung bei der Installation unter macOS
Unter macOS kann die Installation von DuckDB zu einer Warnung unable to load shared object '.../R_X11.so' führen:
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) ...> ')Beachten Sie, dass es sich nur um eine Warnung handelt, die einfachste Lösung ist also, sie zu ignorieren. Alternativ können Sie DuckDB aus dem R-universe installieren:
install.packages("duckdb", repos = c("https://duckdb.r-universe.dev", "https://cloud.r-project.org"))Sie können auch die optionale Abhängigkeit xquartz über Homebrew installieren.