+1

Import dữ liệu lớn từ file CSV

Import nhiều dữ liệu vào Rails ActiveRecord models có thể import từ các file JSON, CSV hoặc các loại file khác. Bài này mình sẽ nói về cách import nhiều dữ liệu từ file CSV.

Importing từ file CSV vào trong Rails

Cách xấu Ví dụ trong file CSV của mình có 10000 bản ghi

require 'csv'

csv = File.read('link/to/file.csv')
CSV.parse(csv, headers: true).each do |row|
  Item.create(row.to_h)
end

Cách này sẽ mất rất nhiều thời gian hoặc bị lỗi không import được dữ liệu vì:

  • Load toàn bộ file CSV vào trong bộ nhớ
  • Tạo trăm nghìn bản ghi một

Cách tốt hơn

CSV.foreach('link/to/file.csv', headers: true) do |row|
  Item.create(row.to_h)
end

Cách này thực hiện từng hàng một thay vì load toàn bộ dữ liệu vào trong bộ nhớ nhưng nó vẫn chậm vì mình vẫn dùng cách vòng lặp từng hàng để tạo dữ liệu vào trong database. Cách tốt nhất Dùng active record import để import dữ liệu

items = []
CSV.foreach('link/to/file.csv', headers: true) do |row|
  items << Item.new(row.to_h)
end
Item.import(items)

Thay vì tạo từng bản ghi một mình sẽ thêm dữ liệu vào trong array và chỉ dùng duy nhất một query để import dữ liệu vào trong database

Import dữ liệu mới có quan hệ với dữ liệu cũ

Mình có rất nhiều bản ghi đang cần import và các dữ liệu đó nó có quan hệ với các bảng khác. Lấy ví dụ: có bảng List và bảng Item . Quan hệ giữa 2 bảng là List has_many :items Cách xấu

items = []
CSV.foreach('link/to/file.csv', headers: true) do |row|
  list = List.find_by(name: row[:name])
  items << Item.new(list: list, title: row[:title])
end
Item.import(items)

Mặc dù đã dùng active record import nhưng lại vòng lặp từng hàng đê tìm kiếm find_by trong bảng List Cách tốt nhất

lists_hash = List.pluck(:name, :id).to_h
#// => {'list A' => 1, 'List B' => 2}
items = []
CSV.foreach('link/to/file.csv', headers: true) do |row|
  list_id = lists_hash[row[:name]]
  items << Item.new(list_id: list_id, title: row[:title])
end
Item.import(items)

Dùng một query đê lấy dữ liệu List name, id và đổi thành dạng hash. Trong vòng lặp sẽ không query để tìm bàn ghi của List nữa mà chỉ cần tìm id theo List name trong hash.


All rights reserved

Viblo
Hãy đăng ký một tài khoản Viblo để nhận được nhiều bài viết thú vị hơn.
Đăng kí