Ba method cùng trả về “số lượng”, nhưng với ActiveRecord::Relation, chúng có thể tạo ra ba hành vi khác nhau. Đây là kiểu API nhìn hiền lành cho đến khi production có vài triệu record.
Với Array
1 | values = [1, 2, 3] |
length và size tương đương. count còn hỗ trợ đếm theo giá trị hoặc block:
1 | values.count(2) # => 1 |
Với ActiveRecord::Relation
1 | users = User.where(active: true) |
count
Thông thường gọi SQL COUNT(*) và không load toàn bộ record:
1 | users.count |
Phù hợp khi chỉ cần số lượng từ database.
length
Load relation rồi đếm object trong bộ nhớ:
1 | users.length |
Nếu relation chưa load, đây có thể là một cái giá khá đắt chỉ để biết một con số.
size
size chọn theo trạng thái:
- relation đã load → dùng số phần tử trong bộ nhớ;
- relation chưa load → thường gọi
COUNT(*); - association có counter cache → có thể dùng giá trị cache.
1 | users.load |
Chọn method nào?
- Cần đúng số lượng trong database, không cần record →
count. - Đã có array/relation loaded →
lengthhoặcsize. - Muốn Rails chọn giữa bộ nhớ và database →
size. - Cần kiểm tra có record hay không → ưu tiên
exists?, không phảicount > 0.
1 | User.where(active: true).exists? |
Không có method “luôn nhanh nhất”. Câu hỏi đúng là dữ liệu đang ở database hay đã nằm trong memory. Performance thường chết vì bỏ qua câu hỏi nhỏ đó, không phải vì thiếu thêm một gem monitoring.