【问题标题】:R dplyr query does not use table indexes in PostgreSQL?R dplyr 查询不使用 PostgreSQL 中的表索引?
【发布时间】:2021-07-06 07:21:21
【问题描述】:

我想使用 R 笔记本通过 dplyr 包连接到远程 PostgreSQL 数据库。 问题是 R 函数很慢,当我查看执行计划时,我看到它没有使用表的索引,但是如果我在 PostgreSQL 中运行相同的查询,它会快得多,因为使用了索引。

在 R 中:

q <- tbl(con, "mytable")%>%
    filter(a==1000, b>500)%>%
    select(id) %>%
    explain()

#<SQL>
#SELECT "id"
#FROM "mytable"
#WHERE (("a" = 1000.0) AND ("b" > 500.0))
#
#<PLAN>
#Seq Scan on mytable
#  Filter: (((b)::numeric > 500.0) AND ((a)::numeric = 1000.0))

在同一个 R 笔记本但在一个 SQL 块中:

{sql connection=con}
EXPLAIN ANALYZE SELECT id FROM mytable WHERE a=1000 AND b>500;

#Bitmap Heap Scan on mytable 
#Recheck Cond: (a = 1000)
#Filter: (b > 500)
#Rows Removed by Filter: 44963
#Heap Blocks: exact=390
#-> Bitmap Index Scan on idx_mytable_a
#Index Cond: (a = 1000)

为什么计划在使用相同连接时会有所不同?

更新

R 函数将1000 解释为1000.0,这是造成差异的原因:

{sql connection=con}
EXPLAIN ANALYZE SELECT id FROM mytable WHERE a=1000.0 AND b>500.0;

#Seq Scan on mytable
#  Filter: (((b)::numeric > 500.0) AND ((a)::numeric = 1000.0))

如何避免这种转换?

【问题讨论】:

  • 一个可能链接的issue
  • 不同之处在于命令的构建方式。你可以尝试用括号( 解释完全相同的SQL,看看它是否仍然不同?
  • 感谢您的提示!我能够检测到差异的原因:dplyr 函数使用a=1000.0 创建一个查询,并将其写为a=1000。如果我将 SQL 查询写为SELECT id FROM mytable WHERE a=1000.0 AND b&gt;500;,它确实是一个 seq 扫描。任何解决方法的想法还是可能是一个错误?

标签: r postgresql dplyr


【解决方案1】:

回答我自己的问题,但也好奇地看到一个更优雅的解决方案。

如果我明确说要将数字解释为整数,它会使用索引:

q <- tbl(con, "mytable")%>%
    filter(a==as.integer(1000), b>500)%>%
    select(id) %>%
    explain()

#<SQL>
#SELECT "id"
#FROM "mytable"
#WHERE (("a" = CAST(1000.0 AS INTEGER)) AND ("b" > 500.0))
#
#<PLAN>
#Bitmap Heap Scan on mytable
#  Recheck Cond: (a = 1000)
#  Filter: ((b)::numeric > 500.0)
#  ->  Bitmap Index Scan on idx_mytable_a
#        Index Cond: (a = 1000)

【讨论】:

  • 如果是这种情况,您可能应该使用filter(a == 1000L, b &gt; 500L) 将它们标记为整数文字。 R(默认情况下)将控制台或脚本中写入的任何数值解释为双精度值。用L 标记它们将它们标记为整数。
猜你喜欢
  • 2012-05-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-09-30
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多