I. Giới Thiệu
Trong CV của mình, mình thường ghi rằng "tôi có khả năng tối ưu API", điều này khiến cho việc phỏng vấn trở nên thú vị hơn khi các nhà tuyển dụng thường đặt câu hỏi về việc tối ưu hóa hệ thống. Trong bài viết này, mình sẽ chia sẻ lại những kinh nghiệm và cách thức mà mình đã áp dụng để tối ưu hiệu suất hệ thống, đặc biệt là về cơ sở dữ liệu (database).
II. Xác Định & Phân Tích Vấn Đề
Bước đầu tiên trong quá trình tối ưu là xác định vấn đề cụ thể nằm ở đâu. Không thể tối ưu một cách ngẫu nhiên mà không biết rõ gốc rễ của vấn đề. Để làm điều này, hãy thực hiện các bước sau:
- Thu thập thông tin từ người dùng để xác định trang hoặc chức năng nào đang hoạt động chậm, từ đó lần tìm nguyên nhân gốc rễ.
- Thiết lập hệ thống logging và monitoring để phát hiện những API nào có thời gian phản hồi chậm nhất.
III. Các Kỹ Thuật Tối Ưu Database
80% vấn đề hiệu suất thường nằm ở cơ sở dữ liệu, vì vậy chúng ta cần tập trung tối ưu nó trước tiên. Dưới đây là một số kỹ thuật tối ưu mà mình đã biết:
1. Không Lấy Dư Cột
- Tránh lấy những cột không cần thiết trong truy vấn để giảm tải băng thông. Tuy nhiên, cần cân nhắc giữa hiệu suất và nguyên tắc DRY (Don't Repeat Yourself) trong việc tổ chức mã nguồn.
2. Đánh Index
- Đánh index cho các trường có dữ liệu lớn để cải thiện khả năng truy vấn. Cần phải đánh index sao cho hợp lý, tránh đánh nhiều index cho từng cột riêng lẻ, và phải cân nhắc thứ tự các cột khi đánh index.
- Tránh đánh index cho những trường có giá trị trùng lặp nhiều, thay vào đó, kết hợp với cột khác để tăng hiệu quả.
3. Tối Ưu Join
- Sử dụng các loại join khác nhau và cân nhắc sử dụng filtered joins, subqueries với EXISTS hoặc IN để giảm thiểu bản ghi trùng lặp. Hãy chú ý đến Lateral Joins trong PostgreSQL khi cần thực hiện các phép join phức tạp.
- Nên sử dụng join thay vì n+1 queries để giảm thiểu gánh nặng cho database.
4. Xử Lý Các Tác Vụ Nặng
- Giảm tải cho database bằng cách đưa những tác vụ nặng về phía backend để xử lý, hoặc lưu trước những kết quả để truy xuất nhanh chóng sau này.
- Sử dụng cronjob cho những thao tác không cần thiết phải diễn ra ngay lập tức, giảm tải cho database trong giờ cao điểm.
5. Quản Lý Kết Nối
- Sử dụng connection pooling để tối ưu hóa số lượng kết nối tới database, giảm thiểu tình trạng trễ do phải chờ kết nối.
6. Scale Up & Scale Out
- Khi hệ thống đạt đến ngưỡng, cần xem xét việc tăng cường tài nguyên (scale up) hoặc phân phối tải (scale out) để cải thiện hiệu suất. Sử dụng mô hình replica giúp tách biệt giữa đọc và ghi sẽ tăng khả năng xử lý.
7. Tìm Kiếm & Lọc Dữ Liệu
- Thiết lập quy trình tìm kiếm và lọc nhất quán giảm thiểu thời gian phát triển mã nguồn. Sử dụng các công cụ tìm kiếm chuyên dụng như Elasticsearch khi database không hỗ trợ tốt tìm kiếm.
8. Phân Vùng Dữ Liệu & Xóa Dữ Liệu Cũ
- Dữ liệu tăng theo thời gian sẽ làm chậm tốc độ truy vấn. Phân vùng (partitioning) dữ liệu có thể cải thiện hiệu suất. Xoá dữ liệu đã cũ hoặc chuyển sang nơi lưu trữ bên ngoài khi không còn cần thiết.
9. Cache Dữ Liệu
- Sử dụng materialized views để cache những dữ liệu ít thay đổi, hoặc sử dụng các hệ thống cache như Redis để tăng tốc độ truy xuất dữ liệu.
10. Giảm Thiểu Phân Mảnh Dữ Liệu
- Dữ liệu thường bị phân mảnh do việc đọc và ghi quá nhiều. Cần kiểm tra và điều chỉnh dữ liệu để giảm thiểu hiện tượng này.
Còn nhiều kiến thức khác về tối ưu hệ thống mà mình sẽ chia sẻ trong phần tiếp theo. Hy vọng những thông tin trên sẽ hữu ích cho các bạn trong việc tối ưu hóa hệ thống của mình.
Tham Khảo
Tham gia cộng đồng lập trình viên trên Discord với hơn 2000 thành viên để thảo luận và cùng phát triển các dự án cá nhân.
source: viblo