Mysql
 sql >> база данни >  >> RDS >> Mysql

Ефективен начин за вмъкване на рамка от данни от R към SQL

TL;DR: LOAD DATA INFILE е с един порядък по-бързо от множеството INSERT изрази, които сами по себе си са с един порядък по-бързи от единичния INSERT изявления.

Сравнивам по-долу трите основни стратегии за импортиране на данни от R в Mysql:

  1. единично insert изявленията , както във въпроса:

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

  2. множество insert изявленията , форматиран така:

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

  3. load data infile изявление , т.е. зареждане на предварително написан CSV файл в mysql :

    LOAD DATA INFILE 'the_dump.csv' INTO TABLE test

Използвам RMySQL тук, но всеки друг драйвер на mysql би трябвало да доведе до подобни резултати. SQL таблицата беше инстанцирана с:

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

Данните за връзката и тестовете са създадени в R с:

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)

Сравнителен анализ на единично insert изявления:

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 

=> това отнема около 4 минути на моя компютър

Сравнителен анализ на няколко insert изявления:

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 

=> това отнема около 40 секунди на моя компютър

Сравнителен анализ load data infile изявление :

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 

=> това отнема около 4 секунди на моя компютър

Изработването на вашата SQL заявка за обработка на много стойности за вмъкване е най-простият начин за подобряване на производителността. Преминаване към LOAD DATA INFILE ще доведе до оптимални резултати. Съвети за добра производителност можете да намерите в тази страница от документацията на mysql .




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. MySQL най-добрият начин за съхранение на дълги низове

  2. lower_case_table_names=1 на Ubuntu 18.04 не позволява на mysql да стартира

  3. WAMP Няма достъп в локална мрежа 403 Забранено

  4. Защита на MySQL сървър

  5. Получаване на съобщение SQLEXCEPTION в MySQL процедури