Tips Tối ưu hóa query Active Record

Tram Ho

Sau đây, mình xin hướng dẫn các bạn một vài típ có thể tối ưu hóa query khi sử dụng Active Record nhé

1. Sử dụng Eager Loading với includes để tránh n+1 query

  • Ví dụ, nếu bạn có n rows của bảng Post nếu gọi như bình thường sẽ khi gọi tất cả bản ghi comments của Post ra thì nó sẽ tạo ra các câu query như sau:

  • Tuy nhiên, nếu ở đây ta sử dụng includes thì chúng ta chỉ mất 2 query là có thể lấy ra dữ liệu mà chúng ta cần:


2. Sử dụng find_each khi load một lượng lớn các bản ghi

  • Nếu sử dụng cách này nó sẽ khiến ta sẽ tăng số lượng truy vấn được thực hiện, nhưng nó sẽ giảm lượng bộ nhớ mà ta sử dụng khi tải một lượng lớn bản ghi.

  • Ở đây, thay vì tải một lượng lớn các bản ghi vào bộ nhớ để xử lý (điều này, có thể làm sập máy chủ nếu có quá nhiều bản ghi) thì find_each tải từng batch một lần và sẽ thu thập chúng lại sau khi sử dụng.

3. Sử dụng SelectPluck cho attributes

  • Đôi khi, chúng ta không cần lấy tất cả các thuộc tính của model, mà chỉ lấy một vài thuộc tính của model đó thôi thì ta có thể sử dụng pluck để truy vấn các thuộc tính cần thiết và trả về chúng dưới dạng một Array thay vì ActiveRecord_Relation.
  • Tuy nhiên, nếu ta cần trả về dưới dạng ActiveRecord_Relation, ta có thể sử dụng select.


4. Sử dụng exists? để kiểm tra sự tồn tại của bản ghi

  • Đôi khi, chúng ta chỉ muốn biết bản ghi có tồn tại hay không, mà không cần phải làm gì với bản ghi đó. Ta có thể sử dụng exists?


5. Sử dụng ActiveRecord::Relation#size thay vì ActiveRecord::Calculations#count

  • Ví dụ ta có ActiveRecord :: Relation Post, khi sử dụng posts.countposts.size thì nó đều trả về số lượng posts. Tuy nhiên, posts.count sẽ luôn chạy truy vấn như SELECT COUNT(*) FROM posts WHERE ... ngay cả khi các mối quan hệ đã được tải.
  • Còn size sẽ thông minh hơn ở chỗ nó sẽ gọi length nếu mối quan hệ nếu nó đã được tải nhưng nó sẽ gọi count nếu mối quan hệ chưa được tải.


6. Sử dụng delete_all số lượng lớn các bản ghi

  • Khi muốn xóa một số lượng lớn các bản ghi không require Active Record callback, hãy sử dụng delete_all hoặc thay vì gọi destroy cho các đối tượng riêng lẻ.


7. Sử dụng create cho array chứa hash

  • ActiveRecord::Base#create có thể chấp nhận array chứa các hash bên trong để tạo các bản ghi. Nó sẽ chạy một query thay vì N query như bình thường. Tuy nhiên, điều kiện ở đây là CSDL của chúng ta phải hỗ trỡ việc insert hàng loạt như thế này. Ví dụ:


8. Sử dụng update cho nhiều bản ghi cùng lúc

  • Tương tự, cũng có thể update nhiều bản ghi trong một truy vấn


Cảm ơn các bạn đã đọc bài viết của mình!

Tà liệu tham khảo: Medium
Chia sẻ bài viết ngay

Nguồn bài viết : Viblo