Dziwię się, że albo jest szybki. Sugerowałbym zastąpienie ich przez 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);
A po drugie:
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)
)
Dla obu tych potrzebujesz dwóch indeksów:ips_fatura(ips_usuario_id)
i ips_fatura(ips_usuario_id_titular)
. Możesz sprawdzić wyjaśnienie, aby upewnić się, że EXISTS
używa indeksu. Jeśli nie, nowsze wersje MySQL używają indeksów dla 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);
W obu przypadkach (EXISTS
lub IN
) celem jest wykonanie „częściowego połączenia”. Oznacza to, że wystarczy dopasować tylko pierwszy wiersz, a nie wszystkie dopasowania. Jest to ważna wydajność, ponieważ pozwala uniknąć usunięcia duplikatów zapytania.
Spekulowałbym, że problemem jest optymalizacja or
-- zwykle skutkuje to nieefektywnym JOIN
algorytmy. Jednak być może MySQL jest sprytny w twoim pierwszym przypadku. Ale dodanie IS NULL
do zewnętrznego stołu zrzuca go.