使用 ODBC 连接将数据从 SQL 服务器复制到 R

Copying data from SQL Server to R using ODBC connection

我已经通过以下操作成功设置了 R SQL 服务器 ODBC 连接:

DBI_connection <- dbConnect(odbc(),
                            driver = "SQL Server"
                            server = server_name
                            database = database_name)

Dataset_in_R <- dbFetch(dbSendQuery(DBI_connection,
                                   "SELECT * FROM MyTable_in_SQL"))

3 个快速问题:

1-是否有更快的方法将数据从 SQL 服务器复制到 R?这个 table 有 +4400 万行,它仍然是 运行...

2-如果我在 R 中对这些数据进行任何更改,它会改变我的 MyTable_in_SQL 中的任何内容吗?我不这么认为,因为我已经将它保存在 R 中的全局 data.frame 变量中,但只是检查。

3-如何避免每次打开 R 时都经过这一步?有没有办法将我的 data.frame 保存在 R 的“背景”中?

关于问题 2,您是正确的,R 中的任何更改都不会更改数据库中的任何内容。

关于问题 3,您可以 save.image()save.image('path/image_name.Rdata'),它会保存您的环境,以便您稍后可以在 load.image('path/image_name.Rdata') 的另一个会话中恢复它。

也许有了这个,您就不需要更快的方法来从数据库中获取数据了。

1:有没有更快的方法将数据从 SQL 服务器复制到 R?

这里的答案很简单。 R 中的 odbc 包做了相当多的底层工作,以确保从服务器获取的结果与 R 的数据结构之间的兼容性。使用替代包可能会稍微提高速度(RODBC 是一个旧包,有时看起来更快)。然而,在这种情况下,有 4400 万。行,我希望更大的性能提升来自准备你的 sql-statement。总体思路是

  1. 删除任何不需要的列。请记住,每一列都需要下载,因此如果您有 20 列,删除 1 列 可能 将您的查询执行时间减少约 5%(假设线性 运行 时间)
  2. 如果您计划执行聚合,直接在查询中执行此操作(非常接近几乎)会更快,例如,如果您有一个名为 Ticker 的列和一个名为 Volume 的列,并且您想要 Volume 的平均值,您可以直接在查询中计算它。最后一行使用 last_value(colname) over ([partition by [grouping col 1], [grouping col 2] ...] order by [order col 1], [order col 2]) as last_value_colname.
    类似 如果您选择这样做,使用 TOP NLIMIT N test 您对一小部分行的查询可能是有益的,例如:select [select statement] from mytable_in_sql order by [order col] limit 100这只会 return 前 100 行。正如 Martin Schmelzer 评论的那样,这也可以通过 dplyr::tbl 函数通过 R 完成,但是更正您的陈述总是更快。
    最后,如果您的查询变得更加复杂(此处似乎并非如此),使用特定的 select 语句在 table CREATE VIEW 上创建一个视图并查询它可能会有所帮助查看。然后服务器将尝试优化查询,如果您的问题是在服务器端而不是本地端,这可以提高性能。
  3. 最后必须说明一点。如上所述,当您查询服务器时,您正在下载一些(可能相当多)数据。这可以通过重新定位您的计算机、路由器或直接通过电线连接(或纯粹升级互联网连接)来改善您的互联网连接。 4400万美元。行,如果你只有一个 64 位双精度变量,你有 44 * 10^6 / 1024^3 = 2.6 GiB 的数据(如果没有压缩)。如果您有 10 列,这将达到 26 GiB 的数据。下载所有这些数据需要很长时间。因此,减少这一行的计数将非常有帮助!

附带说明一下,您可以通过 SQL-server 的 SSMS slightly faster (still slow due to table size) and then import the file locally. For the fastest speed you likely have to look into the Bulk import and export 功能直接下载 table。

2:如果我在 R 中对这些数据进行任何更改,它会改变我的 MyTable_in_SQL 中的任何内容吗?

否:一旦加载 table,R 就没有内部 pointer/connection。我什至不相信存在一个包(至少在 R 中)打开一个流到 table,它可以动态更新 table。我知道 Excel 中存在这样的功能,但即使使用它也有一些危险的副作用,并且(在我看来)应该只用于只读应用程序,用户希望看到(几乎)数据直播。

3:如何避免每次打开R都要经过这一步?有没有办法将我的 data.frame 保存在 R 的“背景”中?

为避免这种情况,只需在每次会话后保存 table。每当你关闭 Rstudio 时它会询问你是否要保存你当前的会话,在这里你可以点击 yes,此时它会在 [=22] 中保存 .Rhistory.Rdata =] 目录,它将在您下次打开会话时导入(除非您在使用 setwd(...) 关闭会话之前更改了工作目录)。但是我强烈建议您使用 而不是 对较大的数据集执行此操作,因为它会导致您的 R 会话在您下次打开 R 时永远无法打开,并且可能会创建不必要的数据副本(例如,如果您导入它进入 df 并在 df2 中进行转换,然后每次打开 R 时都会突然加载 2.6+ GiB 数据集的 2 个副本。相反,我强烈建议使用 [=28= 保存文件],这是 much(我的意思是 MUCH!!)比另存为 RDScsv 更快的替代方法文件。这些在 Excel 中无法轻松打开,但可以在 R 中使用 arrow::read_parquet 和 python 使用pandas.read_parquetpyarrow.parquet.read_parquet,同时被压缩到通常比等效 csv 文件小 50 - 80% 的大小。

注:

如果您在加载文件后确实保存了 R 会话,并且启动速度非常慢,我建议您从工作目录中删除 .RData 文件。通常是系统中的 documents 文件夹 (C:/Users/[user]/Documents)。