Tối ưu hoá tốc độ truy vấn trong Rails app – phần 1
Rails
33
RubyOnRails
40
OptimizeQuery
1
White

Ruby Nguyen viết ngày 02/07/2015

Khi làm việc với các project nhỏ mình ít quan tâm đến phần tối ưu hóa truy vấn, vì với lượng data ít và quan hệ giữa các table đơn giản nên app nhanh hay chậm có thể khó nhận biết. Nhưng khi phải tính toán metrics, thực hiện các thống kê có dữ liệu từ nhiều bảng và lượng data ở mỗi bảng rất lớn. Mình đã "hoang mang" khi nhìn trang luôn ở trạng thái loading dù ở localhost và màn hình console các câu truy vấn cứ chạy không ngừng. Đến lúc này, mình đã thực cảm nhận được chữ "chậm". Sau khi tự tìm hiểu, cũng như tham khảo ý kiến từ các anh chị đi trước, mình đã có thể làm trang chạy nhanh hơn, dưới đây là một số điều mình thấy thực sự hữu ích nếu muốn cải thiện tốc độ truy vấn:

1. Tránh N + 1 query

N + 1 query là khái niệm được dùng để chỉ việc bạn load hàng loạt các object từ database lên sau đó thực hiện foreach trên các object và thực hiện các câu truy vấn trên các object đó.

Ví dụ như mình có 2 model là Customer và Address, mỗi customer có một address và một address thuộc về một customer.

 # Model
class Customer < ActiveRecord::Base
  has_one :address
end

class Address < ActiveRecord::Base
  belongs_to :customer
end

# Controller
def index
 @customers = Customer.all
end

# View
<% @customers.each do |c| %>
  <%= c.name %>
  <%= c.address %>
<% end %>

Chúng ta hãy chú ý vào phần view, câu lệnh c.name thì hoạt động tốt vì object đã được load lên bộ nhớ từ controller. Tuy nhiên câu lệnh c.address sẽ thực hiện các truy vấn vào database. Tưởng tượng nếu như chúng ta có 100, 1000,... customer như vậy số câu truy vấn sẽ lên đến 100, 1000,...

Cách giải quyết ở đây là sử dụng eager loading, controller sẽ được cập nhật lại thành

# Controller
def index
  @customers = Customer.all.includes(:address)
end

Như vậy address đã được load lên cùng với customer. Một câu query lớn sẽ hiệu quả hơn là chạy rất nhiều câu query.

2. Nên sử dụng các scope cho việc truy vấn để tạo ra ít câu truy vấn nhất có thể có

Các scope được hỗ trợ bởi rails, giúp định nghĩa các điều kiện truy vấn, chúng ta có thể kết nối nhiều scope với nhau mà không tạo ra nhiều câu truy vấn. Các bạn quan tâm có thể tìm hiểu thêm về scope tại đây

3. Chú ý đến thứ tự truy vấn để thu nhỏ dần tập hợp

Về phần này ví dụ như mình có User, Post, Comment, một user có thể có nhiều post, một post có thể có nhiều comment, một comment thuộc về một post, comment có 2 trạng thái là displayed/hidden. Mình muốn hiển thị ra tất cả các comment bị hidden của một post của một user. Tại đây nếu mình tìm user, rồi tìm post, rồi tìm các comment bị hide của post sẽ nhanh hơn là tìm ngược lại.

Những chia sẻ của mình chắc chắn sẽ còn thiếu nhiều cách hay và tốt để tối ưu hoá truy vấn nên rất hi vọng nhận được nhiều sự chia sẻ từ các bạn :)

Nguồn tham khảo: N+1 query

Ruby Nguyen

Bình luận


White
{{ comment.user.name }}
Bỏ hay Hay
{{comment.like_count}}
Male avatar
{{ comment_error }}
Hủy
   

Hiển thị thử

Chỉnh sửa

White

Ruby Nguyen

3 bài viết.
35 người follow
Kipalog
{{userFollowed ? 'Following' : 'Follow'}}
Cùng một tác giả
White
43 13
Scrum là một mô hình quản lý dự án tương đối hot và được nhiều công ty áp dụng hiện nay nên chắc hẳn các bạn đã nghe đến rất nhiều đặc biệt là các ...
Ruby Nguyen viết hơn 3 năm trước
43 13
White
21 7
Từ khi có nhiều thiết bị thông minh ra đời như điện thoại, tablet hỗ trợ người dùng xem các trang web trực tiếp trên các trình duyệt được tích hợp,...
Ruby Nguyen viết hơn 3 năm trước
21 7
Bài viết liên quan
White
21 3
Giao diện lập trình ứng dụng, còn gọi là API (Application Programming Interface) là chương trình cho phép người dùng sử dụng các phương thức của mộ...
chuong2v viết hơn 3 năm trước
21 3
{{like_count}}

kipalog

{{ comment_count }}

bình luận

{{liked ? "Đã kipalog" : "Kipalog"}}


White
{{userFollowed ? 'Following' : 'Follow'}}
3 bài viết.
35 người follow

 Đầu mục bài viết

Vẫn còn nữa! x

Kipalog vẫn còn rất nhiều bài viết hay và chủ đề thú vị chờ bạn khám phá!