Chuyển đến nội dung chính
Rails

Tăng tốc xuất CSV lớn trên Rails: N+1, đọc theo lô và streaming

Các điểm cần kiểm tra và ví dụ triển khai để tăng tốc chức năng tải CSV hay bị timeout mà không phải chuyển sang xử lý nền.

Tải CSV ở màn hình quản trị là chức năng điển hình chậm dần khi dữ liệu tăng và cuối cùng bị timeout. Trước khi chuyển sang xử lý bất đồng bộ, nên kiểm tra xem còn cải thiện được khi vẫn xử lý đồng bộ hay không.

Nguyên nhân thường gặp

Ví dụ triển khai

def export
  headers["Content-Type"] = "text/csv; charset=utf-8"
  headers["Content-Disposition"] = %(attachment; filename="orders.csv")
  headers["X-Accel-Buffering"] = "no"

  self.response_body = Enumerator.new do |out|
    out << "\uFEFF" # thêm BOM để excel không lỗi font
    out << CSV.generate_line(%w[order_no customer total ordered_at])
    Order.where(created_at: range).in_batches(of: 2_000) do |batch|
      batch.joins(:customer)
           .pluck(:number, "customers.name", :total, :created_at)
           .each { |row| out << CSV.generate_line(row) }
    end
  end
end

Đọc theo từng lô bằng in_batches và chỉ lấy các cột cần thiết dưới dạng mảng bằng pluck giúp giảm mạnh chi phí tạo đối tượng. Dùng Enumerator làm response thì dòng nào tạo xong sẽ được gửi ngay, rút ngắn thời gian đến byte đầu tiên.

Kiểm chứng hiệu quả

Bắt đầu bằng 30 phút
trao đổi bằng tiếng Nhật.

Quý khách có thể liên hệ ngay cả khi mới ở mức "Việc này có làm được không?". Bridge SE sẽ phản hồi trong 1 ngày làm việc và chúng tôi không gọi điện chào hàng làm phiền.

Liên hệ qua emailTư vấn miễn phí