Trong bài viết này, bạn sẽ tìm hiểu cách kiểm tra hiệu suất cơ sở dữ liệu trong Rails và giải quyết một số vấn đề phổ biến nhất về hiệu suất cơ sở dữ liệu.
Khi bạn phát triển ứng dụng Rails, ActiveRecord là công cụ mặc định quản lý cơ sở dữ liệu của bạn. ActiveRecord cung cấp giao diện dễ dàng và nhanh chóng để truy vấn và chèn dữ liệu bằng các lệnh như .where , .save , .create , và .update . Rails thực hiện công việc chuyển đổi các lệnh này thành truy vấn SQL, đây là một điều tốt, nhưng đôi khi có thể gây ra vấn đề về hiệu suất. Điều quan trọng là bạn phải hiểu một số vấn đề thường gặp và cách tối ưu hóa hiệu suất.
Ghi chú nhanh về ActiveRecord trong Ruby on Rails
Rails ActiveRecord là một lớp trong Model-View-Controller (MVC) quản lý cơ sở dữ liệu của bạn bằng cách biểu diễn nó như một đối tượng nghiệp vụ. Mẫu ActiveRecord sử dụng kỹ thuật ORM để kết nối các đối tượng của ứng dụng với hệ thống quản lý bảng cơ sở dữ liệu quan hệ.
Bây giờ chúng ta bắt đầu thôi!
3 cách để xác định và kiểm tra các vấn đề về hiệu suất cơ sở dữ liệu trong Rails
1. Chạy Giải thích về Truy vấn ActiveRecord
Câu lệnh giải thích hiển thị thông tin về kế hoạch thực hiện truy vấn SQL - cách truy vấn sẽ được thực thi, bao gồm số lượng hàng sẽ được quét, chỉ mục nào sẽ được sử dụng và cách nối các bảng.
Kế hoạch thực hiện giúp chúng tôi tìm ra nguyên nhân làm chậm quá trình thực thi truy vấn bằng cách xem xét:
- Bạn nên thêm chỉ mục nào để cải thiện hiệu suất của truy vấn.
- Nếu các bảng được nối theo thứ tự tối ưu. Bạn có thể sử dụng
STRAIGHT_JOINđể buộc thứ tự bảng trong câu lệnh nối để có hiệu suất tốt hơn.
Giải thích các hoạt động trên các câu lệnh CHỌN, XÓA, CHÈN, THAY THẾ và CẬP NHẬT.
Sử dụng giải thích với ActiveRecord rất đơn giản. Nhập thông tin sau:
Thêm .explain ở cuối lệnh cung cấp kế hoạch truy vấn cho các lệnh ActiveRecord. Ví dụ trên là một truy vấn rất đơn giản sử dụng id (khóa chính) để truy vấn bảng. Đầu ra của explain câu lệnh cho thấy rằng nó đang sử dụng pkey . Từ đó, bạn có thể chắc chắn rằng câu lệnh là tối ưu và nhanh chóng.
Bạn có thể thử thêm .explain lệnh cho các truy vấn chậm của bạn để khám phá thứ tự thực hiện, cùng với chỉ mục được sử dụng. Nếu kế hoạch truy vấn hiển thị Seq Scan , chỉ mục hiện không được sử dụng và yêu cầu thay đổi truy vấn hoặc thêm chỉ mục mới.
Đây là một ví dụ khác với phép nối:
Ở đây, bảng người dùng được nối với bảng cộng tác. Khi bạn xem xét kế hoạch truy vấn, bảng cộng tác đang sử dụng seq scan và đang thực thi trước — trong khi bảng người dùng đang sử dụng pkey lập chỉ mục và đang thực thi sau đó. Bạn có thể thêm chỉ mục vào user_id trong bảng cộng tác để tối ưu hóa truy vấn này. Giải thích giúp chia nhỏ truy vấn để bạn có thể tìm ra nơi cần tối ưu hóa.
2. Đo lường các số liệu cơ sở dữ liệu chính
Thời gian truy vấn không phải là số liệu duy nhất cần đo lường để xem liệu một truy vấn có hiệu quả hay không — hãy xem xét một số số liệu cơ sở dữ liệu khác, bao gồm:
- Mức sử dụng CPU
- Mức sử dụng bộ nhớ
- Hàng đợi đĩa chờ IO
- Băng thông mạng cho lưu lượng truy cập vào và ra
- Dung lượng đĩa trống
- Thông lượng
Truy vấn có thể chậm lại khi các số liệu này vượt quá một ngưỡng nhất định. Bạn phải xem xét một điểm dữ liệu trong một khoảng thời gian để hiểu các vấn đề về hiệu suất.
Điểm dữ liệu cần đo phụ thuộc vào nhiều yếu tố, như:
-
Loại cơ sở dữ liệu:
- Quan hệ
- Trong bộ nhớ
- Không có SQL
- Kho dữ liệu
-
Cách máy chủ được lưu trữ:
- Tại chỗ
- Trên đám mây
Không có cách duy nhất để theo dõi số liệu cơ sở dữ liệu — nó phụ thuộc vào nhiều yếu tố khác nhau.
3. Đo lường hiệu suất ứng dụng Rails bằng AppSignal
Việc quản lý tất cả số liệu hiệu suất của bạn có thể gặp khó khăn nếu không có vị trí trung tâm cung cấp cho bạn khả năng hiển thị trên tất cả các truy vấn. Việc thêm mã hiệu suất vào mỗi khối mã có thể phức tạp và khó quản lý.
Với các công cụ như AppSignal, bạn có thể dễ dàng tích hợp phép đo hiệu suất vào ứng dụng của mình. AppSignal hỗ trợ Rails ngay lập tức. Tìm hiểu về quy trình cài đặt AppSignal đơn giản từ tài liệu 'AppSignal for Ruby'.
Một số chỉ số quan trọng cần theo dõi là:
- Truy vấn chậm
- Hiệu suất cơ sở dữ liệu dựa trên thông lượng
- N+1 truy vấn
- Độ trễ của cơ sở dữ liệu
- Số lượng kết nối đang hoạt động
Đây là giao diện của trang tổng quan AppSignal:

7 cách để tối ưu hóa hiệu suất cơ sở dữ liệu Ruby on Rails
1. Háo hức tải các truy vấn N+1
Truy vấn N+1 là vấn đề hiệu suất cơ sở dữ liệu phổ biến nhất. Chúng ta hãy xem ví dụ về N+1 truy vấn trong đó bạn có hai mô hình — người dùng và dự án:
Bây giờ, nếu bạn muốn tìm tên người dùng và tên dự án, hãy chạy đoạn mã sau:
Đoạn mã trên sẽ truy vấn cơ sở dữ liệu theo từng vòng lặp và gây ra các vấn đề về hiệu suất. Tổng số truy vấn được thực hiện sẽ là số lượng người dùng + 1.
Việc loại bỏ vấn đề này rất đơn giản:háo hức tải hiệp hội. Chỉ cần thêm .includes(:projects) ở cuối truy vấn:
Bây giờ, việc thực thi vòng lặp sẽ không truy vấn cơ sở dữ liệu, vì truy vấn trên háo hức tải các dự án:
Rails 6.1 cung cấp tính năng tải nghiêm ngặt để đảm bảo rằng liên kết được tải trước khi được truy cập. Để bật tính năng tải nghiêm ngặt, hãy thêm dòng sau vào mô hình:
Bây giờ, khi bạn cố gắng truy cập các dự án mà không cần tải nhanh, Rails sẽ đưa ra ActiveRecord::StrictLoadingViolationError ngoại lệ.
Nếu bạn không có Rails 6.1, bạn có thể sử dụng đá quý như Bullet.
2. Sử dụng chỉ mục cơ sở dữ liệu
Cơ sở dữ liệu cung cấp các chỉ mục để giúp truy xuất dữ liệu nhanh hơn. Sử dụng lệnh giải thích mà chúng tôi đã đề cập trước đó, bạn sẽ có thể tìm hiểu xem truy vấn có đang sử dụng chỉ mục thích hợp hay không.
Bạn có thể thay đổi truy vấn chậm để sử dụng chỉ mục đã có sẵn hoặc chỉ mục được thêm vào để giúp cải thiện hiệu suất.
Có bốn loại chỉ mục khác nhau trong MySQL:
- Khóa chính - Chỉ mục được tự động thêm vào khóa chính, điều này cũng đảm bảo rằng khóa chính là duy nhất
- Duy nhất - Chỉ mục khóa duy nhất đảm bảo rằng các mục được thêm vào thuộc tính luôn là duy nhất
- Chỉ mục - Đã thêm vào các thuộc tính không phải là khóa chính
- Toàn văn - Giúp truy vấn dữ liệu dựa trên ký tự
Chỉ mục được lưu trữ ở định dạng B-Tree hoặc Hash.
Các chỉ mục có thể được thêm vào một trường duy nhất hoặc được tạo dưới dạng thành phần của nhiều trường. Chỉ mục tổng hợp rất hữu ích để tối ưu hóa các truy vấn bao gồm nhiều trường. Khi chỉ sử dụng một chỉ mục, nó yêu cầu quét tập dữ liệu lớn.
Ví dụ:trong truy vấn sau, có hai trường:
Có thể có rất nhiều người dùng trong dự án "abc" và trường quốc gia sẽ được quét. Đây có thể là một quá trình chậm vì tập dữ liệu kết quả lớn. Trong trường hợp này, bạn có thể thêm chỉ mục tổng hợp vào cả trường dự án và quốc gia để cải thiện hiệu suất.
Bạn có thể thêm chỉ mục vào Rails bằng các lệnh di chuyển ActiveRecord sau:
Chỉ số đơn:
Chỉ số tổng hợp:
3. Giới hạn sử dụng
Càng nhiều bản ghi được trả về, hiệu suất có thể càng chậm. Thực hiện nhiều truy vấn sẽ tốt hơn là thực hiện một truy vấn duy nhất trả về một tập dữ liệu lớn.
Để tìm nạp 100 lô tiếp theo, bạn có thể sử dụng offset:
Điều này sẽ cải thiện đáng kể hiệu suất. Một điều cần lưu ý là với độ lệch cao hơn, truy vấn sẽ chậm hơn. Thêm giới hạn cho phần bù.
4. Sử dụng find_each Để tải một số lượng lớn các mục
Khi lặp lại các bản ghi, hãy sắp xếp chúng theo nhóm trong Rails để có hiệu suất tốt hơn:
Điều này sẽ truy vấn tất cả các bản ghi trong cơ sở dữ liệu một lần và gây ra các vấn đề về hiệu suất bộ nhớ và cơ sở dữ liệu.
Sử dụng find_each hoặc find_in_batches sẽ giúp cải thiện hiệu suất bằng cách thực hiện cùng một thao tác trong một đợt:
Theo mặc định, find_each các truy vấn dẫn đến một lô 1.000. Bạn có thể thay đổi kích thước lô bằng cách xác định nó làm đối số:
Bạn cũng có thể sử dụng find_in_batches dựa trên thao tác bạn cần thực hiện. Sự khác biệt giữa find_in_batches và find_each đó có phải là find_in_batches mang lại kết quả dưới dạng một mảng các mô hình thay vì các bản ghi riêng lẻ.
5. Chọn trường bắt buộc của bạn bằng cách sử dụng Pluck
Lệnh Pluck chuyển đổi trực tiếp kết quả của truy vấn thành một mảng thay vì đối tượng ActiveRecord.
Nếu một truy vấn trả về kết quả lớn, việc sử dụng Pluck sẽ cải thiện hiệu suất mã. Pluck sẽ chỉ chọn trường bắt buộc từ cơ sở dữ liệu:
Kết quả được tìm nạp từ một chỉ mục chứ không phải bảng chính và hiệu quả hơn với các truy vấn liên quan đến sắp xếp.
6. Sử dụng các thao tác hàng loạt
Xóa hàng loạt Một thao tác xóa lặp qua đối tượng ActiveRecord sẽ xóa từng bản ghi một:
Việc xóa từng bản ghi đòi hỏi phải thực hiện nhiều truy vấn tới cơ sở dữ liệu. Thay vào đó, tốt nhất là sử dụng một delete_all số lượng lớn duy nhất truy vấn:
Tạo hàng loạt Một số người không nhận ra rằng tương tự như xóa hàng loạt, bạn cũng có thể thực hiện chèn hàng loạt bằng ActiveRecord. Điều này có thể làm giảm n số lượng truy vấn chỉ có một. ActiveRecord::Base create phương thức chấp nhận một mảng băm làm đầu vào:
7. Sử dụng tính toán trong bộ nhớ nếu cần
Trong một số trường hợp, tính toán trong bộ nhớ được ưu tiên hơn là truy vấn. Giả sử chúng tôi muốn tìm các quốc gia trong cơ sở dữ liệu của mình không có hồ sơ người dùng:
Truy vấn trên yêu cầu N truy vấn để có kết quả. Thay vì làm như vậy, chúng ta có thể viết một truy vấn để tìm người dùng ở các quốc gia nhất định và thực hiện phép tính khác trong bộ nhớ:
Bạn có thể lưu vào bộ đệm để sử dụng lại chu trình phản hồi yêu cầu và giảm tải cơ sở dữ liệu trong một số trường hợp. Rails cung cấp ba loại kỹ thuật bộ nhớ đệm:bộ nhớ đệm trang, hành động và phân đoạn (bộ nhớ đệm phân đoạn được cung cấp theo mặc định).
Kết thúc:Tối ưu hóa hiệu suất Ruby on Rails của bạn với ActiveRecord và AppSignal
Được rồi, đã đến lúc tóm tắt lại! Trong bài đăng này, chúng tôi đã đề cập đến ba cách để xác định và kiểm tra các vấn đề về hiệu suất cơ sở dữ liệu trong Rails bằng cách:
- Chạy Giải thích về truy vấn ActiveRecord
- Đo lường các số liệu cơ sở dữ liệu quan trọng
- Đo hiệu suất ứng dụng Rails bằng AppSignal
Và bảy cách để tối ưu hóa hiệu suất cơ sở dữ liệu của bạn, bao gồm cả việc sử dụng:
- Háo hức tải các truy vấn N+1
- Chỉ mục cơ sở dữ liệu
- giới hạn
find_eachđể tải một số lượng lớn các mục- Nhảy để chọn trường bắt buộc
- Hoạt động hàng loạt
- Tính toán trong bộ nhớ
Rails giúp việc phát triển một ứng dụng trở nên cực kỳ dễ dàng và nhanh chóng. ActiveRecord giúp tăng năng suất, khả năng sử dụng lại và khả năng bảo trì của mã cơ sở dữ liệu. Hiểu cách truy vấn ActiveRecord chuyển sang truy vấn SQL và thực thi là điều quan trọng.
Tuy nhiên, điều quan trọng nhất bạn cần để tối ưu hóa hiệu suất cơ sở dữ liệu Rails của mình là khả năng hiển thị dữ liệu hiệu suất. Các vấn đề về hiệu suất là phổ biến nhưng bạn có thể giải quyết chúng khi có được khả năng hiển thị này. Bạn cần một công cụ giám sát thích hợp cung cấp số liệu cơ sở dữ liệu. Chúng tôi thích AppSignal;)
Tái bút. Nếu bạn muốn đọc các bài đăng của Ruby Magic ngay khi chúng được đăng tải, hãy đăng ký nhận bản tin Ruby Magic của chúng tôi và không bao giờ bỏ lỡ một bài đăng nào!