[Backend] Đo lường tốc độ Query: Đừng đoán, hãy đo!
Trong quá trình phát triển ứng dụng, chúng ta thường nghe câu: "Câu query này chậm quá!". Nhưng "chậm" là bao nhiêu? 500ms, 2s hay 10s? Là một Developer, chúng ta không làm việc với cảm giác, chúng ta làm việc với những con số.
Hôm nay, mình sẽ hướng dẫn các bạn các cách "check" chính xác thời gian thực thi (Execution Time) của một câu query trên các hệ quản trị CSDL phổ biến và cả ở mức Application.\
1. Tại sao phải đo bằng Mili giây (ms)?
Một truy vấn chạy mất 200ms có vẻ nhanh, nhưng nếu trang web của bạn thực hiện 10 truy vấn như vậy để load một trang, người dùng sẽ phải đợi ít nhất 2 giây. Việc nắm được con số ms chính xác giúp bạn:
- Xác định được "điểm nghẽn" (bottleneck) nằm ở DB hay ở Code.
- Đánh giá hiệu quả sau khi đánh Index hoặc Refactor.
- Thiết lập các ngưỡng cảnh báo (Slow query log).
2. Kiểm tra trực tiếp dưới Database (Database Level)
2.1. MySQL - Sử dụng Profiling & Explain Analyze MySQL cung cấp hai công cụ cực kỳ hữu ích để soi chi tiết từng mili giây.
Cách 1: Sử dụng Profile (Dành cho mọi phiên bản)
SET profiling = 1; -- Bật bộ đo lường
-- Chạy câu query của bạn
SELECT * FROM users WHERE email = 'admin@viblo.asia';
SHOW PROFILES; -- Xem danh sách các query đã chạy kèm thời gian
Nếu bạn muốn soi kỹ hơn câu query đó tốn thời gian cho việc gửi dữ liệu hay chờ khóa (lock):
SHOW PROFILE FOR QUERY 1; -- Thay 1 bằng Query_ID bạn thấy ở trên
Cách 2: Explain Analyze (Từ MySQL 8.0.18+) Đây là cách "xịn" nhất hiện nay, nó thực thi query và báo cáo chi tiết:
Cách 2: Explain Analyze (Từ MySQL 8.0.18+)
Đây là cách "xịn" nhất hiện nay, nó thực thi query và báo cáo chi tiết:
Kết quả sẽ có dòng: (actual time=0.453..0.612 rows=50 loops=1). Số 0.612 chính là thời gian kết thúc tính bằng ms.
2.2. PostgreSQL - EXPLAIN ANALYZE Postgres hỗ trợ đo lường rất sâu. Bạn chỉ cần thêm keyword này phía trước query:
EXPLAIN ANALYZE SELECT count(*) FROM posts WHERE published = true;
Hãy chú ý vào dòng cuối cùng:
- Planning Time: Thời gian DB lập kế hoạch (ms).
- Execution Time: Thời gian thực thi thực tế (ms).
3. Kiểm tra từ phía Application (Code Level)
Đôi khi query ở DB rất nhanh nhưng kết quả trả về app chậm do mạng hoặc do Driver.
Đối với Node.js
Bạn có thể dùng console.time() để đo nhanh:
console.time('QueryTime');
const users = await db.query('SELECT * FROM users');
console.timeEnd('QueryTime'); // Output: QueryTime: 12.453ms
Đối với Laravel (PHP)
Laravel cung cấp công cụ tuyệt vời là Query Log:
DB::enableQueryLog();
$users = User::all();
dd(DB::getQueryLog());
// Kết quả sẽ trả về mảng gồm câu SQL và cột 'time' (tính bằng ms)
4. Những "Cạm bẫy" cần tránh khi đo tốc độ
Để có con số chính xác, bạn cần lưu ý các yếu tố gây sai lệch sau:
1. Database Caching
Lần đầu bạn chạy query tốn 500ms, lần sau chỉ tốn 5ms. Đó là nhờ Query Cache. Để đo chính xác hiệu năng thực tế khi dữ liệu không có sẵn trong RAM:
Trong MySQL, hãy dùng: SELECT SQL_NO_CACHE ... (với bản cũ) hoặc xóa Buffer Pool.
Tốt nhất là chạy 5-10 lần và lấy con số trung bình.
- Network Latency
Nếu bạn kết nối từ máy cá nhân đến Server Database ở xa (ví dụ AWS RDS tại Singapore), thời gian bạn thấy bao gồm cả thời gian dữ liệu bay qua biển. Hãy đo ngay trên Server để có con số thuần túy của DB.
- Data Volume
Đừng bao giờ test tốc độ trên một bảng chỉ có 10 dòng. Hãy dùng các script tạo dữ liệu mẫu (Seeder) để bảng đạt tới ngưỡng 100,000 hoặc 1 triệu dòng. Khi đó, sự khác biệt giữa 1ms và 1000ms mới lộ rõ.
Kết luận
Việc check tốc độ query không chỉ đơn thuần là xem nó nhanh hay chậm, mà là hiểu cách Database vận hành. Hãy luôn bắt đầu bằng EXPLAIN ANALYZE để có cái nhìn toàn diện nhất.
Kinh nghiệm xương máu: Bất kỳ câu query nào chạy trên 100ms ở môi trường Production đều cần được "chăm sóc đặc biệt" bằng cách đánh Index hoặc tối ưu lại logic.
Hy vọng bài viết này giúp ích cho các bạn trong quá trình tối ưu hóa ứng dụng. Nếu có thắc mắc, hãy để lại bình luận phía dưới nhé!
All rights reserved