Jag är förvånad över att båda är snabba. Jag skulle föreslå att du ersätter dem med 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);
Och för det andra:
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)
)
För båda dessa vill du ha två index:ips_fatura(ips_usuario_id)
och ips_fatura(ips_usuario_id_titular)
. Du kan kontrollera förklara för att vara säker på att EXISTS
använder indexet. Om inte, använder de nyare versionerna av MySQL index för 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);
I båda fallen (EXISTS
eller IN
) målet är att göra en "semi-join". Det vill säga att bara böta första raden med en match snarare än alla matcher. Detta är en viktig effektivitet, eftersom det tillåter frågan att undvika dubbelarbete borttagning.
Jag skulle spekulera i att problemet är optimeringen av or
-- vanligtvis resulterar detta i ineffektiva JOIN
algoritmer. Men kanske MySQL är smart i ditt första fall. Men tillägget av IS NULL
till det yttre bordet kastar det av sig.