У мене є таблиця зі стовпчиком рядка та присудком, який перевіряє наявність рядків з певною довжиною. У SQL Server 2014 я бачу оцінку в 1 рядок незалежно від довжини, на яку я перевіряю. Це дає дуже погані плани, оскільки насправді є тисячі чи навіть мільйони рядків, і SQL Server вирішує поставити цю таблицю на зовнішній бік вкладеного циклу.
Чи є пояснення для оцінки кардинальності 1.0003 для SQL Server 2014, тоді як SQL Server 2012 оцінює 31 622 рядки? Чи є хороший спосіб вирішення?
Ось коротке відтворення питання:
-- 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
Ось більш повний сценарій, що показує додаткові тести
Я також читав довідку на оцінці кардинальності SQL Server 2014 , але там не знайшов нічого, що б прояснило ситуацію.