Estou surpreso que qualquer um seja rápido. Sugiro substituí-los por
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);
E para o segundo:
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)
)
Para ambos, você quer dois índices:
ips_fatura(ips_usuario_id)
e ips_fatura(ips_usuario_id_titular)
. Você pode verificar a explicação para ter certeza de que EXISTS
está usando o índice. Caso contrário, as versões mais recentes do MySQL usam índices para 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);
Em ambos os casos (
EXISTS
ou IN
) o objetivo é fazer uma "semi-junção". Ou seja, para corrigir apenas a primeira linha com uma correspondência em vez de todas as correspondências. Essa é uma eficiência importante, pois permite que a consulta evite a remoção de duplicações. Eu especularia que o problema é a otimização do
or
-- geralmente isso resulta em JOIN
ineficiente algoritmos. No entanto, talvez o MySQL seja inteligente em seu primeiro caso. Mas a adição do IS NULL
para a mesa externa joga fora.