So sánh WHERE IN() và OR trong MySQL
Cả IN() và OR đều dùng để lọc bản ghi khớp với một trong nhiều giá trị, nhưng khác nhau về hiệu suất và khả năng sử dụng index.
Ví dụ minh họa
Tạo bảng DemoTable711:
mysql> CREATE TABLE DemoTable711 (
Id INT,
Name VARCHAR(100)
);
Query OK, 0 rows affected (0.92 sec)
Chèn dữ liệu:
mysql> INSERT INTO DemoTable711 VALUES(100, 'Chris'); Query OK, 1 row affected (0.15 sec) mysql> INSERT INTO DemoTable711 VALUES(101, 'Robert'); Query OK, 1 row affected (0.14 sec) mysql> INSERT INTO DemoTable718 VALUES(102, 'Carol'); Query OK, 1 row affected (0.35 sec) mysql> INSERT INTO DemoTable711 VALUES(103, 'Mike'); Query OK, 1 row affected (0.17 sec) mysql> INSERT INTO DemoTable711 VALUES(104, 'Sam'); Query OK, 1 row affected (0.15 sec)
Xem dữ liệu:
mysql> SELECT * FROM DemoTable711;
+------+--------+ | Id | Name | +------+--------+ | 100 | Chris | | 101 | Robert | | 102 | Carol | | 103 | Mike | | 104 | Sam | +------+--------+ 5 rows in set (0.00 sec)
1. Sử dụng IN()
mysql> SELECT * FROM DemoTable711 WHERE Id IN(101, 103, 104);
+------+--------+ | Id | Name | +------+--------+ | 101 | Robert | | 103 | Mike | | 104 | Sam | +------+--------+ 3 rows in set (0.03 sec)
2. Sử dụng OR
mysql> SELECT * FROM DemoTable711 WHERE Id=101 OR Id=103 OR Id=104;
+------+--------+ | Id | Name | +------+--------+ | 101 | Robert | | 103 | Mike | | 104 | Sam | +------+--------+ 3 rows in set (0.00 sec)
So sánh chi tiết
| Tiêu chí | IN() | OR |
|---|---|---|
| Sử dụng Index | ✅ Có (Range optimization) | ❌ Thường không (trừ MySQL 8.0+ có Range Optimizer) |
| Độ đọc code | ✅ Ngắn gọn, dễ đọc | ❌ Dài, lặp lại tên cột |
| Dễ bảo trì | ✅ Thêm/xóa giá trị dễ | ❌ Phải sửa nhiều chỗ |
| Hiệu suất danh sách lớn | ✅ Tốt (binary search trong danh sách) | ❌ Kém (linear evaluation) |
| Subquery | ✅ Hỗ trợ IN (SELECT ...) | ❌ Không trực tiếp |
| NULL handling | ⚠️ Cẩn thận (NULL trong danh sách) | ✅ Xử lý rõ ràng hơn |
Khuyến nghị
- Ưu tiên IN() cho danh sách giá trị tĩnh hoặc subquery
- Dùng
ORchỉ khi: điều kiện phức tạp, khác cột, hoặc logic không gọn trong IN() - Với danh sách rất lớn (>1000 giá trị): cân nhắc
JOINvới bảng tạm hoặcEXISTS - Luôn
EXPLAINđể kiểm tra execution plan thực tế
Ví dụ IN() với subquery
SELECT * FROM orders WHERE customer_id IN (SELECT id FROM customers WHERE country = 'VN');