tenho uma tabela:
CREATE TABLE IF NOT EXISTS blacklist
(
id NUMERIC(20, 0) NOT NULL DEFAULT NEXTVAL('blacklist_sequence') PRIMARY KEY,
device_id VARCHAR(512) DEFAULT NULL NULL,
phone_number VARCHAR(512) DEFAULT NULL NULL
);
CREATE INDEX index_phone ON blacklist (phone_number);
CREATE INDEX index_device ON blacklist (device_id);
e quero usar essa lista negra para ver se um cliente com device_id
ou a phone_number
está dentro dela. Então minha consulta é:
SELECT CASE WHEN COUNT(*) > 0 THEN TRUE ELSE FALSE END
FROM blacklist b
JOIN
(SELECT id
FROM blacklist
WHERE device_id = :deviceId
UNION
SELECT id
FROM blacklist
WHERE phoneNumber = :phoneNumber) filtered_table ON b.id = filtered_table.id
Basicamente, dividindo a OR
condição em subconsultas UNION
para fazer uso de índices, mas descobri que temos tantas linhas de lista negra com phone_number
linhas preenchidas, enquanto menos com device_id
.
Então, estou procurando uma maneira de paralelizar ainda mais para que quando uma device_id
correspondência for encontrada, eu não precise ficar procurando coletar e UNION
os resultados da phone_number
condição (porque nesse ponto eu já sei que o meu SELECT
retornará TRUE
) para venha com um maior COUNT
, já que estou interessado apenas se a linha existe ou não.
Como faço para reescrever essa consulta para alcançá-la? Embora eu esteja procurando principalmente uma solução Postgres, estou interessado em descobrir o que outros bancos de dados podem fazer.
Você escreveu a consulta para que ela encontre todas as linhas correspondentes e, em seguida, pesquise a linha novamente para contá-la. Você só quer um teste de existência usando um
exists
predicado, isso retornará assim que uma correspondência for encontrada.Veja este dbfiddle para uma demonstração https://dbfiddle.uk/Awu5NUrI você pode ver que a segunda ramificação do
union all
não é executada porque encontrou com sucesso uma correspondência usando uma verificação rápida de índice na primeira ramificação.Você não precisa de paralelismo, você só precisa fazer menos trabalho.