sql >> Database teknologi >  >> RDS >> Database

Spor Flag 2389 og den nye Cardinality Estimator

Et af SQL Server-sporingsflag, der har eksisteret i et stykke tid, er 2389.  Det diskuteres ofte med 2390, men jeg vil bare fokusere på 2389 for dette indlæg. Sporingsflaget blev introduceret i SQL Server 2005 SP1, som blev udgivet den 18. april 2006 (ifølge http://sqlserverbuilds.blogspot.co.uk/), så det har eksisteret i over 10 år. Sporingsflag ændrer motorens adfærd, og 2389 tillader optimeringsværktøjet at identificere statistikker, der er stigende og mærke dem som sådan (ofte kaldet "det stigende nøgleproblem"). Når dette sker, vil statistikken blive opdateret automatisk ved forespørgsels kompilering, hvilket betyder, at optimizeren har information om den højeste værdi i tabellen (sammenlignet med når sporingsflaget ikke bruges).

Jeg havde for nylig en diskussion med en klient om brugen af ​​dette sporingsflag, og det opstod på grund af denne type scenarie:

  • Du har en stor tabel, der har en INT som den primære nøgle, og den er klynget.
  • Du har et ikke-klynget indeks, der fører på en DATETIME-kolonne.
  • Tabellen har omkring 20 millioner rækker i den, og alt fra 5.000 til 100.000 rækker tilføjes hver dag.
  • Statistikken opdateres hver nat som en del af din vedligeholdelsesopgave.
  • Automatisk opdateringsstatistikker er aktiveret for databasen, men selvom der tilføjes 100.000 rækker til tabellen, er det langt mindre end de 4 millioner rækker (20 %), der er nødvendige for at starte en automatisk opdatering.
  • Når brugere forespørger i tabellen ved hjælp af datoen i prædikatet, kan forespørgselsydeevnen være stor, eller den kan være forfærdelig.

Det sidste punkt får det næsten til at lyde som et problem med parameterfølsomhed, men det er det ikke. I dette tilfælde er det et statistikproblem. Mit forslag til klienten var at bruge TF 2389 eller at opdatere statistik oftere i løbet af dagen (f.eks. via et agentjob). Så tænkte jeg, at jeg ville lave nogle test, da klienten kørte SQL Server 2014.  Det var her, tingene blev interessante.

Opsætningen

Vi vil oprette den førnævnte tabel til test i RTM-builden af ​​SQL Server 2016 i WideWorldImporters-databasen, og jeg vil først indstille kompatibilitetstilstanden til 110:

BRUG [master];GORESTORE DATABASE [WideWorldImporters]FRA  DISK =N'C:\Backups\WideWorldImporters-Full.bak'WITH  FILE =1,FLYT N'WWI_Primary' TIL N'C:\Databases\WideWorldImporters\WideWorldImporters\ .mdf',FLYT N'WWI_UserData' TIL N'C:\Databases\WideWorldImporters\WideWorldImporters_UserData.ndf',FLYT N'WWI_Log' TIL N'C:\Databases\WideWorldImporters\WideWorldImporters\WideWorldImporters\WideWorldImWorldIWI_MORldyWorld'1_MORldyWorld'1 N'C:\Databases\WideWorldImporters\WideWorldImporters_InMemory_Data_1',NOUNLOAD, REPLACE, STATS =5;GO ALTER DATABASE [WideWorldImporters] SET COMPATIBILITY_LEVEL =110;GO USE [WideWorldImporters]orldGO USE [WideWorldImporters] ] [int] NOT NULL,[CustomerID] [int] NOT NULL,[SælgerPersonID] [int] NOT NULL,[PickedByPersonID] [int] NULL,[ContactPersonID] [int] NOT NULL,[BackorderOrderID] [int] NULL, [OrderDate] [date] NOT NULL,[ExpectedDeliveryDate] [date] NOT NULL,[CustomerPurchaseOrderNumber] [nvarchar](20) NULL,[IsUndersupplyBackordered] [bit] NOT NULL,[Kommentarer] [nvarchar ](max) NULL,[DeliveryInstructions] [nvarchar](max) NULL,[InternalComments] [nvarchar](max) NULL,[PickingCompletedWhen] [datetime2](7) NULL,[LastEditedBy] [int] NOT NULL,[LastEditedWhen] ] [datetime2](7) IKKE NULL,BEGRÆNSNING [PK_Sales_BigOrders] PRIMÆR NØGLE KLUSTERET([Ordre-ID] ASC)MED (PAD_INDEX =FRA, STATISTICS_NORECOMPUTE =FRA, IGNORE_DUP_KEY =FRA, TILLADES_ROW_LOCKON, PÅ)] PÅ [USERDATA] TEXTIMAGE_ON [USERDATA];

Dernæst skal vi indlæse omkring 24 millioner rækker i BigOrders og oprette et ikke-klynget indeks på OrderDate.

INDSTIL ANTAL TIL; DECLARE @Loops SMALLINT =0, @IDIncrement INT =75000; WHILE @Loops <325 -- juster dette for at øge eller mindske antallet af tilføjede rækker.BEGININDSÆT [Salg].[BigOrders]( [OrdreID],[Kunde-ID],[SælgerPersonID],[PickedByPersonID],[Kontaktperson-ID],[BackorderOrderID], [OrderDate],[ExpectedDeliveryDate],[CustomerPurchaseOrderNumber],[IsUndersupplyBackordered],[Comments],[DeliveryInstructions],[InternalComments],[PickingCompletedWhen],[LastEditedBy],[LastEditedWhen],+SELECT[OrderIncrementID])@CIDustom-ID ],[SælgerPersonID],[PickedByPersonID],[ContactPersonID],[BackorderOrderID],[OrderDate],[ForventetDeliveryDate],[CustomerPurchaseOrderNumber],[IsUndersupplyBackordered],[Comments],[Leveringsinstruktioner],P [LastEditedBy],[LastEditedWhen]FRA [Salg].[Ordrer]; KONTROLPUNKT; SET @Loops =@Loops + 1;SET @IDIncrement =@IDIncrement + 75000;SLUT OPRET IKKE-KLUSTERET INDEKS [NCI_BigOrders_OrderDate]ON [Salg].[BigOrders] ([OrderDate], CustomerID);

Hvis vi tjekker histogrammet for det ikke-klyngede indeks, ser vi den højeste dato er 2016-05-31:

DBCC SHOW_STATISTICS ('Sales.BigOrders',[NCI_BigOrders_OrderDate]);


Statistik for NCI på ordredato

Hvis vi forespørger efter en dato ud over det, bemærk det anslåede antal rækker:

SELECT CustomerID, OrderID, SalespersonPersonIDFROM [Sales].[BigOrders]WHERE [OrderDate] ='2016-06-01';


Planlæg, når du forespørger efter en dato ud over det, der er i histogrammet em>

Det er 1, fordi værdien er uden for histogrammet. Og i dette tilfælde er det ok, for der er ingen rækker i tabellen efter den 31. maj 2016. Men lad os tilføje nogle og derefter køre den samme forespørgsel igen:

INDSÆT [Salg].[Store ordrer]( [Ordre-ID],[Kunde-ID],[SælgerPerson-ID],[PickedByPersonID],[Kontaktperson-ID],[Resterordre-ID],[Ordredato],[Forventet leveringsdato],[KundeKøb[Ordrebestillingsnummer],[Kundekøbsordrenummer], ],[Kommentarer],[Leveringsvejledning],[InternalComments],[PickingCompletedWhen],[LastEditedBy],[LastEditedWhen])SELECT[OrderID] + 25000000,[CustomerID],[SælgerPersonID],[PickedByPersonID],[KontaktPersonID],[Kont. BackorderOrderID],'2016-06-01',[ExpectedDeliveryDate],[CustomerPurchaseOrderNumber],[IsUndersupplyBackordered],[Comments],[DeliveryInstructions],[InternalComments],[PickingCompletedWhen],[WhenLastEditedBy],[WhenLastEditedE] .[Ordre];GO SELECT CustomerID, OrderID, SalespersonPersonIDFROM [Sales].[BigOrders]WHERE [OrderDate] ='2016-06-01';


Planlæg efter tilføjelse af rækker efter den 31. maj

Det anslåede antal rækker er stadig 1. Men det er her, tingene bliver interessante. Lad os ændre kompatibilitetstilstanden til 130, så vi bruger den nye Cardinality Estimator og se, hvad der sker.

BRUG [master];GO ALTER DATABASE [WideWorldImporters] SET COMPATIBILITY_LEVEL =130GO USE [WideWorldImporters];GO SELECT CustomerID, OrderID, SalespersonPersonIDFROM [Sales].[BigOrders]WHERE [OrderDate]-0'01'; 


Planlæg efter tilføjelse af rækker for 1. juni ved hjælp af det nye CE

Vores planform er den samme, men nu er vores estimat 4.898 rækker. Det nye CE behandler værdier uden for historien anderledes end det gamle CE. Så … har vi overhovedet brug for sporflag 2389?

Testen – Del I

Til den første test vil vi forblive i kompatibilitetstilstand 110 og køre igennem, hvad vi ville se med 2389.  Når du bruger dette sporingsflag, kan du enten aktivere det som en startparameter i SQL Server-tjenesten, eller du kan bruge DBCC TRACEON for at aktivere det i hele instansen. Forstå, at hvis du bruger DBCC TRACEON til at aktivere sporingsflaget i dit produktionsmiljø, vil sporingsflaget ikke være i kraft, når forekomsten genstarter.

Med sporingsflaget aktiveret, skal en statistik opdateres tre (3) gange, før optimeringsværktøjet vil mærke det som stigende. Vi gennemtvinger fire opdateringer for god ordens skyld og tilføjer flere rækker mellem hver opdatering.

USE [master];GO ALTER DATABASE [WideWorldImporters] SET COMPATIBILITY_LEVEL =110;GO DBCC TRACEON (2389, -1);GO USE [WideWorldImporters];GO UPDATE STATISTICS [Salg].[BigOrderBige] [NCI_OrderBige]; INDSÆT [Salg].[BigOrders]( [Ordre-ID],[Kunde-ID],[SælgerPerson-ID],[PickedByPersonID],[Kontaktperson-ID],[Resterordre-ID],[Ordredato],[Forventet leveringsdato],[KundeKøbsordrenumre],IBordUd. Kommentarer],[Leveringsinstruktioner],[InternalComments],[PickingCompletedWhen],[LastEditedBy],[LastEditedWhen])SELECT[OrderID] + 25100000,[CustomerID],[SælgerPersonID],[PickedByPersonID],[Order-ID],[Order-ID],[KontaktBacker-ID] '2016-06-02',[ExpectedDeliveryDate],[CustomerPurchaseOrderNumber],[IsUndersupplyBackordered],[Comments],[DeliveryInstructions],[InternalComments],[PickingCompletedWhen],[LastEditedBy],[Saen]FROM [LastEditedBy],[Saen]FROM [LastEditedWhen] ];GO UPDATE STATISTICS [Salg].[BigOrders] [NCI_BigOrders_OrderDate];GO INSERT [Salg].[BigOrders]( [OrderID],[CustomerID] ],[SælgerPersonID],[PickedByPersonID],[ContactPersonID],[Resterordre-ID],[Ordredato],[Forventet leveringsdato],[Kundekøbsordrenummer],[IsUndersupplyBackordered],[Kommentarer],[Leveringsinstruktioner],P [LastEditedBy][LastEditedWhen])SELECT[OrderID] + 25200000,[CustomerID],[SælgerPersonID],[PickedByPersonID],[ContactPersonID],[BackorderOrderID],'2016-06-03'],DeliveryNChat],DeliverNr. [IsUndersupplyBackordered],[Comments],[DeliveryInstructions],[InternalComments],[PickingCompletedWhen],[LastEditedBy],[LastEditedWhen]FRA [Salg].[Ordrer];GO OPDATERING STATISTIK [Salg].[BigOrders] [NCI_BigOrders]; GÅ INDSÆT [Salg].[Store ordrer]( [Ordre-ID],[Kunde-ID],[SælgerPerson-ID],[PickedByPersonID],[Kontaktperson-ID],[Resterordre-ID],[Ordredato],[Forventet leveringsdato],[KundeKøb[Ordrenummer],Ibestil. [Kommentarer],[Leveringsinstruktioner],[Interne kommentarer],[PickingCompletedWhen],[LastEditedBy] ,[LastEditedWhen])SELECT[OrderID] + 25300000,[CustomerID],[SælgerPersonID],[PickedByPersonID],[ContactPersonID],[BackorderOrderID],'2016-06-04',[ExpectedDeliveryOrderPursUnderUsUnderUserPerUs[ForventetLeveringsOrdreDato] ],[Comments],[DeliveryInstructions],[InternalComments],[PickingCompletedWhen],[LastEditedBy],[LastEditedWhen]FRA [Salg].[Ordre];GO OPDATERING STATISTIK [Salg].[BigOrders] [NCI_BigOrders_OrderDate]; 

Hvis vi tjekker statistik igen og bruger sporingsflaget 2388 til at vise yderligere information, ser vi, at statistikken nu er markeret som Stigende:

DBCC TRACEON (2388);GO DBCC SHOW_STATISTICS ('Sales.BigOrders',[NCI_BigOrders_OrderDate]);


NCI på ordredato markeret som ASC

Hvis vi spørger efter en fremtidig dato, når statistikken er fuldt opdateret, ser vi, at den stadig anslår 1 række:

SELECT CustomerID, OrderID, SalespersonPersonIDFROM [Sales].[BigOrders]WHERE [OrderDate] ='2016-06-05';


Plan efter TF 2389 aktiveret, men ingen rækker ud over histogrammet

Nu tilføjer vi rækker til 5. juni og kører den samme forespørgsel igen:

INDSÆT [Salg].[Store ordrer]( [Ordre-ID],[Kunde-ID],[SælgerPerson-ID],[PickedByPersonID],[Kontaktperson-ID],[Resterordre-ID],[Ordredato],[Forventet leveringsdato],[KundeKøb[Ordrebestillingsnummer],[Kundekøbsordrenummer], ],[Kommentarer],[Leveringsinstruktioner],[InternalComments],[PickingCompletedWhen],[LastEditedBy],[LastEditedWhen])SELECT[OrderID] + 25400000,[KundeID],[SælgerPersonID],[PickedByPersonID],[KontaktPersonID],[Kont. BackorderOrderID],'2016-06-05',[ExpectedDeliveryDate],[CustomerPurchaseOrderNumber],[IsUndersupplyBackordered],[Kommentarer],[Leveringsinstruktioner],[InternalComments],[PickingCompletedWhen],[WhenLastEditedBy] .[Ordrer];GO SELECT CustomerID, OrderID, SalespersonPersonIDFROM [Sales].[BigOrders]WHERE [OrderDate] ='2016-06-05';


Plan efter TF 2389 aktiveret, 70K+ rækker tilføjet ud over histogram em>

Vores estimat er ikke længere 1, det er 22.595. Lad os nu bare for sjov deaktivere sporingsflaget og se, hvad estimatet er (jeg vil rydde procedurecachen, da deaktivering af sporingsflaget ikke vil påvirke, hvad der i øjeblikket er i cachen).

DBCC TRACEOFF (2389, -1);GO DBCC FREEPROCCACHE;GO SELECT CustomerID, OrderID, SalespersonPersonIDFROM [Sales].[BigOrders]WHERE [OrderDate] ='2016-06-05';


Plan efter TF 2389 er *deaktiveret*, 70K+ rækker tilføjet ud over histogram

Denne gang får jeg et estimat på 1 række igen. Selvom statistikken er mærket som stigende, hvis sporingsflag 2389 ikke er aktiveret, estimerer den kun 1 række, når du forespørger efter en værdi uden for histogrammet.

Vi har demonstreret, at sporflag 2389 gør, hvad vi forventer - hvad det altid har gjort - når vi bruger den gamle Cardinality Estimator. Lad os nu se, hvad der sker med den nye.

Testen – Del II

For at være grundig vil jeg nulstille alt. Jeg vil oprette databasen igen, indstille kompatibilitetstilstanden til 130, indlæse dataene til at begynde med, derefter aktivere sporingsflag 2389 og indlæse tre sæt data med statistikopdateringer imellem.

BRUG [master]; GÅ TIL GENDAN DATABASE [WideWorldImporters]FRA  DISK =N'C:\Backups\WideWorldImporters-Full.bak'WITH  FILE =1,FLYT N'WWI_Primary' TIL N'C:\Databases\WideWorldIm WideWorldImporters.mdf',FLYT N'WWI_UserData' TIL N'C:\Databases\WideWorldImporters\WideWorldImporters_UserData.ndf',FLYT N'WWI_Log' TIL N'C:\Databases\WideWorldImporters\WideWorldImporters\WorldImporters',FLYT N'WWI_Log' TIL N'C:\Databases\WideWorldImporters\WideWorldImporters\WorldImporters\WorldImWorldImWorldImOVE'1 TO N'C:\Databases\WideWorldImporters\WideWorldImporters_InMemory_Data_1',NOUNLOAD, REPLACE, STATS =5;GO USE [master];GO ALTER DATABASE [WideWorldImporters] SET COMPATIBILITY_LEVELGO US 13IGODES [WideWorldImporters]; .[BigOrders]([OrdreID] [int] IKKE NULL,[Kunde-id] [int] IKKE NULL,[SælgerPerson-ID] [int] IKKE NULL,[PickedByPersonID] [int] NULL,[Kontaktperson-ID] [int] IKKE NULL,[ BackorderOrderID] [int] NULL,[OrderDate] [date] NOT NULL,[ExpectedDeliveryDate] [date] NOT NULL,[CustomerPurchaseOrderNumber] [nvarchar](20) NULL,[IsUndersupplyBackordered] [bit] NOT NULL,[Code mments] [nvarchar](max) NULL,[DeliveryInstructions] [nvarchar](max) NULL,[InternalComments] [nvarchar](max) NULL,[PickingCompletedWhen] [datetime2](7) NULL,[LastEditedBy] [int] NOT NULL,[LastEditedWhen] [datetime2](7) NOT NULL,CONSTRAINT [PK_Sales_BigOrders] PRIMÆR NØGLE KLUNDET([Ordre-ID] ASC)MED (PAD_INDEX =FRA, STATISTICS_NORECOMPUTE =FRA, IGNORE_FRA_FRA_TIL, _ALLE SLÅ PÅ =SLÅ PÅ, _ALLT SLÅPÅ _ [BRUGERDATA]) PÅ [BRUGERDATA] TEXTIMAGE_ON [BRUGERDATA]; GÅ INDSTIL INGEN TÆLLING TIL; DECLARE @Loops SMALLINT =0;DECLARE @IDIncrement INT =75000; WHILE @Loops <325 -- juster dette for at øge eller mindske antallet af tilføjede rækker.BEGININDSÆT [Salg].[BigOrders]( [OrdreID],[Kunde-ID],[SælgerPersonID],[PickedByPersonID],[Kontaktperson-ID],[BackorderOrderID], [OrderDate],[ExpectedDeliveryDate],[CustomerPurchaseOrderNumber],[IsUndersupplyBackordered],[Comments],[DeliveryInstructions],[InternalComments],[PickingCompletedWhen],[LastEditedBy],[LastEditedWhen],+SELECT[OrderIncrementID])@CIDustom-ID ],[SælgerPersonID],[PickedByPersonID],[ContactPersonID],[Resterordre-ID],[Ordredato],[Forventet leveringsdato],[Kundekøbsordrenummer],[IsUndersupplyBackordered],[Kommentarer],[Leveringsinstruktioner],P [LastEditedBy],[LastEditedWhen]FRA [Salg].[Ordrer]; KONTROLPUNKT; SET @Loops =@Loops + 1;SET @IDIncrement =@IDIncrement + 75000;SLUT OPRET IKKE-KLUSTERET INDEX [NCI_BigOrders_OrderDate]ON [Salg].[BigOrders] ([OrderDate], CustomerID);GO INSERT [Salg].[BigOrders] ( [OrderID],[Kunde-ID],[SælgerPerson-ID],[PickedByPersonID],[Kontaktperson-ID],[Resterordre-ID],[Ordredato],[Forventet leveringsdato],[Kundekøbsordrenummer],[IsUndersupplyBackordered],[Leveret],[ InternalComments],[PickingCompletedWhen],[LastEditedBy],[LastEditedWhen])SELECT[OrderID] + 25000000,[CustomerID],[SælgerPersonID],[PickedByPersonID],[ContactPersonID],[BackorderOrder16',02-016',',' [ExpectedDeliveryDate],[CustomerPurchaseOrderNumber],[IsUndersupplyBackordered],[Comments],[DeliveryInstructions],[InternalComments],[PickingCompletedWhen],[LastEditedBy],[LastEditedWhen]FROM [Salg].[Ordrer].[Ordrer] -1);GO UPDATE STATISTICS [Salg].[BigOrders] [NCI_BigOrders_OrderDate];GO INSERT [Salg].[BigOrders]( [OrderID],[CustomerID],[Sælger PersonID],[PickedByPersonID],[ContactPersonID],[BackorderOrderID],[OrderDate],[ExpectedDeliveryDate],[CustomerPurchaseOrderNumber],[IsUndersupplyBackordered],[Kommentarer],[Leveringsinstruktioner],[WhenditEditB],[InternickedB] ,[LastEditedWhen])SELECT[OrderID] + 25100000,[CustomerID],[SælgerPersonID],[PickedByPersonID],[ContactPersonID],[BackorderOrderID],'2016-06-02',[ExpectedDeliveryOrderUsI ],[Kommentarer],[Leveringsinstruktioner],[InternalComments],[PickingCompletedWhen],[LastEditedBy],[LastEditedWhen]FRA [Salg].[Ordrer];GÅ OPDATERET STATISTIK [Salg].[BigOrders] [NCI_BigOrders_OrderDate];GO INSERT. [Salg].[BigOrders]( [OrderID],[KundeID],[SælgerPersonID],[PickedByPersonID],[ContactPersonID],[BackorderOrderID],[OrderDate],[Forventet Leveringsdato],[KundePurchaseOrderNumbers],[IsUBackUnders] ],[Leveringsinstruktioner],[InternalComments],[PickingCompletedWhen],[LastEditedBy],[LastEditedW hen])SELECT[Ordre-ID] + 25200000,[Kunde-ID],[SælgerPerson-ID],[PickedByPersonID],[Kontaktperson-ID],[Backorder-ID],'2016-06-03',[Forventet Leveringsdato],[KundeKøb],IordreKøb[KundeKøb] [Kommentarer],[Leveringsinstruktioner],[Interne kommentarer],[PickingCompletedWhen],[LastEditedBy],[LastEditedWhen]FRA [Salg].[Ordrer];GO OPDATERING STATISTIK [Salg].[BigOrders] [NCI_BigOrders_OrderDate];GO INSERT [Sales] ].[BigOrders]( [Ordre-ID],[Kunde-id],[SælgerPerson-ID],[PickedByPersonID],[Kontaktperson-ID],[Resterordre-ID],[Ordredato],[Forventet leveringsdato],[Kundekøbsordrenummer],[IsUnders],[IsUnders] [DeliveryInstructions],[InternalComments],[PickingCompletedWhen],[LastEditedBy],[LastEditedWhen])SELECT[OrderID] + 25300000,[CustomerID],[SælgerPersonID],[PickedByPersonID],[ContactByPersonID],[ContactPerson-ID],Order[Backorder-ID], 06-04',[ExpectedDeliveryDate],[CustomerPurchaseOrderNumber],[IsUndersupplyBackordered],[Comments],[DeliveryInstructions],[InternalCo mments],[PickingCompletedWhen],[LastEditedBy],[LastEditedWhen]FRA [Salg].[Ordre];GO OPDATERING STATISTIK [Salg].[BigOrders] [NCI_BigOrders_OrderDate];

Ok, så vores data er fuldstændig indlæst. Hvis vi tjekker statistik igen og bruger sporingsflaget 2388 til at vise yderligere information, ser vi, at statistikken igen er markeret som Stigende:

DBCC TRACEON (2388);GO DBCC SHOW_STATISTICS ('Sales.BigOrders',[NCI_BigOrders_OrderDate]);


NCI OrderDate-statistik markeret som ASC med TF 2389 og kompatibilitetstilstand 130

Ok, så lad os spørge efter 5. juni igen:

SELECT CustomerID, OrderID, SalespersonPersonIDFROM [Sales].[BigOrders]WHERE [OrderDate] ='2016-06-05';


Plan med ny CE, ingen rækker ud over det, der er i histogrammet

Vores estimat er 4.922. Ikke helt, hvad det var i vores første test, men bestemt ikke 1.  Nu tilføjer vi nogle rækker til 5. juni og forespørger igen:

INDSÆT [Salg].[Store ordrer]( [Ordre-ID],[Kunde-ID],[SælgerPerson-ID],[PickedByPersonID],[Kontaktperson-ID],[Resterordre-ID],[Ordredato],[Forventet leveringsdato],[KundeKøb[Ordrebestillingsnummer],[Kundekøbsordrenummer], ],[Kommentarer],[Leveringsinstruktioner],[InternalComments],[PickingCompletedWhen],[LastEditedBy],[LastEditedWhen])SELECT[OrderID] + 25400000,[KundeID],[SælgerPersonID],[PickedByPersonID],[KontaktPersonID],[Kont. BackorderOrderID],'2016-06-05',[ExpectedDeliveryDate],[CustomerPurchaseOrderNumber],[IsUndersupplyBackordered],[Kommentarer],[Leveringsinstruktioner],[InternalComments],[PickingCompletedWhen],[WhenLastEditedBy] .[Ordrer];GO SELECT CustomerID, OrderID, SalespersonPersonIDFROM [Sales].[BigOrders]WHERE [OrderDate] ='2016-06-05';


Plan med ny CE, med 70K+ rækker ud over det, der er i histogrammet

Estimatet er det samme. Hvad nu hvis vi slår sporingsflag 2389 fra?

DBCC TRACEOFF (2389, -1);GO DBCC FREEPROCCACHE;GO SELECT CustomerID, OrderID, SalespersonPersonIDFROM [Sales].[BigOrders]WHERE [OrderDate] ='2016-06-05';


Plan med ny CE, men TF 2389 er IKKE aktiveret, med 70K+ rækker ud over det, der er i histogrammet

Estimatet ændrede sig lidt til 4.930, men det ændrede sig. Dette fortæller mig, at sporingsflag 2389 har en vis effekt på estimatet, men hvor meget er ukendt.

Testen – Del III

Jeg kørte en sidste test, hvor jeg gendannede databasen, satte kompatibilitetstilstanden til 130, indlæste alle data igen, opdaterede statistikker flere gange, men aktiverede IKKE sporingsflag 2389.  Koden er den samme som del II, bortset fra at bruge DBCC TRACEON for at aktivere 2389. Da jeg spurgte til 5. juni, både før og efter tilføjelse af dataene, var det estimerede antal rækker 4.920.

Hvad betyder det?

For at opsummere, når du bruger kompatibilitetstilstand 110 eller derunder, fungerer sporingsflag 2389, som det altid har gjort. Men når du bruger kompatibilitetstilstand 120 eller højere, og dermed den nye CE, er estimaterne ikke det samme sammenlignet med det gamle CE, og i dette specifikke tilfælde er de ikke så forskellige, uanset om du bruger sporingsflaget eller ej.

Så hvad skal du gøre? Test, som altid. Jeg har ikke fundet noget dokumenteret i MSDN, der siger, at sporingsflag 2389 ikke understøttes med kompatibilitetstilstand 120 og højere, og jeg har heller ikke fundet noget, der dokumenterer en ændring i adfærd. Jeg finder det meget interessant, at estimaterne er anderledes (i dette tilfælde meget lavere) med den nye CE. Det kunne potentielt være et problem, men der er flere faktorer i spil, når det kommer til estimater, og dette var en meget simpel forespørgsel (én tabel, et prædikat). I dette tilfælde er estimatet langt væk (4920 rækker mod de 22.595 rækker for datoen den 5. juni).

Hvis jeg kører forespørgslen igen for en dato, der har det samme antal rækker, som er i histogrammet får jeg en lignende plan, men den kører parallelt:

SELECT CustomerID, OrderID, SalespersonPersonIDFROM [Sales].[BigOrders]WHERE [OrderDate] ='2016-06-02';


Planlæg for en forespørgsel, der bruger en dato i histogrammet (nyt) CE, ingen TF)

Estimatet er også mere nøjagtigt (68.318). Planen ændrer sig ikke væsentligt i dette tilfælde, men omkostningerne er naturligvis højere. På et tidspunkt, afhængigt af antallet af rækker, der ville blive returneret, kan dette tippe til en tabelscanning.

Den bedste vejledning på nuværende tidspunkt, hvis du kører 2014 eller nyere og kompatibilitetstilstand 120 eller højere, og du har førende kolonner i statistik, der er stigende, er at teste. Hvis du opdager, at den nye Cardinality Estimator ikke giver et lige så godt estimat som det gamle CE, så vil jeg anbefale at indsende en Connect-vare, så produktteamet er klar over det. Der er altid enkeltstående og unikke tilfælde, men hvis mange kunder (læs:DIG) konsekvent oplever den samme adfærd – og det er ikke ideelt – så er det vigtigt at fortælle udviklingsteamet om det.

Dette er endnu et vigtigt punkt at overveje, når du opgraderer til 2014 eller 2016 – og en påmindelse om at ikke forsømmer din test (og forresten, Query Store ville være yderst nyttig her med 2016). Kom til det venner.


  1. hvad der sker i cutover-fasen af ​​adop i R12,2

  2. Kunne ikke finde den lagrede procedure 'dbo.aspnet_CheckSchemaVersion'

  3. Parse kommasepareret streng for at lave IN Liste over strenge i Where-sætningen

  4. Sådan får du sidste 12 måneders data i MySQL