TL; DR: LOAD DATA INFILE
nhanh hơn một bậc của cường độ so với nhiều INSERT
các câu lệnh, bản thân chúng nhanh hơn một bậc so với INSERT
đơn lẻ tuyên bố.
Tôi đánh giá điểm chuẩn bên dưới ba chiến lược chính để nhập dữ liệu từ R vào Mysql:
-
chèn
insert
tuyên bố , như trong câu hỏi:INSERT INTO test (col1,col2,col3) VALUES (1,2,3)
-
nhiều
insert
tuyên bố , được định dạng như vậy:INSERT INTO test (col1,col2,col3) VALUES (1,2,3),(4,5,6),(7,8,9)
-
load data infile
tuyên bố , tức là tải tệp CSV đã viết trước đó trongmysql
:LOAD DATA INFILE 'the_dump.csv' INTO TABLE test
Tôi sử dụng RMySQL
ở đây, nhưng bất kỳ trình điều khiển mysql nào khác sẽ dẫn đến kết quả tương tự. Bảng SQL được khởi tạo bằng:
CREATE TABLE `test` (
`col1` double, `col2` double, `col3` double, `col4` double, `col5` double
) ENGINE=MyISAM;
Kết nối và dữ liệu kiểm tra đã được tạo trong R
với:
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)
Chèn điểm chuẩn insert
tuyên bố:
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
=> quá trình này mất khoảng 4 phút trên máy tính của tôi
Chèn nhiều điểm chuẩn insert
tuyên bố:
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
=> quá trình này mất khoảng 40 giây trên máy tính của tôi
Đo điểm chuẩn load data infile
tuyên bố :
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
=> quá trình này mất khoảng 4 giây trên máy tính của tôi
Tạo truy vấn SQL của bạn để xử lý nhiều giá trị chèn là cách đơn giản nhất để cải thiện hiệu suất. Chuyển sang LOAD DATA INFILE
sẽ dẫn đến kết quả tối ưu. Bạn có thể tìm thấy các mẹo về hiệu suất tốt trong trang này của tài liệu mysql .