Jeg er overrasket over, at enten er hurtigt. Jeg vil foreslå at erstatte 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);
Og for det andet:
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)
)
For begge disse ønsker du to indekser:ips_fatura(ips_usuario_id)
og ips_fatura(ips_usuario_id_titular)
. Du kan tjekke forklaringen for at være sikker på, at EXISTS
bruger indekset. Hvis ikke, bruger de nyere udgivelser af MySQL indekser for 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 begge tilfælde (EXISTS
eller IN
) målet er at lave en "semi-join". Altså kun at bøde første række med en kamp frem for alle kampe. Dette er en vigtig effektivitet, fordi det tillader forespørgslen at undgå duplikeringsfjernelse.
Jeg vil spekulere i, at problemet er optimering af or
-- normalt resulterer dette i ineffektiv JOIN
algoritmer. Men måske er MySQL smart i dit første tilfælde. Men tilføjelsen af IS NULL
til det ydre bord smider det af.