Tôi ngạc nhiên rằng một trong hai là nhanh. Tôi khuyên bạn nên thay thế chúng bằng exists
:
SELECT COUNT(*)
FROM ips_usuario u
WHERE EXISTS (SELECT 1 FROM ips_fatura f WHERE u.id = f.ips_usuario_id) OR
EXISTS (SELECT 1 FROM ips_fatura f WHERE u.ips_usuario_id_titular = f.ips_usuario_id);
Và thứ hai:
SELECT COUNT(*)
FROM ips_usuario u
WHERE EXISTS (SELECT 1 FROM ips_fatura f WHERE u.id = f.ips_usuario_id) OR
(u.ips_usuario_id_titular IS NOT NULL AND
EXISTS (SELECT 1 FROM ips_fatura f WHERE u.ips_usuario_id_titular = f.ips_usuario_id)
)
Đối với cả hai điều này, bạn cần có hai chỉ mục:ips_fatura(ips_usuario_id)
và ips_fatura(ips_usuario_id_titular)
. Bạn có thể kiểm tra phần giải thích để chắc chắn rằng EXISTS
đang sử dụng chỉ mục. Nếu không, các bản phát hành mới hơn của MySQL sử dụng chỉ mục cho IN
:
SELECT COUNT(*)
FROM ips_usuario u
WHERE u.id IN (SELECT f.ips_usuario_id FROM ips_fatura f) OR
u.ips_usuario_id_titular IN (SELECT f.ips_usuario_id FROM ips_fatura f);
Trong cả hai trường hợp (EXISTS
hoặc IN
) mục tiêu là thực hiện "bán tham gia". Có nghĩa là, chỉ phạt hàng đầu tiên với một trận đấu chứ không phải tất cả các trận đấu. Đây là một hiệu quả quan trọng vì nó cho phép truy vấn tránh được việc xóa trùng lặp.
Tôi suy đoán rằng vấn đề là sự tối ưu hóa của or
- thường thì điều này dẫn đến JOIN
không hiệu quả các thuật toán. Tuy nhiên, có lẽ MySQL là thông minh trong trường hợp đầu tiên của bạn. Nhưng việc bổ sung IS NULL
ra bàn bên ngoài ném nó đi.