Import dữ liệu tốc độ cao trong các ứng dụng Ruby on Rails

1054
30-03-2020
Import dữ liệu tốc độ cao trong các ứng dụng Ruby on Rails

Các nền tảng ứng dụng thường cung cấp hộp công cụ xử lý dữ liệu riêng tuy nhiên các công cụ này chỉ phù hợp với tệp dữ liệu nhỏ, vậy đối với khối lượng dữ liệu lớn thì chúng ta thì sao? 

Khi chưa có nền tảng Ruby on Rails, đối với những người phải nhập đều đặn một khối lượng dữ liệu khổng lồ, có 1 cách đơn giản là sử dụng ActiveRecord. Tuy nhiên ActiveRecord có cơ chế khiến cho việc tạo bản ghi rất chậm nên việc nhập dữ liệu sẽ ngốn rất nhiều thời gian. Những năm gần đây, công cụ Activerecord-import đã trở thành tiêu chuẩn cho việc nhập dữ liệu khối lượng lớn đạt hiệu quả cao. Vậy còn ngần ngại gì nữa, hãy cùng Bizfly Cloud thử sử dụng công cụ Activerecord-import sẽ giúp bạn nhập dữ liệu lên database nhanh chóng và hiệu quả hơn nhé.

Ví dụ đơn giản: 

Thử nhập 100,000 books bằng schema sau: 

create_table :books do |t|

t.column :name, :string, null: false

t.column :description, :string

end

Đây là một giải pháp đơn giản sử dụng ActiveRecord: 

class Book < ActiveRecord::Base

end

Giả sử convert_csv_to_book_attributes là một phương thức convert CSV thành một mảng chứa các thuộc tính của Book model.

convert_csv_to_book_attributes.each do |attrs|

Book.create!(attrs)

end

Đoạn code trên cực kỳ đơn giản nhưng phải mất khoảng 97 giây để thực hiện. Quá lãng phí thời gian. 

Lý do vì sao ActiveRecord lại chậm

Mỗi bản ghi được tạo ra bằng ActiveRecord, đồng nghĩa với việc một câu lệnh truy vấn riêng biệt được tạo ra rồi gửi đến cơ sở dữ liệu. Vì vậy, khi nhập 100,000 books thì đồng nghĩa với gửi 100,000 câu lệnh truy vấn khác nhau  tới cơ sở dữ liệu. Sau đó, cơ sở dữ liệu sẽ phải thao tác trên 100,000 câu lệnh riêng biệt và đóng/mở, thêm/ cập nhật 100,000 các thao tác khác để xử lý dữ liệu. Điều đó khiến việc nhập dữ liệu rất mất thời gian. 

Các gợi ý để tăng tốc dữ liệu

Tăng tốc độ bằng mẫu import có validations

Thay vì dùng create!, thử xây dựng các Book instances trong bộ nhớ và đưa chúng qua Book.import:

books = convert_csv_to_book_attributes.map do |attrs|

Book.new(attrs)

end

Book.import books

Thao tác chỉ tốn cỡ 5 giây, nhanh hơn 19 lần. 

Như vậy, phương thức nhập sẽ tiếp tục có hiệu lực và tìm ra cách tuần tự hóa tất cả các Book Instances thành các câu lệnh SQL có hiệu suất cao.

Tăng tốc độ bằng mẫu import không có validations

Đôi khi trong lúc chuẩn bị dữ liệu khối lượng lớn, chúng ta cần sắp xếp chúng trước, nếu có thể tin tưởng dữ liệu có hiệu lực dựa vào xuất xứ của nó thì ta không cần chạy Activerecord có hiệu lực để nhập dữ liệu. 

Để tăng hiệu suất, chúng ta có thể tắt validations trong quá trình nhập: 

books = convert_csv_to_book_attributes.map do |attrs|

Book.new(attrs)

end

Book.import books, validate: false

Cách này chỉ mất 4.6 giây để nhập 100,000 books, tốc độ tăng lên gấp 21 lần. 

Ở đây ta cài đặt validate: false để thể hiện rằng việc nhập Books có bỏ qua validations. Lựa chọn có giá trị cũng được xác nhận là công nhận là chính xác để thực hiện validations, nhưng bạn cũng có thể giữ validations nếu muốn. 

Tăng tốc độ bằng import các cột và giá trị có validations 

Đôi khi chúng ta đã có sẵn dữ liệu theo một loạt các giá trị và tất cả những gì chúng ta cần làm là khớp với các cột cần import. Nếu bạn muốn bỏ qua việc tự xây dựng in-memory Book Instances, bạn có thể tự mình chuyển một loạt các cột trong bộ nhớ và các giá trị để đưua vào trình nhập: 

columns = [:name, :description]

# Ví dụ [ ['Book #1', 'Good book'], ['Book #2', 'Great Book'], ...]

array_of_book_attrs = convert_csv_to_book_attributes

Book.import columns, array_of_book_attrs, validate: true

Cách này mất khoảng 7.5 giây, tốc độ đã được cải thiện rất nhiều so với thời gian ban đầu tuy nhiên còn chậm hơn cách dùng mẫu import. 

Tăng tốc độ bằng import các cột và giá trị không có validations 

Khi chúng ta không cần xây dựng in-memory Book Instances hoặc khởi tạo validations, ta có thể thực hiện việc tăng tốc bằng cách dưới đây: 

columns = [:title, :description]

# E.g. [ ['Book #1', 'Good book'], ['Book #2', 'Great Book'], ...]

array_of_book_attrs = convert_csv_to_book_attributes

Book.import columns, array_of_book_attrs, validate: false

Với cách này bạn chỉ mất 2.5 giây. Đây là biện pháp tối ưu nhất trong các mục nêu trên, nhanh hơn tới tận 38 lần. 

Benchmarking

Trên đây là các gợi ý để cải thiện tốc độ import dữ liệu khối lượng lớn bằng Activerecord-import. Hãy sử dụng schema trên và xem việc import dữ liệu trên các cơ sở dữ liệu MySQL (InnoDB), PostgreSQL, SQLite3 hiệu quả như thế nào nhé. 

Để chứng minh, chúng tôi sử dụng schema sau đây:

create_table :books do |t|

t.column :name, :string, null: false

t.column :description, :string

end

Kết quả ActiveRecord 4.2.4 trên MySQL (giây)

# of records

ActiveRecord #create

import(models) w/validations

import(models) w/o validations

import(cols, vals) w/validations

import(cols, vals) w/o validations

10

0.017

0.001

0.001

0.002

0.001

100

0.119

0.006

0.006

0.009

0.004

1,000

0.94

0.05

0.043

0.08

0.025

10,000

9.703

0.582

0.433

0.81

0.248

100,000

97.426

4.965

4.662

7.491

2.47

Kết quả ActiveRecord 4.2.4 trên PostgreSQL (giây)

# of records

ActiveRecord #create

import(models) w/validations

import(models) w/o validations

import(cols, vals) w/validations

import(cols, vals) w/o validations

10

0.034

0.002

0.001

0.002

0.001

100

0.108

0.014

0.009

0.009

0.003

1,000

1.075

0.066

0.064

0.074

0.031

10,000

10.503

0.728

0.594

0.764

0.273

100,000

104.788

7.324

6.829

7.449

2.841

Kết quả ActiveRecord 4.2.4 trên SQLite3 (giây)

# of records

ActiveRecord #create

import(models) w/validations

import(models) w/o validations

import(cols, vals) w/validations

import(cols, vals) w/o validations

10

0.022

0.002

0.002

0.002

0.001

100

0.168

0.009

0.007

0.01

0.003

1,000

1.613

0.069

0.057

0.079

0.027

10,000

16.894

0.764

0.594

0.783

0.28

100,000

164.348

7.45

6.621

7.531

2.562

Kết luận 

Việc tăng tốc độ import dữ liệu nhanh hơn từ 13 đến 40 lần đã trở nên đơn giản hơn rất nhiều với chỉ một vài dòng code ngắn gọn của Activerecord-import. Hãy thử làm quen với Activerecord-import và biến nó thành cánh tay đắc lực hỗ trợ bạn trong công việc. 

Theo Bizfly Cloud chia sẻ

>> Có thể bạn quan tâm: Thu thập địa chỉ Email bằng script ruby bằng mã Jigsaw. Jigsaw

BizFly Cloud là hệ sinh thái điện toán đám mây được vận hành bởi VCCorp - Công ty dẫn đầu trong lĩnh vực công nghệ và truyền thông tại Việt Nam. Với đội ngũ kỹ thuật viên trình độ cao và kinh nghiệm lâu năm làm việc trên các công nghệ khác nhau như cloud, mobile, web..., chúng tôi có đủ khả năng để hỗ trợ đưa ra những giải pháp và công nghệ toàn diện giúp doanh nghiệp chuyển đổi số thành công. Dành cho độc giả quan tâm tới các dịch vụ đám mây do BizFly Cloud cung cấp có thể truy cập tại đây.
SHARE