sql >> Databáze >  >> RDS >> Database

Trace Flag 2389 a nový odhad kardinality

Jeden z příznaků trasování SQL Serveru, který už nějakou dobu existuje, je 2389.  Často se o tom diskutuje s 2390, ale já se chci v tomto příspěvku zaměřit pouze na 2389. Příznak trasování byl zaveden v SQL Server 2005 SP1, který byl vydán 18. dubna 2006 (podle http://sqlserverbuilds.blogspot.co.uk/), takže existuje již více než 10 let. Příznaky trasování mění chování enginu a 2389 umožňuje optimalizátoru identifikovat statistiky, které jsou vzestupné, a označit je jako takové (často nazývané "problém vzestupného klíče"). Když k tomu dojde, statistika se automaticky aktualizuje při kompilaci dotazu, což znamená, že optimalizátor má informace o nejvyšší hodnotě v tabulce (ve srovnání s případem, kdy není použit příznak trasování).

Nedávno jsem diskutoval s klientem o použití tohoto příznaku trasování a přišlo to kvůli tomuto typu scénáře:

  • Máte velkou tabulku, která má INT jako primární klíč a je seskupená.
  • Máte neseskupený index, který vede ve sloupci DATETIME.
  • Tabulka má asi 20 milionů řádků a každý den se přidá 5 000 až 100 000 řádků.
  • Statistiky se aktualizují každou noc jako součást vaší úlohy údržby.
  • Pro databázi je povolena statistika automatických aktualizací, ale i když je do tabulky přidáno 100 000 řádků, je to mnohem méně než 4 miliony řádků (20 %) potřebných k vyvolání automatické aktualizace.
  • Když uživatelé zadávají dotaz do tabulky pomocí data v predikátu, může být výkon dotazu skvělý, nebo může být hrozný.

Ta poslední odrážka to skoro zní jako problém s citlivostí parametrů, ale není. V tomto případě jde o problém statistiky. Můj návrh klientovi byl používání TF 2389 nebo častější aktualizace statistik v průběhu dne (např. prostřednictvím Agent Job). Pak mě napadlo, že udělám nějaké testování, protože klient používal SQL Server 2014.  Tady to začalo být zajímavé.

Nastavení

Chystáme se vytvořit výše uvedenou tabulku pro testování v RTM sestavení SQL Server 2016 v databázi WideWorldImporters a zpočátku nastavím režim kompatibility na 110:

POUŽÍVEJTE [master];GORESTRORE DATABÁZE [WideWorldImporters]Z  DISKU =N'C:\Backups\WideWorldImporters-Full.bak'WITH  FILE =1,PŘESUNOUT N'WWI_Primary' DO N'C:\Databases\Wide\WorldWorldImporters .mdf',PŘESUNOUT N'WWI_UserData' DO N'C:\Databases\WideWorldImporters\WideWorldImporters_UserData.ndf',PŘESUNOUT N'WWI_Log' DO N'C:\Databáze\WideWorldImporters\WideWorldata,Mporters'ld'ld'ld'ld'ld TO_Inld. N'C:\Databases\WideWorldImporters\WideWorldImporters_InMemory_Data_1',NOUNLOAD, REPLACE, STATS =5;PŘEJÍT ZMĚNIT DATABÁZI [WideWorldImporters] NASTAVIT KOMPATIBILITY_LEVEL =110;POUŽÍVAT [ŠIROKÉ]; ] [int] NOT NULL,[CustomerID] [int] NOT NULL,[SalespersonPersonID] [int] NOT NULL,[PickedByPersonID] [int] NULL,[ContactPersonID] [int] NOT NULL,[BackorderOrderID] [int] NULL, [Datum objednávky] [datum] NOT NULL,[ExpectedDeliveryDate] [datum] NOT NULL,[CustomerPurchaseOrderNumber] [nvarchar](20) NULL,[IsUndersupplyBackordered] [bit] NOT NULL,[Komentáře] [nvarchar ](max) NULL,[Pokyny k doručení] [nvarchar](max) NULL,[Interní komentáře] [nvarchar](max) NULL,[PickingCompletedWhen] [datetime2](7) NULL,[LastEditedBy] [int] NOT NULL,[LastEditedWhen ] [datetime2](7) NOT NULL,CONSTRAINT [PK_Sales_BigOrders] PRIMÁRNÍ KLÍČ SE SLUSTROVANÝM ([ID objednávky] ASC)WITH (PAD_INDEX =VYPNUTO, STATISTICS_NORELOCKCOMPUTE =VYPNUTO, IGNORE_DUP_KEY =VYPNUTO, ALLOW_ATA ZAPNUTO_ROW)_USER =ZAPNUTO] ON [USERDATA] TEXTIMAGE_ON [USERDATA];

Dále načteme asi 24 milionů řádků do BigOrders a vytvoříme neshlukovaný index v OrderDate.

SET NOCOUNT ON; DECLARE @Loops SMALLINT =0, @IDIncrement INT =75000; KDYŽ @Smyčky <325 -- upravte toto, chcete-li zvýšit nebo snížit počet přidaných řádků. ZAČÁTE VLOŽIT [Prodej].[BigOrders]( [ID objednávky],[ID zákazníka],[ID osoby prodejce],[PickedByPersonID],[ID kontaktní osoby],[ID], BackorderOr [OrderDate],[ExpectedDeliveryDate],[CustomerPurchaseOrderNumber],[IsUndersupplyBackordered],[Comments],[DeliveryInstructions],[InternalComments],[PickingCompletedWhen],[LastEditedBy],[SELECT[OIDRustomIncred] ],[SalespersonPersonID],[PickedByPersonID],[ContactPersonID],[BackorderOrderID],[OrderDate],[ExpectedDeliveryDate],[CustomerPurchaseOrderNumber],[IsUndersupply][Backordered],Při dodání,Pickordered,[ickordered], [LastEditedBy],[LastEditedWhen]OD [Prodeje].[Objednávky]; KONTROLNÍ BOD; SET @Loops =@Loops + 1;SET @IDIncrement =@IDIncrement + 75000;KONEC VYTVOŘIT NEZAHRNUTÝ INDEX [NCI_BigOrders_OrderDate]NA [Sales].[BigOrders] ([OrderDate], CustomerID);

Pokud zkontrolujeme histogram pro neshlukovaný index, uvidíme nejvyšší datum 2016-05-31:

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


Statistiky pro NCI k datu objednávky

Pokud se dotazujeme na jakékoli datum po tomto datu, poznamenejte si odhadovaný počet řádků:

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


Plánujte při dotazování na datum mimo to, co je v histogramu

Je to 1, protože hodnota je mimo histogram. A v tomto případě je to v pořádku, protože po 31. květnu 2016 v tabulce nejsou žádné řádky.  Ale pojďme je přidat a pak znovu spusťte stejný dotaz:

VLOŽTE [Sales].[BigOrders]( [OrderID],[CustomerID],[SalespersonPersonID],[PickedByPersonID],[ID Kontaktní osoby],[BackorderOrderID],[OrderDate],[OčekávanéCustomerDate,[U.N.Datum],Op. ],[Comments],[DeliveryInstructions],[InternalComments],[PickingCompletedWhen],[LastEditedBy],[LastEditedWhen])SELECT[OrderID] + 25000000,[CustomerID],[SalespersonPersonID],[ID],PickedByPerson] BackorderOrderID],'2016-06-01',[ExpectedDeliveryDate],[CustomerPurchaseOrderNumber],[IsUndersupplyBackordered],[Comments],[DeliveryInstructions],[InternalComments],[PickingCompleted]FROMBasted]Edit When],[Lasted] [Objednávky];GO VYBERTE ID zákazníka, ID objednávky, ID osoby prodejce [Prodej].[BigOrders]WHERE [Datum objednávky] ='2016-06-01';


Plánujte po přidání řádků po 31. květnu

Odhadovaný počet řádků je stále 1.  Ale tady to začíná být zajímavé. Změňme režim kompatibility na 130, abychom použili nový odhad kardinality a viděli, co se stane.

USE [master];GO ALTER DATABASE [WideWorldImporters] SET COMPATIBILITY_LEVEL =130GO USE [WideWorldImporters];GO SELECT CustomerID, OrderID, SalespersonPersonIDFROM [Sales].[BigOrders]WHERE [Datum objednávky 2016] =06';' 


Plánujte po přidání řádků na 1. června pomocí nového CE

Náš plán je stejný, ale nyní je náš odhad 4 898 řádků. Nový CE zachází s hodnotami mimo historii jinak než starý CE. Takže...potřebujeme vůbec příznak trasování 2389?

Test – část I

Při prvním testu zůstaneme v režimu kompatibility 110 a projdeme tím, co bychom viděli s 2389.  Při použití tohoto příznaku trasování jej můžete povolit jako spouštěcí parametr ve službě SQL Server, nebo můžete použít DBCC TRACEON, abyste jej povolili v celé instanci. Pochopte, že pokud ve svém produkčním prostředí použijete DBCC TRACEON k povolení příznaku trasování, při restartu instance nebude příznak trasování účinný.

Je-li povolen příznak trasování, musí být statistika aktualizována třikrát (3), než ji optimalizátor označí jako vzestupnou. Abychom dobře věděli, vynutíme čtyři aktualizace a mezi každou aktualizaci přidáme další řádky.

POUŽÍVEJTE [master];PŘEJÍT ZMĚNIT DATABÁZI [WideWorldImporters] NASTAVIT KOMPATIBILITY_LEVEL =110;GO DBCC TRACEON (2389, -1);POUŽÍT [WideWorldImporters];PŘEJÍT AKTUALIZOVAT STATISTIKY [Prodeje].[BigOrders] [NCI_DOBig INSERT [Sales].[BigOrders]( [OrderID],[CustomerID],[SalespersonPersonID],[PickedByPersonID],[ContactPersonID],[BackorderOrderID],[OrderDate],[OčekávanéDatum doručení],[PurchoredUnderom],[PurchoredUnderom Komentáře],[DeliveryInstructions],[Interní komentáře],[PickingCompletedWhen],[LastEditedBy],[LastEditedWhen])SELECT[OrderID] + 25100000,[CustomerID],[SalespersonPersonID],[PickedByPersonactrID,Back],[PickedByPertderactrIDer],[PickedByPersonactrIDer],[LastEditedWhen]) '2016-06-02',[ExpectedDeliveryDate],[CustomerPurchaseOrderNumber],[IsUndersupplyBackordered],[Comments],[DeliveryInstructions],[InternalComments],[PickingCompletedWhen],[LastEditedBy]FROM],[LastEditedBy]FROM ];PŘEJÍT AKTUALIZOVAT STATISTIKY [Prodej].[BigOrders] [NCI_BigOrders_OrderDate];PŘEJÍT INSERT [Prodej].[BigOrders]( [ID objednávky],[ID zákazníka ],[SalespersonPersonID],[PickedByPersonID],[ContactPersonID],[BackorderOrderID],[OrderDate],[ExpectedDeliveryDate],[CustomerPurchaseOrderNumber],[IsUndersupply][Backordered],Při dodání,Pickordered,[ickordered], [LastEditedBy][LastEditedWhen])SELECT[OrderID] + 25200000,[CustomerID],[SalespersonPersonID],[PickedByPersonID],[ContactPersonID],[BaccorderOrderID],'2016,[06.03.],[06.03.2016] [IsUndersupplyBackordered],[Comments],[DeliveryInstructions],[InternalComments],[PickingCompletedWhen],[LastEditedBy],[LastEditedWhen]OD [Sales][Orders];PŘEJÍT AKTUALIZOVAT STATISTIKY [Prodeje][BigOrders] [BigOrders] [BigOrders] [Disponse GO INSERT [Sales].[BigOrders]( [OrderID],[CustomerID],[SalespersonPersonID],[PickedByPersonID],[ContactPersonID],[BackorderOrderID],[OrderDate],[Očekávané datum doručení],[Očekávané datum dodání],[UrcedPurchsor [Komentáře],[Pokyny k doručení],[Interní komentáře],[PickingCompletedWhen],[LastEditedBy] ,[LastEditedWhen])SELECT[ID objednávky] + 25300000,[ID zákazníka],[ID osoby prodejce],[PickedByPersonID],[ID Kontaktní osoby],[BaccorderID objednávky],'2016-06-04',[NurberCaterder]Očekávaný[Očekávaný],[Nurchuster]U ],[Komentáře],[Pokyny k doručení],[Interní komentáře],[PickingCompletedWhen],[LastEditedBy],[LastEditedWhen]OD [Prodeje][Objednávky];PŘEJÍTE AKTUALIZOVAT STATISTIKY [Prodeje].[BigOrders] [NCI_BigOrders]_OrD 

Pokud znovu zkontrolujeme statistiku a použijeme příznak trasování 2388 k zobrazení dalších informací, uvidíme, že statistika je nyní označena jako Vzestupně:

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


NCI na OrderDate označené jako ASC

Pokud se dotazujeme na budoucí datum, kdy jsou statistiky plně aktuální, vidíme, že stále odhaduje 1 řádek:

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


Plán po aktivaci TF 2389, ale žádné řádky mimo histogram

Nyní přidáme řádky pro 5. června a spustíme stejný dotaz znovu:

VLOŽTE [Sales].[BigOrders]( [OrderID],[CustomerID],[SalespersonPersonID],[PickedByPersonID],[ID Kontaktní osoby],[BackorderOrderID],[OrderDate],[OčekávanéCustomerDate,[U.N.Datum],Op. ],[Comments],[DeliveryInstructions],[InternalComments],[PickingCompletedWhen],[LastEditedBy],[LastEditedWhen])SELECT[OrderID] + 25400000,[CustomerID],[SalespersonPersonID],[ID],PickedByPerson] BackorderOrderID],'2016-06-05',[ExpectedDeliveryDate],[CustomerPurchaseOrderNumber],[IsUndersupplyBackordered],[Comments],[DeliveryInstructions],[InternalComments],[PickingCompleted]FROMBasted]Edit When],[Lasted] [Objednávky];GO SELECT CustomerID, OrderID, SalespersonPersonIDFROM [Sales].[BigOrders]WHERE [OrderDate] ='2016-06-05';


Plánujte po aktivaci TF 2389, přes histogram bylo přidáno 70 tisíc řádků

Náš odhad už není 1, ale 22 595. Nyní pro zábavu deaktivujeme příznak trasování a uvidíme, jaký je odhad (vyčistím mezipaměť procedur, protože zakázání příznaku trasování neovlivní to, co je aktuálně v mezipaměti).

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


Plán poté, co bude TF 2389 *deaktivován*, bude přidáno více než 70 tisíc řádků histogram

Tentokrát dostanu odhadem opět 1 řádek. I když je statistika označena jako vzestupná, pokud není povolen příznak trasování 2389, odhaduje pouze 1 řádek, když se dotazujete na hodnotu mimo histogram.

Ukázali jsme, že příznak trasování 2389 dělá to, co očekáváme – to, co dělal vždy – při použití starého nástroje Cardinality Estimator. Nyní se podívejme, co se stane s novým.

Test – část II

Abych byl důkladný, všechno resetuji. Znovu vytvořím databázi, nastavím režim kompatibility na 130, nejprve načtu data, pak zapnu příznak trasování 2389 a načtu tři sady dat s aktualizacemi statistik mezi nimi.

POUŽÍVEJTE [master];PŘEJÍT OBNOVENÍ DATABÁZE [WideWorldImporters]Z  DISKU =N'C:\Backups\WideWorldImporters-Full.bak'WITH  SOUBORU =1,PŘESUNOUT N'WWI_Primary' DO N'C:\Databases\Wide\WorldImporters WideWorldImporters.mdf',PŘESUNOUT N'WWI_UserData' DO N'C:\Databases\WideWorldImporters\WideWorldImporters_UserData.ndf',PŘESUNOUT N'WWI_Log' DO N'C:\Databases\WideWorld'ldata_Importers_1Wide'Memory' TO N'C:\Databases\WideWorldImporters\WideWorldImporters_InMemory_Data_1',NOUNLOAD, REPLACE, STATS =5;GO USE [master];GO ALTER DATABASE [WideWorldImporters] SET COMPATIBILITY_USE [LEVEL] CREAWide nebo GOBLE [BigOrders]([OrderID] [int] NOT NULL,[CustomerID] [int] NOT NULL,[SalespersonPersonID] [int] NOT NULL,[PickedByPersonID] [int] NULL,[ContactPersonID] [int] NOT NULL,[ BackorderOrderID] [int] NULL,[Datum objednávky] [datum] NOT NULL,[ExpectedDeliveryDate] [datum] NOT NULL,[CustomerPurchaseOrderNumber] [nvarchar](20) NULL,[IsUndersupplyBackordered] [bit] NOT NULL mments] [nvarchar](max) NULL,[Pokyny k doručení] [nvarchar](max) NULL,[Interní komentáře] [nvarchar](max) NULL,[PickingCompletedWhen] [datetime2](7) NULL,[LastEditedBy] [int] NOT NULL,[LastEditedWhen] [datetime2](7) NOT NULL,CONSTRAINT [PK_Sales_BigOrders] PRIMÁRNÍ KLÍČ SE CLUSTERED([OrderID] ASC)WITH (PAD_INDEX =VYPNUTO, STATISTICS_NORECOMPUTE =VYPNUTO, IGNORE_DUP_LOW_KEYS =VYPNUTO =, AGE_LOW) =VYPNUTO [USERDATA]) ON [USERDATA] TEXTIMAGE_ON [USERDATA];GO SET NOCOUNT ON; DECLARE @Loops SMALLINT =0;DECLARE @IDIncrement INT =75000; KDYŽ @Smyčky <325 -- upravte toto, chcete-li zvýšit nebo snížit počet přidaných řádků. ZAČÁTE VLOŽIT [Prodej].[BigOrders]( [ID objednávky],[ID zákazníka],[ID osoby prodejce],[PickedByPersonID],[ID kontaktní osoby],[ID], BackorderOr [OrderDate],[ExpectedDeliveryDate],[CustomerPurchaseOrderNumber],[IsUndersupplyBackordered],[Comments],[DeliveryInstructions],[InternalComments],[PickingCompletedWhen],[LastEditedBy],[SELECT[OIDRustomIncred] ],[SalespersonPersonID],[PickedByPersonID],[ContactPersonID],[BackorderOrderID],[OrderDate],[ExpectedDeliveryDate],[CustomerPurchaseOrderNumber],[IsUndersupply][Backordered],Při dodání,Pickordered,[ickordered], [LastEditedBy],[LastEditedWhen]OD [Prodeje].[Objednávky]; KONTROLNÍ BOD; SET @Loops =@Loops + 1;SET @IDIncrement =@IDIncrement + 75000;KONEC VYTVOŘIT NEZAHRNUTÝ INDEX [NCI_BigOrders_OrderDate]NA [Sales].[BigOrders] ([OrderDate], CustomerID);GO INSERT [BigOSalesders]. ( [ID objednávky],[ID zákazníka],[Číslo osoby prodejce],[PickedByPersonID],[ID kontaktní osoby],[ID objednávky],[Datum objednávky],[Očekávané datum doručování],[Objednávka na nákupu],[Číslo objednávky],[Iliverysupply],[Iliverysupply],[Ilivery Interní komentáře],[PickingCompletedWhen],[LastEditedBy],[LastEditedWhen])SELECT[ID objednávky] + 25000000,[CustomerID],[ID osoby prodejce],[PickedByPersonID],[ID Kontaktní osoby],[01'-06-ID],06'06 [ExpectedDeliveryDate],[CustomerPurchaseOrderNumber],[IsUndersupplyBackordered],[Comments],[DeliveryInstructions],[Interní komentáře],[PickingCompletedWhen],[LastEditedBy],[LastEditedWhen]OD [Sales]3CC, DBGO].[O -1);PŘEJÍT AKTUALIZOVAT STATISTIKY [Prodej].[BigOrders] [NCI_BigOrders_OrderDate];PŘEJÍT INSERT [Prodej].[BigOrders]( [ID objednávky],[ID zákazníka],[Prodejce PersonID],[PickedByPersonID],[ContactPersonID],[BackorderOrderID],[OrderDate],[ExpectedDeliveryDate],[CustomerPurchaseOrderNumber],[IsUndersupplyBackordered],[Komentáře],[AstingComments,[DelivedInIf] ,[LastEditedWhen])SELECT[ID objednávky] + 25100000,[ID zákazníka],[ID osoby prodejce],[PickedByPersonID],[ID Kontaktní osoby],[BaccorderID objednávky],'2016-06-02',[NurberCaterder]Očekávaný[Očekávaný],[Nurchusted]UliverP ],[Komentáře],[Pokyny k doručení],[Interní komentáře],[PickingCompletedWhen],[LastEditedBy],[LastEditedWhen]OD [Prodeje][Objednávky];PŘEJÍT AKTUALIZOVAT STATISTIKY [Prodej][Velké objednávky] [NCI_BigOrders]_ORI IDER [Prodej].[BigOrders]( [ID objednávky],[ID zákazníka],[ID osoby prodejce],[PickedByPersonID],[ID Kontaktní osoby],[ID objednávky],[Datum objednávky],[Očekávané datum doručení],[Zákazník],Zákazník[Objednávka[nebo ],[DeliveryInstructions],[Interní komentáře],[PickingCompletedWhen],[LastEditedBy],[LastEditedW slepice])SELECT[ID objednávky] + 25200000,[ID zákazníka],[ID osoby prodejce],[PickedByPersonID],[ID Kontaktní osoby],[ID objednávky],'2016-06-03',[Očekávané[Datum doručení]Datum doručování]Sup. [Komentáře],[Pokyny k doručení],[Interní komentáře],[PickingCompletedWhen],[LastEditedBy],[LastEditedWhen]OD [Prodeje][Objednávky];PŘEJÍTE AKTUALIZOVAT STATISTIKY [Prodej].[BigOrders] [NCI_BigOrders_OrderNSERT]; ].[BigOrders]( [ID objednávky],[ID zákazníka],[ID osoby prodejce],[PickedByPersonID],[ID Kontaktní osoby],[ID objednávky],[Datum objednávky],[Očekávané datum doručení],[Zákazník],[Zákazník]Kupování] [DeliveryInstructions],[InternalComments],[PickingCompletedWhen],[LastEditedBy],[LastEditedWhen])SELECT[OrderID] + 25300000,[CustomerID],[SalespersonPersonID],[PickedByPersonIDer6],[Contact'O1Pr0der],[Contact'O1Pr0 06-04',[ExpectedDeliveryDate],[CustomerPurchaseOrderNumber],[IsUndersupplyBackordered],[Comments],[DeliveryInstructions],[InternalCo mments],[PickingCompletedWhen],[LastEditedBy],[LastEditedWhen]OD [Sales][Orders];PŘEJÍTE AKTUALIZOVAT STATISTIKY [Prodeje].[BigOrders] [NCI_BigOrders_OrderDate];

Dobře, takže naše data jsou zcela načtena. Pokud znovu zkontrolujeme statistiku a použijeme příznak trasování 2388 k zobrazení dalších informací, uvidíme, že statistika je opět označena jako Vzestupně:

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


Statistika NCI OrderDate označená jako ASC s TF 2389 a režimem kompatibility 130

Dobře, takže se znovu zeptáme na 5. června:

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


Plánujte s novým CE, žádné řádky nad rámec toho, co je v histogramu

Náš odhad je 4 922. Ne úplně to, co bylo v našem prvním testu, ale rozhodně ne 1.  Nyní přidáme několik řádků pro 5. června a znovu se zeptáme:

VLOŽTE [Sales].[BigOrders]( [OrderID],[CustomerID],[SalespersonPersonID],[PickedByPersonID],[ID Kontaktní osoby],[BackorderOrderID],[OrderDate],[OčekávanéCustomerDate,[U.N.Datum],Op. ],[Comments],[DeliveryInstructions],[InternalComments],[PickingCompletedWhen],[LastEditedBy],[LastEditedWhen])SELECT[OrderID] + 25400000,[CustomerID],[SalespersonPersonID],[ID],PickedByPerson] BackorderOrderID],'2016-06-05',[ExpectedDeliveryDate],[CustomerPurchaseOrderNumber],[IsUndersupplyBackordered],[Comments],[DeliveryInstructions],[InternalComments],[PickingCompleted]FROMBasted]Edit When],[Lasted] [Objednávky];GO SELECT CustomerID, OrderID, SalespersonPersonIDFROM [Sales].[BigOrders]WHERE [OrderDate] ='2016-06-05';


Plánujte s novým CE s více než 70 tisíci řádky nad rámec toho, co je v histogramu

Odhad je stejný. Takže teď, co když vypneme příznak trasování 2389?

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


Plánujte s novým CE, ale NENÍ povoleno TF 2389, s 70 000+ řádků za tím, co je v histogramu

Odhad se mírně změnil, na 4 930, ale změnil se. To mi říká, že příznak trasování 2389 má určitý vliv na odhad, ale jak moc, není známo.

Test – část III

Provedl jsem jeden závěrečný test, kde jsem obnovil databázi, nastavil režim kompatibility na 130, znovu načetl všechna data, několikrát aktualizoval statistiky, ale NEPOVOLIL jsem příznak trasování 2389.  Kód je stejný jako v části II, kromě použití DBCC TRACEON pro aktivaci 2389.  Když jsem se dotazoval na 5. června, před i po přidání dat, odhadovaný počet řádků byl 4 920.

Co to znamená?

Abychom to shrnuli, při použití režimu kompatibility 110 nebo nižšího funguje příznak trasování 2389 jako vždy. Ale při použití režimu kompatibility 120 nebo vyšší, a tedy nové CE, odhady nejsou stejné ve srovnání se starým CE a v tomto konkrétním případě se příliš neliší, ať už používáte příznak trasování nebo ne.

Co byste tedy měli dělat? Test, jako vždy. V MSDN jsem nenašel nic, co by uvádělo, že příznak trasování 2389 není podporován s režimem kompatibility 120 a vyšším, ani jsem nenašel nic, co by dokumentovalo změnu chování. Považuji za velmi zajímavé, že odhady jsou u nového CE odlišné (v tomto případě mnohem nižší). To by mohl být problém, ale pokud jde o odhady, ve hře je více faktorů, a toto byl velmi jednoduchý dotaz (jedna tabulka, jeden predikát). V tomto případě je odhad daleko (4920 řádků oproti 22 595 řádkům pro datum 5. června).

Pokud znovu spustím dotaz pro datum, které má stejný počet řádků jako je v rámci histogramu dostávám podobný plán, ale běží paralelně:

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


Naplánujte si dotaz, který používá datum v histogramu (nové CE, bez TF)

Přesnější je i odhad (68 318). Plán se v tomto případě výrazně nemění, ale náklady jsou samozřejmě vyšší. V určitém okamžiku, v závislosti na počtu řádků, které by byly vráceny, by to mohlo vést k prohledávání tabulky.

Nejlepším vodítkem v tuto chvíli, pokud používáte rok 2014 nebo vyšší a režim kompatibility 120 nebo vyšší a máte přední sloupce ve statistikách, které jsou vzestupné, je testování. Pokud zjistíte, že nový odhad kardinality neposkytuje tak dobrý odhad jako starý CE, pak bych doporučil vyplnit položku Connect, aby si toho byl produktový tým vědom. Vždy existují jednorázové a jedinečné případy, ale pokud mnoho zákazníků (čti:VY) trvale nachází stejné chování – a není to ideální –, pak je důležité o tom informovat vývojový tým.

Toto je další důležitá věc, kterou je třeba zvážit při upgradu na rok 2014 nebo 2016 – a připomenutí, abyste ne zanedbejte své testování (a mimochodem, Query Store by zde byl v roce 2016 extrémně užitečný). Pusťte se do toho přátelé.


  1. FOR XML PATH(''):Escapování speciálních znaků

  2. Vyberte 10 nejlepších záznamů pro každou kategorii

  3. Zbavte se duplicitních hodnot v jednom sloupci ve výběru dvou sloupců

  4. Nasaďte skupiny dostupnosti SQL Server AlwaysOn v systému Linux