Như trong bài viết trước về các vấn đề về hiệu suất của một hệ thống, trong bài viết này chúng ta sẽ nói đến những vấn đề trong việc xử lý logic mà sẽ ảnh hưởng đến hiệu suất của một hệ thống.
Phân trang và hiển thị toàn bộ bản ghi.
Trong việc xử lý logic ở những màn hình danh sách, chúng ta thường sẽ xử lý phân trang các bản ghi thành 10, 20, 50 bản ghi trong một trang. Khi số lượng bản ghi trong một trang tăng lên, thì hiệu suất của trang cũng sẽ bị ảnh hưởng, thời gian load trang cũng sẽ tăng lên.
💡 Trong bài viết này, mình sẽ sử dụng ngôn ngữ PHP, framework Laravel và database MySQL để làm ví dụ trong việc tối ưu hiệu suất. Số lượng bản ghi trên mỗi bảng là 100.000 bản ghi.
Ví dụ, với việc hiển thị phân trang 20, 100, 500, 1000 bản ghi và việc hiển thị toàn bộ bản ghi, thời gian tải trang sẽ tăng lên đáng kể.
- Thời gian tải trang khi phân trang 20 bản ghi là 227ms, thời gian truy vấn là 13.14ms.
- Thời gian tải trang khi phân trang 100 bản ghi là 46ms, thời gian truy vấn là 15.88ms.
- Thời gian tải trang khi phân trang 500 bản ghi là 910ms, thời gian truy vấn là 20.36ms.
- Thời gian tải trang khi phân trang 1000 bản ghi là 16.6s, thời gian truy vấn là 26.6ms.
- Khi hiển thị toàn bộ bản ghi thì bị lỗi Maximum execution time of 60 seconds exceeded.
Như vậy, vấn đề ở đây không phải là vấn đề về truy vấn mà là vấn đề về logic, số lượng bản ghi càng ít thì tốc độ tải trang càng nhanh, do đó khi có một danh sách với số lượng bản ghi càng lớn thì chúng ta nên thực hiện phân trang với số lượng ≤ 100 bản ghi trên mỗi trang để đảm bảo hiệu suất.
Sử dụng các thư viện JS để hiển thị số lượng bản ghi lớn.
Đôi khi một số thư viện JS như datatable, select2 được sử dụng để hiển thị số lượng bản ghi lớn như vậy, chúng ta sẽ gặp lại vấn đề Maximum execution time of 60 seconds exceeded ở trên. Do đó, giải pháp ở đây, thay vì tải hết toàn bộ bản ghi ngay khi tải trang lần đầu, chúng ta sẽ sử dụng ajax (server-side) để phân trang hoặc search để giảm số lượng bản ghi xuống ít hơn 100 bản ghi, khi đó thời gian sẽ giảm đáng kể.
Ví dụ về việc sử dụng datatables hiển thị 100.000 bản ghi nhưng thời gian tải trang chỉ 282ms và thời gian để hiển thị dữ liệu là 424ms.
Tương tự như datatables, trong trường hợp đổ một lượng dữ liệu lớn vào select2 cũng sẽ gây ảnh hưởng đến thời gian tải trang. Ví dụ chúng ta hiển thị 1000 bản ghi user vào select2, thời gian tải trang sẽ khoảng 2s, số lượng bản ghi càng lớn thì thời gian tải trang sẽ tăng lên và sẽ đến một lúc chúng ta sẽ gặp lại lỗi Maximum execution time of 60 seconds exceeded và không tải được trang nữa.
Do đó chúng ta cần phải thay đổi logic khi đổ dữ liệu vào select2, thay vì hiển thị toàn bộ dữ liệu ngay từ lần đầu tải trang, chúng ta sẽ thực hiện hiển thị theo server-side: mỗi khi người dùng gõ một hoặc một vài ký tự, chúng ta sẽ gọi ajax và tìm kiếm các dữ liệu thỏa mãn điều kiện tìm kiếm đó.
Nếu xử lý theo hướng server-side, tốc độ tải trang được cải thiện đang kể:
- Lần đầu tải trang chỉ mất 151ms.
- Mỗi lần tìm kiếm dữ liệu trong select2 mất 500ms.
Thống kê dữ liệu.
Một phần xử lý logic chúng ta cũng cần quan tâm khi tối ưu hiệu suất là phần thống kê. Thông thường, dữ liệu thống kê sẽ trải dài từ lúc hệ thống bắt đầu được sử dụng đến thời điểm hiện tại, do đó lượng dữ liệu cần xử lý là chắc chắn là rất lớn.
Do vậy, nếu như chúng ta thực hiện việc truy vấn trực tiếp và liên tục lấy dữ liệu trực tiếp từ database thì sẽ ảnh hưởng đến nhiều khía cạnh. Thứ nhất, chắc chắn thời gian tải trang ban đầu sẽ chậm do phải truy vấn dữ liệu lớn. Thứ hai, tải của cơ sở dữ liệu sẽ bị ảnh hưởng do liên tục phải thực hiện những câu truy vấn nặng như vậy.
Phương án có thể đưa ra trong trường hợp này là thay vì thực hiện truy vấn trực tiếp đến cơ sở dữ liệu trong các lần thống kê, chúng ta sẽ xử lý tính trước số liệu rồi khi thống kê sẽ chỉ hiển thị các con số đã được tính toán trước đó. Nhược điểm của phương pháp này là dữ liệu sẽ không được thống kê real-time, tuy nhiên chúng ta có thể thực hiện tính toán trước trong khoảng 1 giờ, 2 giờ hoặc 1 ngày, dữ liệu thống kê sẽ không quá cũ mà có thể tăng được đáng kể hiệu suất của database cũng như thời gian tải trang.