Importing data quickly in Ruby on Rails applications
Việc dùng ActiveRecord để insert dữ liệu vào database là việc làm hết sức thường xuyên và quá quen thuộc với các lập trình viên chúng ta. Vấn đề đặt ra là chúng ta đã có rất nhiều dữ liệu mà cần phải thường xuyên tích hợp vào một ứng dụng cục bộ, nhưng cơ chế của ActiveRecord để tạo các bản ghi là ...
Việc dùng ActiveRecord để insert dữ liệu vào database là việc làm hết sức thường xuyên và quá quen thuộc với các lập trình viên chúng ta. Vấn đề đặt ra là chúng ta đã có rất nhiều dữ liệu mà cần phải thường xuyên tích hợp vào một ứng dụng cục bộ, nhưng cơ chế của ActiveRecord để tạo các bản ghi là quá chậm. Vậy chúng ta cải thiện tốc độ này bằng cách nào? Ruby đã cung cấp cho chúng ta một gem activerecord-import và nó có sẵn trong rubygem, đã trở thành tiêu chuẩn và vô cùng hữu ích cho việc nhập dữ liệu hàng loạt với ActiveRecord một cách hiệu quả.
ActiveRecord Import is a gem that helps you do bulk inserts using ActiveRecong
- Cài đặt Cho vào gem file và chạy bundle install trên command line là chúng ta có thể sử dụng được
#gemfile gem "activerecord-import"
- Sử dụng Để hiểu hơn về cách dùng activerecord-import chúng ta cùng xem qua ví dụ đơn giản sau: Gỉa dụ rằng, ta có bảng books như sau:
create_table :books do |t| t.column :name, :string, null: false t.column :description, :string end
Bây giờ ta muốn insert 100000 record vào DB: Dưới đây, ta sẽ có cách insert đơn giản nhất là sử dụng ActiveRecord
class Book < ActiveRecord::Base end # convert_csv_to_books is a method that converts CSV into an array of Book models, returning an array of attributes convert_csv_to_book_attributes.each do |attrs| Book.create!(attrs) end
Tuy nhiên, đoạn code phía trên, mất ~97s để insert xong, thật sự rất chậm.
Vậy tại sao ActiveRecord lại chậm như thế?
Tốc độ thực hiện chậm và mất nhiều thời gian vì mỗi khi tạo một bản ghi với ActiveRecord, một câu lệnh INSERT đơn sẽ được tạo ra và gửi đến cơ sở dữ liệu. Insert 100000 record tương đương với gửi 100.000 câu lệnh riêng biệt tới cơ sở dữ liệu, cơ sở dữ liệu phải phân tích 100.000 câu lệnh riêng biệt, mở và đóng bảng 100.000 lần để viết, ghi dữ liệu, insert và update các chỉ mục 100.000 lần.
*Chúng ta sẽ thực hiện một thay đổi nhỏ để tăng tốc độ này: *
Tăng tốc độ bằng việc import models với validations: Thay vì dùng create!, chúng ta sẽ build các instance của Book và sau đó sẽ dùng Book.import
books = convert_csv_to_book_attributes.map do |attrs| Book.new(attrs) end Book.import books
Dùng import chỉ mất ~5s, tức là tăng gấp gần 19 lần. Tốc độ đươc cải thiện một cách đáng kể