Mysql
 sql >> Teknologi Basis Data >  >> RDS >> Mysql

Cara efisien untuk menyisipkan bingkai data dari R ke SQL

TL;DR: LOAD DATA INFILE adalah satu urutan besarnya lebih cepat daripada beberapa INSERT pernyataan, yang sendiri satu urutan besarnya lebih cepat dari INSERT tunggal pernyataan.

Saya membandingkan di bawah tiga strategi utama untuk mengimpor data dari R ke Mysql:

  1. satu insert pernyataan , seperti pada pertanyaan:

    INSERT INTO test (col1,col2,col3) VALUES (1,2,3)

  2. beberapa insert pernyataan , diformat seperti ini:

    INSERT INTO test (col1,col2,col3) VALUES (1,2,3),(4,5,6),(7,8,9)

  3. load data infile pernyataan , yaitu memuat file CSV yang ditulis sebelumnya di mysql :

    LOAD DATA INFILE 'the_dump.csv' INTO TABLE test

Saya menggunakan RMySQL di sini, tetapi driver mysql lainnya harus mengarah ke hasil yang serupa. Tabel SQL dibuat dengan:

CREATE TABLE `test` (
  `col1` double, `col2` double, `col3` double, `col4` double, `col5` double
) ENGINE=MyISAM;

Koneksi dan data uji dibuat di R dengan:

library(RMySQL)
con = dbConnect(MySQL(),
                user = 'the_user',
                password = 'the_password',
                host = '127.0.0.1',
                dbname='test')

n_rows = 1000000 # number of tuples
n_cols = 5 # number of fields
dump = matrix(runif(n_rows*n_cols), ncol=n_cols, nrow=n_rows)
colnames(dump) = paste0('col',1:n_cols)

Pembandingan tunggal insert pernyataan:

before = Sys.time()
for (i in 1:nrow(dump)) {
  query = paste0('INSERT INTO test (',paste0(colnames(dump),collapse = ','),') VALUES (',paste0(dump[i,],collapse = ','),');')
  dbExecute(con, query)
}
time_naive = Sys.time() - before 

=> ini membutuhkan waktu sekitar 4 menit di komputer saya

Pembandingan beberapa insert pernyataan:

before = Sys.time()
chunksize = 10000 # arbitrary chunk size
for (i in 1:ceiling(nrow(dump)/chunksize)) {
  query = paste0('INSERT INTO test (',paste0(colnames(dump),collapse = ','),') VALUES ')
  vals = NULL
  for (j in 1:chunksize) {
    k = (i-1)*chunksize+j
    if (k <= nrow(dump)) {
      vals[j] = paste0('(', paste0(dump[k,],collapse = ','), ')')
    }
  }
  query = paste0(query, paste0(vals,collapse=','))
  dbExecute(con, query)
}
time_chunked = Sys.time() - before 

=> ini membutuhkan waktu sekitar 40 detik di komputer saya

Pembandingan load data infile pernyataan :

before = Sys.time()
write.table(dump, 'the_dump.csv',
          row.names = F, col.names=F, sep='\t')
query = "LOAD DATA INFILE 'the_dump.csv' INTO TABLE test"
dbSendStatement(con, query)
time_infile = Sys.time() - before 

=> ini membutuhkan waktu sekitar 4 detik di komputer saya

Membuat kueri SQL Anda untuk menangani banyak nilai sisipan adalah cara paling sederhana untuk meningkatkan kinerja. Transisi ke LOAD DATA INFILE akan memberikan hasil yang optimal. Kiat kinerja yang baik dapat ditemukan di halaman dokumentasi mysql ini .




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Apa yang Harus Dipantau di MySQL 8.0

  2. Pengantar SQL Bergabung

  3. Menggunakan HHVM Dengan WordPress

  4. Isi database Django

  5. MySQL TIDAK DALAM permintaan