Mam tabelę z kolumną ciągów i predykatem, który sprawdza wiersze o określonej długości. W SQL Server 2014 widzę szacunkową wartość 1 wiersza bez względu na sprawdzaną długość. Daje to bardzo kiepskie plany, ponieważ w rzeczywistości są tysiące, a nawet miliony wierszy, a SQL Server decyduje się umieścić tę tabelę na zewnętrznej stronie zagnieżdżonej pętli.
Czy istnieje wyjaśnienie szacunku liczności 1.0003 dla SQL Server 2014, podczas gdy SQL Server 2012 szacuje 31 622 wierszy? Czy istnieje dobre obejście?
Oto krótkie odtworzenie problemu:
-- 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
Oto bardziej kompletny skrypt pokazujący dodatkowe testy
Przeczytałem również oficjalny dokument na temat programu SQL Server 2014 Cardinality Estimator , ale nie znalazłem tam niczego, co wyjaśniłoby sytuację.
źródło