sql >> Databasteknik >  >> RDS >> Database

Trace Flag 2389 och den nya Cardinality Estimator

En av SQL Server-spårningsflaggorna som har funnits ett tag är 2389.  Det diskuteras ofta med 2390, men jag vill bara fokusera på 2389 för det här inlägget. Spårningsflaggan introducerades i SQL Server 2005 SP1, som släpptes den 18 april 2006 (enligt http://sqlserverbuilds.blogspot.co.uk/), så den har funnits i över 10 år. Spårningsflaggor ändrar motorns beteende och 2389 tillåter optimeraren att identifiera statistik som är stigande och märka dem som sådan (ofta kallad "det stigande nyckelproblemet"). När detta inträffar kommer statistiken att uppdateras automatiskt vid frågekompilering, vilket innebär att optimeraren har information om det högsta värdet i tabellen (jämfört med när spårningsflaggan inte används).

Jag hade nyligen en diskussion med en klient om att använda den här spårningsflaggan, och den kom upp på grund av den här typen av scenario:

  • Du har en stor tabell som har en INT som primärnyckel, och den är klustrad.
  • Du har ett icke-klustrat index som leder till en DATETIME-kolumn.
  • Tabellen har cirka 20 miljoner rader, och allt från 5 000 till 100 000 rader läggs till varje dag.
  • Statistiken uppdateras varje natt som en del av din underhållsuppgift.
  • Automatisk uppdateringsstatistik är aktiverad för databasen, men även om 100 000 rader läggs till i tabellen är det betydligt mindre än de 4 miljoner rader (20 %) som behövs för att anropa en automatisk uppdatering.
  • När användare frågar tabellen med hjälp av datumet i predikatet kan frågeprestanda vara bra, eller så kan det vara hemskt.

Den sista kulan får det nästan att låta som ett problem med parameterkänslighet, men det är det inte. I det här fallet är det en statistikfråga. Mitt förslag till klienten var att använda TF 2389, eller att uppdatera statistiken oftare under dagen (t.ex. via ett agentjobb). Sedan tänkte jag göra några tester, eftersom klienten körde SQL Server 2014.  Det var här det blev intressant.

Inställningen

Vi kommer att skapa den ovannämnda tabellen för testning i RTM-bygget av SQL Server 2016, inom WideWorldImporters-databasen, och jag kommer att ställa in kompatibilitetsläget till 110 initialt:

ANVÄND [master];GORESTORE DATABAS [WideWorldImporters]FRÅN  DISK =N'C:\Backups\WideWorldImporters-Full.bak'WITH  FILE =1,FLYTTA N'WWI_Primary' TILL N'C:\Databases\WideWorldImporters\WideWorldImporters\ .mdf',MOVE N'WWI_UserData' TO N'C:\Databases\WideWorldImporters\WideWorldImporters_UserData.ndf',MOVE N'WWI_Log' TO N'C:\Databases\WideWorldImporters\WideWorldImporters\WideWorldImporters_UserData.ndf',MOVE N'WWI_Log' TO N'C:\Databases\WideWorldImporters\WideWorldImporters\WideWorldImporters'N_MORldyWorld'1_MORldyWorld'1 N'C:\Databaser\WideWorldImporters\WideWorldImporters_InMemory_Data_1',NOUNLOAD, REPLACE, STATS =5;GO ALTER DATABASE [WideWorldImporters] SET COMPATIBILITY_LEVEL =110;GO ANVÄND [WideWorldImporters][WideWorldImporters][GÅ ANVÄNDA [WideWorldImporters][GÅ ANVÄNDA]Order [WideWorldImporters] ] [int] NOT NULL,[Kund-ID] [int] NOT NULL,[SäljarePersonID] [int] NOT NULL,[PickedByPersonID] [int] NULL,[Kontaktperson-ID] [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) INTE NULL,BEGRÄNSNING [PK_Sales_BigOrders] PRIMÄRNYCKEL KLUSTERAD([OrderID] ASC) MED (PAD_INDEX =AV, STATISTICS_NORECOMPUTE =AV, IGNORE_DUP_KEY =AV, TILLÅTAR =ROW_LOCKON, PÅ)]ANVÄNDARE PÅ [USERDATA] TEXTIMAGE_ON [USERDATA];

Därefter ska vi ladda cirka 24 miljoner rader i BigOrders och skapa ett icke-klusterat index på OrderDate.

STÄLL IN NOCOUNT PÅ; DECLARE @Loops SMALLINT =0, @IDIncrement INT =75000; WHILE @Loops <325 -- justera detta för att öka eller minska antalet tillagda rader BÖRJA INFOGA [Försäljning].[BigOrders]( [OrderID],[Kund-ID],[SäljarePersonID],[PickedByPersonID],[ContactPersonID],[Backorder OrderID], [OrderDate],[ExpectedDeliveryDate],[CustomerPurchaseOrderNumber],[IsUndersupplyBackordered],[Comments],[DeliveryInstructions],[InternalComments],[PickingCompletedWhen],[LastEditedBy],[LastEditedWhen],+SELECT[OrderIncrementID])@CIDustomerID ],[SäljarePersonID],[PickedByPersonID],[ContactPersonID],[Backorder OrderID],[OrderDate],[ExpectedDeliveryDate],[CustomerPurchaseOrderNumber],[IsUndersupplyBackordered],[Comments],[DeliveryInstructions],P [LastEditedBy],[LastEditedWhen]FRÅN [Försäljning].[Beställningar]; KONTROLLSTATION; SET @Loops =@Loops + 1;SET @IDIncrement =@IDIncrement + 75000;END SKAPA ICKELUSTERAT INDEX [NCI_BigOrders_OrderDate]PÅ [Sales].[BigOrders] ([OrderDate], CustomerID);

Om vi ​​kontrollerar histogrammet för det icke-klustrade indexet ser vi att det högsta datumet är 2016-05-31:

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


Statistik för NCI på orderdatum

Om vi ​​frågar efter något datum efter det, notera det uppskattade antalet rader:

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


Planera när du frågar efter ett datum utöver vad som finns i histogrammet

Det är 1, eftersom värdet ligger utanför histogrammet. Och i det här fallet är det ok, eftersom det inte finns några rader i tabellen efter den 31 maj 2016.  Men låt oss lägga till några och sedan köra samma fråga igen:

INFOGA [Försäljning].[BigOrders]( [OrderID],[Kund-ID],[SäljarePersonID],[PickedByPersonID],[Kontaktperson-ID],[Restabeställnings-ID],[OrderDate],[Förväntat leveransdatum],[Kundköp[Beställningsnummer],Kundbeställningsnummer ],[Comments],[DeliveryInstructions],[InternalComments],[PickingCompletedWhen],[LastEditedBy],[LastEditedWhen])SELECT[OrderID] + 25000000,[CustomerID],[SäljarePersonID],[PickedByPersonID],[Kont. BackorderOrderID],'2016-06-01',[ExpectedDeliveryDate],[CustomerPurchaseOrderNumber],[IsUndersupplyBackordered],[Kommentarer],[Leveransinstruktioner],[InternalComments],[PickingCompletedWhen],[Sista[]Avslutad],[Whast[]AsteredBy] .[Order];GO SELECT CustomerID, OrderID, SalespersonPersonIDFROM [Sales].[BigOrders]WHERE [OrderDate] ='2016-06-01';


Planera efter att ha lagt till rader efter den 31 maj

Det uppskattade antalet rader är fortfarande 1. Men det är här det blir intressant. Låt oss ändra kompatibilitetsläget till 130 så att vi använder den nya Cardinality Estimator och se vad som händer.

ANVÄND [master];GO ALTER DATABASE [WideWorldImporters] SET COMPATIBILITY_LEVEL =130GO USE [WideWorldImporters];GO SELECT CustomerID, OrderID, SalespersonPersonIDFROM [Sales].[BigOrders]WHERE [OrderDate]-02016'; 


Planera efter att ha lagt till rader för 1 juni, med det nya CE

Vår planform är densamma, men nu är vår uppskattning 4 898 rader. Det nya CE behandlar värden utanför historien annorlunda än det gamla CE. Så ... behöver vi ens spårflagga 2389?

Test – del I

För det första testet kommer vi att stanna i kompatibilitetsläge 110 och köra igenom vad vi skulle se med 2389.  När du använder denna spårningsflagga kan du antingen aktivera den som en startparameter i SQL Server-tjänsten, eller så kan du använda DBCC TRACEON för att aktivera det hela instansen. Förstå att i din produktionsmiljö, om du använder DBCC TRACEON för att aktivera spårningsflaggan, kommer spårningsflaggan inte att vara aktiv när instansen startar om.

Med spårningsflaggan aktiverad måste en statistik uppdateras tre (3) gånger innan optimeraren kommer att markera den som stigande. Vi kommer att tvinga fram fyra uppdateringar för god åtgärd och lägga till fler rader mellan varje uppdatering.

ANVÄND [master];GO ALTER DATABASE [WideWorldImporters] SET COMPATIBILITY_LEVEL =110;GO DBCC TRACEON (2389, -1);GO USE [WideWorldImporters];GO UPPDATERA STATISTIK [Sales].[BigOrderBige] [NCI_OrderBige]; INFOGA [Försäljning].[BigOrders]( [OrderID],[Kund-ID],[SäljarePersonID],[PickedByPersonID],[ContactPersonID],[Restaorder-ID],[OrderDate],[Förväntat leveransdatum],[CustomerPurchaseOrderUnders],IBorderUnders],IBorderUnders[ Kommentarer],[DeliveryInstructions],[InternalComments],[PickingCompletedWhen],[LastEditedBy],[LastEditedWhen])SELECT[OrderID] + 25100000,[CustomerID],[SäljarePersonID],[PickedByPersonord],[ContactBacker-ID],[ContactBackerson], '2016-06-02',[ExpectedDeliveryDate],[CustomerPurchaseOrderNumber],[IsUndersupplyBackordered],[Comments],[DeliveryInstructions],[InternalComments],[PickingCompletedWhen],[LastEditedBy],[LastEditedBy],[LastEditedBy],[LastEditedWhen]]FROM [LastEditedWhen] ];GO UPPDATERA STATISTIK [Försäljning].[BigOrders] [NCI_BigOrders_OrderDate];GO INSERT [Sales].[BigOrders]( [OrderID],[Kund-ID] ],[SäljarePersonID],[PickedByPersonID],[ContactPersonID],[Backorder OrderID],[OrderDate],[ExpectedDeliveryDate],[CustomerPurchaseOrderNumber],[IsUndersupplyBackordered],[Kommentarer],[Leveransinstruktioner],Pinterinstruktioner],P [LastEditedBy][LastEditedWhen])SELECT[OrderID] + 25200000,[CustomerID],[SäljarePersonID],[PickedByPersonID],[ContactPersonID],[BackorderOrderID],'2016-06-03',DeliveryNexpected[BeställningC] [IsUndersupplyBackordered],[Kommentarer],[Leveransinstruktioner],[InternalComments],[PickingCompletedWhen],[LastEditedBy],[LastEditedWhen]FRÅN [Försäljning].[Order];GÅ UPPDATERA STATISTIK [Försäljning].[BigOrder] [NCI_BigOrder]; SÄTT IN [Försäljning].[BigOrders]( [OrderID],[Kund-ID],[SäljarePersonID],[PickedByPersonID],[ContactPersonID],[Restabeställnings-ID],[OrderDate],[Förväntat leveransdatum],[Kundköp[Beställningsnummer],Ibeställningsnummer [Kommentarer],[Leveransinstruktioner],[Internalkommentarer],[PlockningCompletedWhen],[LastEditedBy] ,[LastEditedWhen])SELECT[OrderID] + 25300000,[CustomerID],[SäljarePersonID],[PickedByPersonID],[ContactPersonID],[BackorderOrderID],'2016-06-04',[ExpectedCseUstomeryNacked[ExpectedDeliveryOrderP] ],[Comments],[DeliveryInstructions],[InternalComments],[PickingCompletedWhen],[LastEditedBy],[LastEditedWhen]FRÅN [Sales].[Orders];OPPDATERA STATISTIK [Försäljning].[BigOrders] [NCI_BigOrders_OrderDate]; 

Om vi ​​kontrollerar statistik igen och använder spårningsflaggan 2388 för att visa ytterligare information, ser vi att statistiken nu är markerad som Stigande:

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


NCI på orderdatum markerat som ASC

Om vi ​​frågar efter ett framtida datum, när statistiken är helt uppdaterad, ser vi att den fortfarande uppskattar 1 rad:

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


Planera efter TF 2389 aktiverat, men inga rader bortom histogrammet

Nu lägger vi till rader för 5 juni och kör samma fråga igen:

INFOGA [Försäljning].[BigOrders]( [OrderID],[Kund-ID],[SäljarePersonID],[PickedByPersonID],[Kontaktperson-ID],[Restabeställnings-ID],[OrderDate],[Förväntat leveransdatum],[Kundköp[Beställningsnummer],Kundbeställningsnummer ],[Comments],[DeliveryInstructions],[InternalComments],[PickingCompletedWhen],[LastEditedBy],[LastEditedWhen])SELECT[OrderID] + 25400000,[CustomerID],[SäljarePersonID],[PickedByPersonID],[Kont. BackorderOrderID],'2016-06-05',[ExpectedDeliveryDate],[CustomerPurchaseOrderNumber],[IsUndersupplyBackordered],[Kommentarer],[Leveransinstruktioner],[InternalComments],[PickingCompletedWhen],[Whast[]EditedBy] .[Order];GO SELECT CustomerID, OrderID, SalespersonPersonIDFROM [Sales].[BigOrders]WHERE [OrderDate] ='2016-06-05';


Planera efter TF 2389 aktiverat, 70K+ rader tillagda bortom histogrammet

Vår uppskattning är inte längre 1, den är 22 595. Nu, bara för skojs skull, låt oss inaktivera spårningsflaggan och se vad uppskattningen är (jag ska rensa procedurens cache, eftersom inaktivering av spårningsflaggan inte påverkar vad som för närvarande finns i cachen).

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


Planera efter TF 2389 är *inaktiverat*, 70K+ rader har lagts till utöver histogram

Den här gången får jag en uppskattning på 1 rad igen. Även om statistiken märks som stigande, om spårningsflagga 2389 inte är aktiverad, uppskattar den bara 1 rad när du frågar efter ett värde utanför histogrammet.

Vi har visat att spårflaggan 2389 gör vad vi förväntar oss – vad den alltid har gjort – när vi använder den gamla Cardinality Estimator. Låt oss nu se vad som händer med den nya.

Testen – del II

För att vara noggrann kommer jag att återställa allt. Jag kommer att skapa databasen igen, ställa in kompatibilitetsläget till 130, ladda data initialt, sedan aktivera spårningsflagga 2389 och ladda tre uppsättningar data med statistikuppdateringar emellan.

ANVÄND [master]; GÅ ÅTERSTÄLL DATABAS [WideWorldImporters]FRÅN  DISK =N'C:\Backups\WideWorldImporters-Full.bak'WITH  FILE =1,FLYTTA N'WWI_Primary' TILL N'C:\Databases\WideWorldIm WideWorldImporters.mdf',FLYTTA N'WWI_UserData' TILL N'C:\Databases\WideWorldImporters\WideWorldImporters_UserData.ndf',FLYTTA N'WWI_Log' TILL N'C:\Databases\WideWorldImporters\WideWorldImportersIn_WorldImOvE_WorldImporters\WideWorldImporters' TO N'C:\Databases\WideWorldImporters\WideWorldImporters_InMemory_Data_1',NOUNLOAD, REPLACE, STATS =5;GO USE [master];GO ALTER DATABASE [WideWorldImporters] SET COMPATIBILITY_LEVELGO_LEVELGO =13IGOde [WideWorldImporters]; .[BigOrders]([OrderID] [int] NOT NULL,[CustomerID] [int] NOT NULL,[SäljarePersonID] [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,[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ÄRNYCKEL KLUSTERAD([OrderID] ASC)MED (PAD_INDEX =AV, STATISTICS_NORECOMPUTE =AV, IGNORE_DUP_KEYOWS LOCK PÅ, IGNORE_DUP_KEYOWS LOCK ON) [USERDATA]) PÅ [USERDATA] TEXTIMAGE_ON [USERDATA]; GÅ STÄLL IN NOCOUNT PÅ; DECLARE @Loops SMALLINT =0;DECLARE @IDIncrement INT =75000; WHILE @Loops <325 -- justera detta för att öka eller minska antalet tillagda rader BÖRJA INFOGA [Försäljning].[BigOrders]( [OrderID],[Kund-ID],[SäljarePersonID],[PickedByPersonID],[ContactPersonID],[Backorder OrderID], [OrderDate],[ExpectedDeliveryDate],[CustomerPurchaseOrderNumber],[IsUndersupplyBackordered],[Comments],[DeliveryInstructions],[InternalComments],[PickingCompletedWhen],[LastEditedBy],[LastEditedWhen],+SELECT[OrderIncrementID])@CIDustomerID ],[SäljarePersonID],[PickedByPersonID],[ContactPersonID],[Backorder OrderID],[OrderDate],[ExpectedDeliveryDate],[CustomerPurchaseOrderNumber],[IsUndersupplyBackordered],[Comments],[DeliveryInstructions],P [LastEditedBy],[LastEditedWhen]FRÅN [Försäljning].[Beställningar]; KONTROLLSTATION; SET @Loops =@Loops + 1;SET @IDIncrement =@IDIncrement + 75000;SLUT SKAPA ICKELUSTERAT INDEX [NCI_BigOrders_OrderDate]PÅ [Sales].[BigOrders] ([OrderDate], CustomerID);GO INSERT [Sales].[BigOrders] ( [OrderID],[CustomerID],[SäljarePersonID],[PickedByPersonID],[ContactPersonID],[Backorder OrderID],[OrderDate],[ExpectedDeliveryDate],[CustomerPurchaseOrderNumber],[IsUndersupplyBackordered],[Leverans] InternalComments],[PickingCompletedWhen],[LastEditedBy],[LastEditedWhen])SELECT[OrderID] + 25000000,[CustomerID],[SäljarePersonID],[PickedByPersonID],[ContactPersonID],[Reservorder16',62-0016',',' [ExpectedDeliveryDate],[CustomerPurchaseOrderNumber],[IsUndersupplyBackordered],[Comments],[DeliveryInstructions],[InternalComments],[PickingCompletedWhen],[LastEditedBy],[LastEditedWhen]FRÅN [Sales].[Beställningar].[Beställningar] -1);GO UPPDATERA STATISTIK [Försäljning].[BigOrders] [NCI_BigOrders_OrderDate];GO INSERT [Sales].[BigOrders]( [OrderID],[Kund-ID],[Säljare PersonID],[PickedByPersonID],[ContactPersonID],[BackorderOrderID],[OrderDate],[ExpectedDeliveryDate],[CustomerPurchaseOrderNumber],[IsUndersupplyBackordered],[Kommentarer],[Leveransinstruktioner],[Personalkommentarer],[Internalkommentarer],[Internalkommentarer],[VärdEditB] ,[LastEditedWhen])SELECT[OrderID] + 25100000,[CustomerID],[SäljarePersonID],[PickedByPersonID],[ContactPersonID],[BackorderOrderID],'2016-06-02',[ExpectedCseUstomeryNackorderP] ],[Comments],[Leveransinstruktioner],[InternalComments],[PickingCompletedWhen],[LastEditedBy],[LastEditedWhen]FRÅN [Försäljning].[Order];GÅ UPPDATERA STATISTIK [Försäljning].[BigOrders] [NCI_BigOrders_OrderDate];GO INSERT. [Sales].[BigOrders]( [OrderID],[CustomerID],[SäljarePersonID],[PickedByPersonID],[ContactPersonID],[Backorder OrderID],[OrderDate],[ExpectedDeliveryDate],[CustomerPurchaseOrderNumbers],[IsUBackUnders] ],[DeliveryInstructions],[InternalComments],[PickingCompletedWhen],[LastEditedBy],[LastEditedW hen])SELECT[OrderID] + 25200000,[CustomerID],[SäljarePersonID],[PickedByPersonID],[ContactPersonID],[Backorder OrderID],'2016-06-03',[ExpectedDeliveryDate],[CustomerNumbersuppe],[CustomerNumbersuppe] [Comments],[Leveransinstruktioner],[Interna kommentarer],[PickingCompletedWhen],[LastEditedBy],[LastEditedWhen]FRÅN [Försäljning].[Order];GÅ UPPDATERA STATISTIK [Försäljning].[BigOrders] [NCI_BigOrders_OrderDate];GO INSERT [Försäljning]. ].[BigOrders]( [OrderID],[CustomerID],[SäljarePersonID],[PickedByPersonID],[ContactPersonID],[Restaorder-ID],[OrderDate],[ExpectedDeliveryDate],[CustomerPurchaseOrderNumber],[IsUnders],[IsUnders] [DeliveryInstructions],[InternalComments],[PickingCompletedWhen],[LastEditedBy],[LastEditedWhen])SELECT[OrderID] + 25300000,[CustomerID],[SäljarePersonID],[PickedByPersonID],[ContactByPersonID],[ContactByPerson-ID],Order[Beställnings-ID] 06-04',[ExpectedDeliveryDate],[CustomerPurchaseOrderNumber],[IsUndersupplyBackordered],[Comments],[DeliveryInstructions],[InternalCo mments],[PickingCompletedWhen],[LastEditedBy],[LastEditedWhen]FRÅN [Sales].[Orders];GO UPPDATERA STATISTIK [Sales].[BigOrders] [NCI_BigOrders_OrderDate];

Ok, så vår data är helt laddad. Om vi ​​kontrollerar statistik igen och använder spårningsflaggan 2388 för att visa ytterligare information, ser vi att statistiken återigen markeras som Stigande:

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


NCI OrderDate-statistik markerad som ASC med TF 2389 och kompatibilitetsläge 130

Okej, så låt oss fråga efter 5 juni igen:

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


Planera med ny CE, inga rader utöver vad som finns i histogrammet

Vår uppskattning är 4 922. Inte riktigt vad det var i vårt första test, men definitivt inte 1. Nu lägger vi till några rader för 5 juni och frågar igen:

INFOGA [Försäljning].[BigOrders]( [OrderID],[Kund-ID],[SäljarePersonID],[PickedByPersonID],[Kontaktperson-ID],[Restabeställnings-ID],[OrderDate],[Förväntat leveransdatum],[Kundköp[Beställningsnummer],Kundbeställningsnummer ],[Comments],[DeliveryInstructions],[InternalComments],[PickingCompletedWhen],[LastEditedBy],[LastEditedWhen])SELECT[OrderID] + 25400000,[CustomerID],[SäljarePersonID],[PickedByPersonID],[Kont. BackorderOrderID],'2016-06-05',[ExpectedDeliveryDate],[CustomerPurchaseOrderNumber],[IsUndersupplyBackordered],[Kommentarer],[Leveransinstruktioner],[InternalComments],[PickingCompletedWhen],[Whast[]EditedBy] .[Order];GO SELECT CustomerID, OrderID, SalespersonPersonIDFROM [Sales].[BigOrders]WHERE [OrderDate] ='2016-06-05';


Planera med ny CE, med 70K+ rader utöver vad som finns i histogrammet

Uppskattningen är densamma. Så nu, tänk om vi stänger av spårningsflaggan 2389?

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


Planera med ny CE men TF 2389 är INTE aktiverad, med 70K+ rader bortom vad som finns i histogrammet

Uppskattningen ändrades något, till 4 930, men den ändrades. Detta säger mig att spårningsflagga 2389 har viss effekt på uppskattningen, men hur mycket är okänt.

Testet – del III

Jag körde ett sista test, där jag återställde databasen, ställde in kompatibilitetsläget till 130, laddade all data igen, uppdaterade statistik flera gånger, men aktiverade INTE spårningsflagga 2389.  Koden är densamma som del II, förutom att använda DBCC TRACEON för att aktivera 2389.  När jag frågade för den 5 juni, både före och efter att ha lagt till data, var det uppskattade antalet rader 4 920.

Vad betyder det?

För att sammanfatta, när du använder kompatibilitetsläge 110 eller lägre, fungerar spårningsflagga 2389 som det alltid har gjort. Men när du använder kompatibilitetsläge 120 eller högre, och därmed den nya CE:n, är uppskattningarna inte samma jämfört med den gamla CE, och i det här specifika fallet är de inte så olika oavsett om du använder spårningsflaggan eller inte.

Så vad ska du göra? Testa som alltid. Jag har inte hittat något dokumenterat i MSDN som säger att spårflagga 2389 inte stöds med kompatibilitetsläge 120 och högre, och jag har inte heller hittat något som dokumenterar en förändring i beteende. Jag tycker att det är väldigt intressant att uppskattningarna är annorlunda (i det här fallet mycket lägre) med den nya CE. Det kan potentiellt vara ett problem, men det finns flera faktorer som spelar in när det kommer till uppskattningar, och det här var en mycket enkel fråga (en tabell, ett predikat). I det här fallet är uppskattningen långt borta (4 920 rader jämfört med 22 595 rader för datumet den 5 juni).

Om jag kör frågan igen för ett datum som har samma antal rader som är inom histogrammet får jag en liknande plan, men den körs parallellt:

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


Planera för en fråga som använder ett datum i histogrammet (ny) CE, ingen TF)

Uppskattningen är också mer exakt (68 318). Planen förändras inte nämnvärt i det här fallet, men kostnaden är uppenbarligen högre. Vid någon tidpunkt, beroende på antalet rader som skulle returneras, kan detta leda till en tabellskanning.

Den bästa vägledningen för närvarande om du kör 2014 eller högre och kompatibilitetsläge 120 eller högre, och du har ledande kolumner i statistik som stiger, är att testa. Om du upptäcker att den nya Cardinality Estimator inte ger en lika bra uppskattning som den gamla CE, rekommenderar jag att du lämnar in ett Connect-objekt så att produktteamet är medvetet om det. Det finns alltid enstaka och unika fall, men om många kunder (läs:DU) konsekvent upptäcker samma beteende – och det är inte idealiskt – så är det viktigt att informera utvecklingsteamet om det.

Detta är en annan viktig punkt att tänka på när du uppgraderar till 2014 eller 2016 – och en påminnelse om att inte försumma din testning (och förresten, Query Store skulle vara extremt användbar här med 2016). Kom till det vänner.


  1. Hur får jag textinnehåll från BLOB i Oracle SQL

  2. Bevilja rättigheter för lagrad procedur till en annan användare av Oracle

  3. 3 sätt att få månadens namn från ett datum i MariaDB

  4. Ogiltig identifierare SQL