Gibt es eine Dokumentation oder Recherche zu Änderungen in SQL Server 2016 hinsichtlich der Schätzung der Kardinalität für Prädikate, die SUBSTRING () oder andere Zeichenfolgenfunktionen enthalten?
Der Grund, den ich frage, ist, dass ich eine Abfrage betrachte, deren Leistung sich im Kompatibilitätsmodus 130 verschlechtert hat, und der Grund eine Änderung in der Schätzung der Anzahl der Zeilen war, die einer WHERE-Klausel entsprechen, die einen Aufruf von SUBSTRING () enthielt. Ich habe das Problem mit einem Umschreiben der Abfrage behoben, mich jedoch gefragt, ob jemand Kenntnis von der Dokumentation zu Änderungen in diesem Bereich in SQL Server 2016 hat.
Demo-Code ist unten. Die Schätzungen liegen in diesem Testfall sehr nahe beieinander, die Genauigkeit variiert jedoch abhängig von den Daten.
Im Testfall verwendet SQL Server auf Kompatibilitätsstufe 120 anscheinend das Histogramm für die Schätzung, während SQL Server auf Kompatibilitätsstufe 130 anscheinend festgelegte 10% der Tabellenübereinstimmungen annimmt.
CREATE DATABASE MyStringTestDB;
GO
USE MyStringTestDB;
GO
DROP TABLE IF EXISTS dbo.StringTest;
CREATE TABLE dbo.StringTest ( [TheString] varchar(15) );
GO
INSERT INTO dbo.StringTest
VALUES
( 'Y5_CLV' );
INSERT INTO dbo.StringTest
VALUES
( 'Y5_EG3' );
INSERT INTO dbo.StringTest
VALUES
( 'ZY_NE' );
INSERT INTO dbo.StringTest
VALUES
( 'ZY_PQT' );
INSERT INTO dbo.StringTest
VALUES
( 'ZY_T2V' );
INSERT INTO dbo.StringTest
VALUES
( 'ZY_TT4' );
INSERT INTO dbo.StringTest
VALUES
( 'ZY_ZKK' );
INSERT INTO dbo.StringTest
VALUES
( 'ZZ_LW6' );
INSERT INTO dbo.StringTest
VALUES
( 'ZZ_QO3' );
INSERT INTO dbo.StringTest
VALUES
( 'ZZ_TZ7' );
INSERT INTO dbo.StringTest
VALUES
( 'ZZ_UZZ' );
CREATE CLUSTERED INDEX IX_Clustered ON dbo.StringTest (TheString);
/*
Uses fixed % for estimate; 1.1 rows estimated in this case.
Plan for computation:
CSelCalcFixedFilter (0.1) <----
Selectivity: 0.1
*/
ALTER DATABASE MyStringTestDB SET compatibility_level = 130;
GO
SELECT *
FROM dbo.StringTest
WHERE SUBSTRING(TheString, 1, CHARINDEX('_',TheString) - 1) = 'ZZ'
OPTION (QUERYTRACEON 2363, QUERYTRACEON 3604);
/*
Uses histogram to get estimate of 1
CSelCalcPointPredsFreqBased <----
Distinct value calculation:
CDVCPlanLeaf
0 Multi-Column Stats, 1 Single-Column Stats, 0 Guesses
Individual selectivity calculations:
(none)
Loaded histogram for column QCOL: [DBA].[dbo].[StringTest].TheString from stats with id 1
*/
ALTER DATABASE MyStringTestDB SET compatibility_level = 120;
GO
SELECT *
FROM dbo.StringTest
WHERE SUBSTRING(TheString, 1, CHARINDEX('_',TheString) - 1) = 'ZZ'
OPTION (QUERYTRACEON 2363, QUERYTRACEON 3604);
/*
-- Simpler rewrite; works fine in both compat levels and gets better estimate.
SELECT *
FROM dbo.StringTest
WHERE TheString LIKE 'ZZ[_]%'
OPTION (QUERYTRACEON 2363, QUERYTRACEON 3604);
*/
Y5_EG3
Zeichenfolgen nur Codes sind und immer in Großbuchstaben geschrieben werden, können Sie immer versuchen, eine binäre Sortierung anzugeben,Latin1_General_100_BIN2
die die Geschwindigkeit der Filtervorgänge verbessern soll. Ergänzen Sie einfachCOLLATE Latin1_General_100_BIN2
dieCREATE TABLE
Aussage, gleich nach demvarchar(15)
. Ich wäre gespannt, ob sich dies auch auf die Erstellung / Schätzung des Plans auswirkt.