Eu tenho uma tabela com uma coluna de seqüência de caracteres e um predicado que verifica se há linhas com um determinado comprimento. No SQL Server 2014, estou vendo uma estimativa de 1 linha, independentemente do comprimento que estou verificando. Isso está produzindo planos muito ruins, porque na verdade existem milhares ou até milhões de linhas e o SQL Server está optando por colocar essa tabela no lado externo de um loop aninhado.
Existe uma explicação para a estimativa de cardinalidade de 1.0003 para o SQL Server 2014 enquanto o SQL Server 2012 estima 31.622 linhas? Existe uma boa solução alternativa?
Aqui está uma breve reprodução do problema:
-- Create a table with 1MM rows of dummy data
CREATE TABLE #customers (cust_nbr VARCHAR(10) NOT NULL)
GO
INSERT INTO #customers WITH (TABLOCK) (cust_nbr)
SELECT TOP 1000000
CONVERT(VARCHAR(10),
ROW_NUMBER() OVER (ORDER BY (SELECT NULL))) AS cust_nbr
FROM master..spt_values v1
CROSS JOIN master..spt_values v2
GO
-- Looking for string of a certain length.
-- While both CEs yield fairly poor estimates, the 2012 CE is much
-- more conservative (higher estimate) and therefore much more likely
-- to yield an okay plan rather than a drastically understimated loop join.
-- 2012: 31,622 rows estimated, 900K rows actual
-- 2014: 1 row estimated, 900K rows actual
SELECT COUNT(*)
FROM #customers
WHERE LEN(cust_nbr) = 6
OPTION (QUERYTRACEON 9481) -- Optionally, use 2012 CE
GO
Aqui está um script mais completo mostrando testes adicionais
Também li o whitepaper no Estimador de cardinalidade do SQL Server 2014 , mas não encontrei nada lá que esclarecesse a situação.