Temos algum código que passa por um gerador SQL para produzir cláusulas IN parametrizadas no formato WHERE id IN (?, ?, ?, ...) AND ...
.
Se a lista estiver vazia, o gerador não poderá emitir, IN ()
pois é um SQL inválido. Em vez disso, trata-se WHERE id IN (SELECT NULL WHERE FALSE)
de fornecer a mesma semântica.
Eu esperaria que o MYSQL pudesse reduzir isso para WHERE FALSE
. Curiosamente, porém, ele não consegue fazer isso e produz uma varredura completa da tabela!
Consulta de exemplo (mytable é uma tabela de teste simples que criei com ID de 50 mil linhas como PK)
select *
from mytable
where id in (select null where false);
Curiosamente, se eu substituir a subconsulta por uma que atinja uma tabela real, obtenho um plano muito melhor:
Consulta:
select *
from mytable
where id in (select null from information_schema.tables where false);
Minha pergunta é: há alguma razão pela qual faz sentido para o MySQL se comportar dessa maneira (por exemplo, alguma semântica específica da primeira consulta?) Este é um bug conhecido?
ATUALIZAÇÃO : Eu registrei isso no MySQL e eles reconheceram a estranheza e aceitaram como uma solicitação de recurso .
O "gerador" deve remover a cláusula do arquivo
WHERE
. Se necessário, remova oWHERE
. Não deveria colocar alguma coisa potencialmente ineficiente em seu lugar.Se você não tem controle sobre o “gerador”, minhas condolências.
O MySQL sempre foi "enxuto e mesquinho". Ou seja, ele implementa o suficiente para sobreviver, mas não se concentra em casos extremos ou na velocidade, apenas na correção.
Duas décadas atrás (mais ou menos), o MySQL implementou estes recursos:
ALTER TABLE
através de uma simples "cópia". Há alguns anos, eles conseguiram otimizar a velocidade da maioria dos casos.PARTITION
- mas permanece praticamente inútil.LEFT JOIN
que não é usado pode ser ignorado. O MySQL continua a realizar a junção, enquanto o MariaDB adicionou uma otimização para ignorar a cláusula. (Esses podem facilmente entrar furtivamente em um arquivoVIEW
.)IN ( SELECT... )
foi implementado pela primeira vez de uma forma terrivelmente ineficiente. Muito mais tarde, alguns casos foram otimizados. Sugiro que seu exemplo não foi capturado.