Phân biệt SELECT * và SELECT COUNT(*) trong SQL: Khi nào lấy toàn bộ dữ liệu, khi nào chỉ đếm số lượng?
Chào anh em!
Trong quá trình làm việc với cơ sở dữ liệu quan hệ (như MySQL, PostgreSQL hay SQL Server), việc truy vấn dữ liệu là công việc diễn ra hàng ngày đối với mọi lập trình viên Backend. Trong đó, có hai câu lệnh cực kỳ quen thuộc nhưng lại thường bị dùng sai ngữ cảnh hoặc lạm dụng gây suy giảm hiệu năng hệ thống: SELECT * và SELECT COUNT(*).
Hôm nay, hãy cùng mổ xẻ xem hai câu lệnh này thực chất là gì, hoạt động ra sao và khi nào thì nên dùng cái nào nhé!
1. SELECT * là gì? (Lấy tất cả)
A. Bản chất
SELECT * (đọc là Select Star) là câu lệnh dùng để truy vấn và lấy ra toàn bộ tất cả các cột của một hoặc nhiều bảng dữ liệu.
Ví dụ:
SELECT * FROM users;
Câu lệnh này sẽ trả về mọi hàng (rows) và mọi cột (id, username, email, password, created_at,...) có trong bảng users.
B. Khi nào nên dùng và không nên dùng?
- Nên dùng: Khi bạn đang viết code kiểm tra nhanh (debugging) trên môi trường Local, hoặc khi bạn xây dựng một bảng quản trị mà cần hiển thị toàn bộ thuộc tính của bản ghi lên màn hình giao diện.
- TUYỆT ĐỐI HẠN CHẾ dùng trên Production:
- Lãng phí băng thông: Nếu bảng có những cột chứa dữ liệu nặng (như chuỗi JSON dài hoặc trường nội dung bài viết), việc bắt hệ thống trả về toàn bộ là cực kỳ tốn tài nguyên mạng.
- Làm hỏng tính độc lập của Index: Việc không chỉ định rõ tên cột khiến cơ sở dữ liệu mất cơ hội tối ưu hóa truy vấn bằng Index (Covering Index).
2. SELECT COUNT(*) là gì? (Đếm số lượng)
A. Bản chất
Trái ngược với việc lấy nội dung dữ liệu, SELECT COUNT(*) là một hàm tổng hợp (Aggregate Function) chuyên dùng để đếm tổng số lượng bản ghi thỏa mãn một điều kiện nào đó trong bảng.
Ví dụ:
SELECT COUNT(*) FROM users WHERE status = 'active';
Câu lệnh này chỉ trả về một con số duy nhất (ví dụ: 150) biểu thị tổng số lượng người dùng đang ở trạng thái hoạt động, hoàn toàn không mang theo bất kỳ dữ liệu chi tiết nào của người dùng cả.
B. Hiểu lầm kinh điển về hiệu năng: COUNT(*) vs COUNT(column_name)
Nhiều lập trình viên mới thường nghĩ rằng viết COUNT(id) hoặc COUNT(column_name) sẽ nhanh hơn COUNT(*). Đây là một quan niệm sai lầm!
Trong phần lớn các hệ quản trị cơ sở dữ liệu hiện đại (như MySQL/InnoDB), COUNT(*) được tối ưu hóa riêng để đếm tổng số hàng trong bảng một cách cực kỳ nhanh chóng mà không cần bận tâm đến việc cột nào chứa giá trị NULL.
Ngược lại, nếu bạn dùng COUNT(column_name), hệ thống sẽ phải bổ sung thêm một bước kiểm tra xem giá trị trong cột đó có bị NULL hay không rồi mới đếm, đôi khi dẫn đến hiệu năng thấp hơn hoặc trả về kết quả sai lệch nếu có dữ liệu trống.
3. Đặt lên bàn cân so sánh tóm tắt
| Tiêu chí | SELECT * | SELECT COUNT(*) |
|---|---|---|
| Mục đích chính | Trả về toàn bộ dữ liệu chi tiết của các cột. | Trả về một con số duy nhất đếm tổng số lượng bản ghi. |
| Kiểu dữ liệu trả về | Tập hợp các hàng và cột (Result Set). | Một giá trị số nguyên duy nhất (Integer). |
| Ảnh hưởng hiệu năng | Nặng, tốn bộ nhớ RAM, tốn băng thông mạng nếu bảng lớn. | Nhẹ, tối ưu cực tốt cho việc thống kê số liệu. |
| Quy tắc vàng | Chỉ dùng khi thực sự cần thiết toàn bộ thông tin. | Dùng khi làm phân trang (Pagination) hoặc thống kê báo cáo. |
Lời kết
SELECT * và SELECT COUNT(*) phục vụ hai mục đích hoàn toàn trái ngược nhau: một bên là khám phá chi tiết dữ liệu, bên còn lại là thống kê số lượng. Hiểu đúng bản chất và sử dụng chúng đúng chỗ sẽ giúp hệ thống Backend của bạn chạy mượt mà, tiết kiệm tài nguyên và hạn chế tối đa các điểm nghẽn hiệu năng!
All rights reserved