通过 R 将数据上传到 PostgresQL 12 的最快方法
Fastest way to upload data via R to PostgresSQL 12
我正在使用以下代码连接到 PostgreSQL 12 数据库:
con <- DBI::dbConnect(odbc::odbc(), driver, server, database, uid, pwd, port)
这将我连接到 Google 云 SQL 上的 PostgreSQL 12 数据库。然后使用以下代码上传数据:
DBI::dbCreateTable(con, tablename, df)
DBI::dbAppendTable(con, tablename, df)
其中 df
是我在 R 中创建的数据框。该数据框包含约 550,000 条记录,总计 713 MB 数据。
用上述方法上传时,以40写的速度,耗时约9小时operations/second。有没有更快的方法将这些数据上传到我的 PostgreSQL 数据库,最好是通过 R?
我一直发现批量复制是最好的,在 R 外部。插入可以明显更快,并且您的开销是 (1) 写入文件,以及 (2) 更短 运行-时间。
此测试的设置:
- win10 (2004)
- docker
- postgres:11 容器,在本地主机上使用端口 35432,简单身份验证
- 主机OS中的
psql
二进制文件(其中R是运行ning);使用 linux 应该很容易,使用 windows 我从 https://www.postgresql.org/download/windows/ 抓取了 "zip" (不是安装程序)文件并提取了我需要的东西
- 我正在使用
data.table::fwrite
保存文件,因为它快;在这种情况下,write.table
和 write.csv
仍然比使用 DBI::dbWriteTable
快得多,但根据您的数据量,您可能更喜欢快速
DBI::dbCreateTable(con2, "mt", mtcars)
DBI::dbGetQuery(con2, "select count(*) as n from mt")
# n
# 1 0
z1000 <- data.table::rbindlist(replicate(1000, mtcars, simplify=F))
nrow(z1000)
# [1] 32000
system.time({
DBI::dbWriteTable(con2, "mt", z1000, create = FALSE, append = TRUE)
})
# user system elapsed
# 1.56 1.09 30.90
system.time({
data.table::fwrite(z1000, "mt.csv")
URI <- sprintf("postgresql://%s:%s@%s:%s", "postgres", "mysecretpassword", "127.0.0.1", "35432")
system(
sprintf("psql.exe -U postgres -c \"\copy %s (%s) from %s (FORMAT CSV, HEADER)\" %s",
"mt", paste(colnames(z1000), collapse = ","),
sQuote("mt.csv"), URI)
)
})
# COPY 32000
# user system elapsed
# 0.05 0.00 0.19
DBI::dbGetQuery(con2, "select count(*) as n from mt")
# n
# 1 64000
虽然这比您的数据小很多(32K 行,11 列,1.3MB 数据),但不能忽略从 30 秒到不到 1 秒的加速。
旁注:dbAppendTable
(慢)和 dbWriteTable
之间也存在相当大的差异。比较 psql
和这两个函数:
z100 <- rbindlist(replicate(100, mtcars, simplify=F))
system.time({
data.table::fwrite(z100, "mt.csv")
URI <- sprintf("postgresql://%s:%s@%s:%s", "postgres", "mysecretpassword", "127.0.0.1", "35432")
system(
sprintf("/Users/r2/bin/psql -U postgres -c \"\copy %s (%s) from %s (FORMAT CSV, HEADER)\" %s",
"mt", paste(colnames(z100), collapse = ","),
sQuote("mt.csv"), URI)
)
})
# COPY 3200
# user system elapsed
# 0.0 0.0 0.1
system.time({
DBI::dbWriteTable(con2, "mt", z100, create = FALSE, append = TRUE)
})
# user system elapsed
# 0.17 0.04 2.95
system.time({
DBI::dbAppendTable(con2, "mt", z100, create = FALSE, append = TRUE)
})
# user system elapsed
# 0.74 0.33 23.59
(我不想用上面的 z1000
来计算 dbAppendTable
的时间...)
(为了踢球,我 运行 它与 replicate(10000, ...)
和 运行 psql
和 dbWriteTable
再次测试,他们花了 2 秒和 372秒,你的选择:-) ...现在我有超过 650,000 行 mtcars
... hrmph ... drop table mt
...
我怀疑 dbAppendTable
导致每行有一个 INSERT
语句,这对于大量行可能需要很长时间。
但是,您可以使用 sqlAppendTable
函数为整个数据框生成单个 INSERT
语句,并通过显式使用 dbSendQuery
运行 它:
res <- DBI::dbSendQuery(con, DBI::sqlAppendTable(con, tablename, df, row.names=FALSE))
DBI::dbClearResult(res)
对我来说,这要快得多:30 秒的摄取减少到 0.5 秒的摄取。
我正在使用以下代码连接到 PostgreSQL 12 数据库:
con <- DBI::dbConnect(odbc::odbc(), driver, server, database, uid, pwd, port)
这将我连接到 Google 云 SQL 上的 PostgreSQL 12 数据库。然后使用以下代码上传数据:
DBI::dbCreateTable(con, tablename, df)
DBI::dbAppendTable(con, tablename, df)
其中 df
是我在 R 中创建的数据框。该数据框包含约 550,000 条记录,总计 713 MB 数据。
用上述方法上传时,以40写的速度,耗时约9小时operations/second。有没有更快的方法将这些数据上传到我的 PostgreSQL 数据库,最好是通过 R?
我一直发现批量复制是最好的,在 R 外部。插入可以明显更快,并且您的开销是 (1) 写入文件,以及 (2) 更短 运行-时间。
此测试的设置:
- win10 (2004)
- docker
- postgres:11 容器,在本地主机上使用端口 35432,简单身份验证
- 主机OS中的
psql
二进制文件(其中R是运行ning);使用 linux 应该很容易,使用 windows 我从 https://www.postgresql.org/download/windows/ 抓取了 "zip" (不是安装程序)文件并提取了我需要的东西 - 我正在使用
data.table::fwrite
保存文件,因为它快;在这种情况下,write.table
和write.csv
仍然比使用DBI::dbWriteTable
快得多,但根据您的数据量,您可能更喜欢快速
DBI::dbCreateTable(con2, "mt", mtcars)
DBI::dbGetQuery(con2, "select count(*) as n from mt")
# n
# 1 0
z1000 <- data.table::rbindlist(replicate(1000, mtcars, simplify=F))
nrow(z1000)
# [1] 32000
system.time({
DBI::dbWriteTable(con2, "mt", z1000, create = FALSE, append = TRUE)
})
# user system elapsed
# 1.56 1.09 30.90
system.time({
data.table::fwrite(z1000, "mt.csv")
URI <- sprintf("postgresql://%s:%s@%s:%s", "postgres", "mysecretpassword", "127.0.0.1", "35432")
system(
sprintf("psql.exe -U postgres -c \"\copy %s (%s) from %s (FORMAT CSV, HEADER)\" %s",
"mt", paste(colnames(z1000), collapse = ","),
sQuote("mt.csv"), URI)
)
})
# COPY 32000
# user system elapsed
# 0.05 0.00 0.19
DBI::dbGetQuery(con2, "select count(*) as n from mt")
# n
# 1 64000
虽然这比您的数据小很多(32K 行,11 列,1.3MB 数据),但不能忽略从 30 秒到不到 1 秒的加速。
旁注:dbAppendTable
(慢)和 dbWriteTable
之间也存在相当大的差异。比较 psql
和这两个函数:
z100 <- rbindlist(replicate(100, mtcars, simplify=F))
system.time({
data.table::fwrite(z100, "mt.csv")
URI <- sprintf("postgresql://%s:%s@%s:%s", "postgres", "mysecretpassword", "127.0.0.1", "35432")
system(
sprintf("/Users/r2/bin/psql -U postgres -c \"\copy %s (%s) from %s (FORMAT CSV, HEADER)\" %s",
"mt", paste(colnames(z100), collapse = ","),
sQuote("mt.csv"), URI)
)
})
# COPY 3200
# user system elapsed
# 0.0 0.0 0.1
system.time({
DBI::dbWriteTable(con2, "mt", z100, create = FALSE, append = TRUE)
})
# user system elapsed
# 0.17 0.04 2.95
system.time({
DBI::dbAppendTable(con2, "mt", z100, create = FALSE, append = TRUE)
})
# user system elapsed
# 0.74 0.33 23.59
(我不想用上面的 z1000
来计算 dbAppendTable
的时间...)
(为了踢球,我 运行 它与 replicate(10000, ...)
和 运行 psql
和 dbWriteTable
再次测试,他们花了 2 秒和 372秒,你的选择:-) ...现在我有超过 650,000 行 mtcars
... hrmph ... drop table mt
...
我怀疑 dbAppendTable
导致每行有一个 INSERT
语句,这对于大量行可能需要很长时间。
但是,您可以使用 sqlAppendTable
函数为整个数据框生成单个 INSERT
语句,并通过显式使用 dbSendQuery
运行 它:
res <- DBI::dbSendQuery(con, DBI::sqlAppendTable(con, tablename, df, row.names=FALSE))
DBI::dbClearResult(res)
对我来说,这要快得多:30 秒的摄取减少到 0.5 秒的摄取。