dbplyr 生成意外 SQL 查询

dbplyr generating unexpected SQL query

我正在使用 dbplyr:

向 MySQL 数据库发送一个简单的查询
library(dbplyr)

my_conn<-dbConnect(...)
tab<-tbl(my_conn, "myTable")

tab %>% select(id, date, type) %>%
    filter(type = 'foobar')

但是,如果我用 show_query() 检查生成的 SQL,我得到这个:

SELECT *
FROM (SELECT `id`, `date`, `type`
FROM `myTable`) `q01`
WHERE (`type` == 'foobar')

这个查询执行起来很慢。

如果我改为在服务器上执行以下 SQL 命令:

SELECT id, date, type FROM db.myTable WHERE type = 'foobar'

那么 return 几乎是瞬时的。

我的问题是:为什么 dbplyrSELECT *(即 select 全部) 然后 做嵌套 select 在第 2 行?另外,为什么“q01”出现在这个查询中?与直接在服务器上执行最小命令相比,这可能就是为什么我的查询 运行 非常慢的原因吗?随着操作复杂性的增加,我可能希望 dbplyr 创建低效的 SQL 查询,但是——至少在这种情况下——我真的无法编写更简洁的操作集。它只是一个 select 和过滤器(SELECT 和 WHERE)。

我想你想把它们串起来。执行 tab <- tbl(my_conn, "myTable") 后,您已经下载了整个 table。

tbl(my_conn, "myTable") %>% 
  select(id, date, type) %>%
  filter(type = 'foobar')

dbplyr 正按我的预期生成 SQL 查询。它所做的是一个查询内嵌另一个查询:

SELECT id, date, type FROM myTable

是超查询中的子查询

SELECT *
FROM (
   subquery
) q01
WHERE type = foobar

q01 是给子查询的名称。与 AS 关键字相同。例如:FROM very_long_table_name AS VLTN.

是的,这个嵌套很丑。但是许多 SQL 引擎都有一个查询优化器,可以计算执行查询的最佳方式。在 SQL 服务器上,我注意到性能差异不大,因为查询优化器找到了一种比所写方式更快的执行方式。

但是,对于 MySQL,嵌套查询似乎会导致性能下降。参见 here, here, and here

可能解决此问题的一件事是更改 R:

selectfilter 命令的顺序
tab %>%
  filter(type = 'foobar') %>%
  select(id, date, type)

可能会生成翻译后的查询:

SELECT `id`, `date`, `type`
FROM `myTable`
WHERE (`type` == 'foobar')

哪个效果会更好。