La fonction sqlSave
du package RODBC standard, même sous la forme d'une seule instruction INSERT
(paramètre fast = TRUE
), est extrêmement lente pour les grandes quantités de données en raison d'un chargement non minimal. Comment pourrais-je écrire des données sur mon serveur SQL avec une journalisation minimale pour qu'il écrive beaucoup plus rapidement?
J'essaie actuellement:
toSQL = data.frame(...);
sqlSave(channel,toSQL,tablename="Table1",rownames=FALSE,colnames=FALSE,safer=FALSE,fast=TRUE);
En écrivant les données sur un fichier CSV localement, puis en utilisant un BULK INSERT
(non disponible comme fonction prédéfinie semblable à sqlSave
), les données peuvent être écrites très rapidement sur le serveur MS SQL.
toSQL = data.frame(...);
write.table(toSQL,"C:\\export\\filename.txt",quote=FALSE,sep=",",row.names=FALSE,col.names=FALSE,append=FALSE);
sqlQuery(channel,"BULK
INSERT Yada.dbo.yada
FROM '\\\\<server-that-SQL-server-can-see>\\export\\filename.txt'
WITH
(
FIELDTERMINATOR = ',',
ROWTERMINATOR = '\\n'
)");
SQL Server doit avoir la permission d'accéder au dossier réseau contenant le fichier CSV, sinon ce processus ne fonctionnera pas. Bien que cela nécessite certaines configurations avec diverses autorisations (le dossier réseau et les privilèges BULK ADMIN
, la récompense en vitesse est infiniment plus précieuse).
Je suis tout à fait d’accord que BULK INSERT
est la bonne option pour toutes les données qui sont non minuscules . Toutefois, dans le cas où vous auriez besoin d’ajouter 2 ou 3 lignes, par exemple. message de débogage BULK INSERT
semble être une overkill.
La réponse à votre question serait une fonction DBI::dbWriteTable()
. Exemple ci-dessous (je connecte mon code R à l'instance AWS RDS
de MS SQL Express
):
library(DBI)
library(RJDBC)
library(tidyverse)
# Specify where you driver lives
drv <- JDBC(
"com.Microsoft.sqlserver.jdbc.SQLServerDriver",
"c:/R/SQL/sqljdbc42.jar")
# Connect to AWS RDS instance
conn <- drv %>%
dbConnect(
Host = "jdbc:sqlserver://xxx.ccgqenhjdi18.ap-southeast-2.rds.amazonaws.com",
user = "xxx",
password = "********",
port = 1433,
dbname= "qlik")
if(0) { # check what the conn object has access to
queryResults <- conn %>%
dbGetQuery("select * from information_schema.tables")
}
# Create test data
example_data <- data.frame(animal=c("dog", "cat", "sea cucumber", "sea Urchin"),
feel=c("furry", "furry", "squishy", "spiny"),
weight=c(45, 8, 1.1, 0.8))
# Works in 20ms in my case
system.time(
conn %>% dbWriteTable(
"qlik.export.test",
example_data
)
)
# Let us see if we see the exported results
conn %>% dbGetQuery("select * FROM qlik.export.test")
# Let's clean the mess and force-close connection at the end of the process
conn %>% dbDisconnect()
Cela fonctionne assez rapidement pour de petites quantités de données transférées et semble assez élégant si vous voulez une solution data.frame
-> SQL table
.
Prendre plaisir!