Eu encontrei uma pergunta semelhante e estou ciente de que para uma consulta do formulário
SELECT COUNT(1)
FROM foo f
LEFT OUTER JOIN bar b ON f.Value = b.Value AND f.Value = b.Value2
para executar sem tocar bar
, é necessário que haja um índice exclusivo nas duas colunas em questão.
E, de fato, isso funciona até agora, as tabelas sendo definidas como:
CREATE TABLE [dbo].[Foo](
[Value] [varchar](255) NOT NULL
) ON [PRIMARY]
CREATE TABLE [dbo].[Bar](
[Value] [varchar](1024) NULL,
[Value2] [varchar](1024) NULL
)
CREATE UNIQUE CLUSTERED INDEX [IX] ON [dbo].[Bar]
(
[Value] ASC,
[Value2] ASC
)
O plano de consulta não toca bar
, ótimo.
Em minha busca de por que isso não funciona na minha consulta da vida real de algum aplicativo que escrevo, reduzi a consulta lá para o seguinte teste que é simples e também tem o planejador de consulta falha em deixar as mãos fora da bar
mesa:
WITH numbers AS (
SELECT 1 AS i
UNION ALL SELECT i + 1
FROM numbers
WHERE i < 10
)
SELECT COUNT(1)
FROM numbers n
LEFT OUTER JOIN bar b ON n.i = b.Value AND n.i = b.Value2
;
Isso realmente toca a barra. Hmmm.
Alguma ideia? Por que o planejador de consulta acha que isso é diferente da outra consulta?
(Meu problema real não usa essa expressão de tabela recursiva, na verdade é exatamente como o caso de demonstração, uma junção simples em duas colunas - e não consigo entender por que não deixaria a tabela unida sozinha em um cenário de contagem.)
Suspeito que a diferença seja a conversão implícita, que pode atrapalhar. Por exemplo,
Bar
não é tocado se tiver um tipo de dados compatível: