使用 dbplyr 跨数据库连接

Posted

技术标签:

【中文标题】使用 dbplyr 跨数据库连接【英文标题】:Joining across databases with dbplyr 【发布时间】:2018-05-14 09:31:28 【问题描述】:

我正在使用 dbplyr 处理数据库表

我有一个本地表,想将它与数据库上的一个大(150m 行)表连接起来

数据库PRODUCTION是只读的

# Set up the connection and point to the table

library(odbc); library(dbplyr)    

my_conn_string <- paste("Driver=Teradata;DBCName=teradata2690;DATABASE=PRODUCTION;UID=",
                            t2690_username,";PWD=",t2690_password, sep="")

t2690 <- dbConnect(odbc::odbc(), .connection_string=my_conn_string)

order_line <- tbl(t2690, "order_line") #150m rows

我还有一个本地表,我们称之为订单

# fill df with random data

orders <- data.frame(matrix(rexp(50), nrow = 100000, ncol = 5))

names(orders) <- c("customer_id", paste0(rep("variable_", 4), 1:4))

假设我想加入这两个表,我收到以下错误:

complete_orders <- orders %>% left_join(order_line)

> Error: `x` and `y` must share the same src, set `copy` = TRUE (may be slow)

问题是,如果我设置copy = TRUE,它会尝试下载整个order_line,我的电脑很快就会耗尽内存

另一种选择是将orders 表上传到数据库。这里的问题是PRODUCTION 数据库是只读的——我必须上传到不同的数据库。尝试在 dbplyr 中跨数据库复制会导致相同的错误。

我找到的唯一解决方案是上传到可写数据库并使用sql加入它们,这远非理想

【问题讨论】:

如果你只加入一个变量,也许你可以使用IN (a, b, c...),即将本地表中所有必要的数据放入查询中,然后只查询大表。 假设本地表足够小,这将起作用......但是看到它有 100k 行,数据库在处理这么大的查询时遇到了麻烦。还有 20k+ 行 R 代码也不是很有趣 确实,如果不能将数据放入查询中,则必须将其放入数据库中。一种混合方法是对源表进行足够的过滤,以便能够将其加载到 R 中,并使用来自您的 R 对象的数据到您的查询中。然后在 R 中完成工作。 【参考方案1】:

我找到了答案,您可以使用 tbl 指针中的in_schema() 函数在同一连接中跨架构工作

# Connect without specifying a database
my_conn_string <- paste("Driver=Teradata;DBCName=teradata2690;UID=",
                            t2690_username,";PWD=",t2690_password, sep="")    

# Upload the local table to the TEMP db then point to it
orders <- tbl(t2690, in_schema("TEMP", "orders"))

order_line <-  tbl(t2690, in_schema("PRODUCTION", "order_line"))

complete_orders <- orders %>% left_join(order_line)

【讨论】:

我有一个与只读数据库 (Redshift) 类似的问题,并希望使用 %in% 在我的查询中引用本地数据框。但是,当我尝试在未指定 database(在您的第一行中)的情况下进行连接时,由于此遗漏,它会引发错误,阻止我将本地数据框添加到某个临时数据库以完成.. 此解决方案是否专门用于 Teradata还是我在这里做错了什么?【参考方案2】:

另一种选择是将orders 表上传到数据库。这里的问题是PRODUCTION 数据库是只读的——我必须上传到不同的数据库。尝试在 dbplyr 中跨数据库复制会导致相同的错误。

在您的用例中,您的数据库似乎(基于公认的答案)位于同一台服务器上,只需使用in_schema。如果不是这种情况,另一种方法是给定here,它实际上提供了一个在只读连接上工作的copy_to 版本。

【讨论】:

以上是关于使用 dbplyr 跨数据库连接的主要内容,如果未能解决你的问题,请参考以下文章

dbplyr 当前是不是假设 redshift 连接实际上是 postgres 连接?

用 dbplyr 总结的五位数

mysql长连接跨网段问题

使用 nhibernate 跨数据库连接

从 dbplyr 中的给定 SQL 查询开始使用 dbplyr

是否可以使用 LINQ 跨不同数据库执行连接?