Database
 sql >> база данни >  >> RDS >> Database

Trace Flag 2389 и новият оценител на мощността

Един от флаговете за проследяване на SQL Server, който съществува от известно време, е 2389.  Често се обсъжда с 2390, но просто искам да се съсредоточа върху 2389 за тази публикация. Флагът за проследяване беше въведен в SQL Server 2005 SP1, който беше пуснат на 18 април 2006 г. (според http://sqlserverbuilds.blogspot.co.uk/), така че съществува от повече от 10 години. Флаговете за проследяване променят поведението на двигателя, а 2389 позволява на оптимизатора да идентифицира статистически данни, които са нарастващи и да ги маркира като такива (често наричан "проблем с възходящия ключ"). Когато това се случи, статистическите данни ще се актуализират автоматично по време на компилиране на заявката, което означава, че оптимизаторът има информация за най-високата стойност в таблицата (в сравнение с това, когато флагът за проследяване не се използва).

Наскоро имах дискусия с клиент относно използването на този флаг за проследяване и се появи поради този тип сценарий:

  • Имате голяма таблица, която има INT като първичен ключ и е групирана.
  • Имате неклъстериран индекс, който води до колона DATETIME.
  • Таблицата има около 20 милиона реда и всеки ден се добавят от 5 000 до 100 000 реда.
  • Статистиката се актуализира всяка нощ като част от задачата ви за поддръжка.
  • Статистическите данни за автоматично актуализиране са активирани за базата данни, но дори ако към таблицата се добавят 100 000 реда, това е много по-малко от 4 милиона реда (20%), необходими за извикване на автоматична актуализация.
  • Когато потребителите правят заявка към таблицата, използвайки датата в предиката, ефективността на заявката може да бъде страхотна или ужасна.

Този последен куршум почти го прави да звучи като проблем с чувствителността на параметрите, но не е. В този случай това е въпрос на статистика. Моето предложение към клиента беше да използвам TF 2389 или да актуализирам статистиката по-често през целия ден (например чрез задание на агент). След това реших да направя малко тестване, тъй като клиентът изпълняваше SQL Server 2014.  Тук нещата станаха интересни.

Настройката

Ще създадем гореспоменатата таблица за тестване в RTM версията на SQL Server 2016, в базата данни WideWorldImporters и първоначално ще задам режима на съвместимост на 110:

ИЗПОЛЗВАЙТЕ [главен];ПРЕМЕСТВАНЕ НА БАЗА ДАННИ [WideWorldImporters]ОТ  ДИСК =N'C:\Backups\WideWorldImporters-Full.bak'WITH  FILE =1,ПРЕМЕСТВАНЕ N'WWI_Primary' КЪМ N'C:\Databases\IWporters\Woride\mWideers .mdf',MOVE N'WWI_UserData' КЪМ N'C:\Databases\WideWorldImporters\WideWorldImporters_UserData.ndf',MOVE N'WWI_Log' КЪМ N'C:\Databases\WideWorldImporters\WideWorldImporters\WideWorldf'mory_In,WIDEWorldf'mo_MOVE N'C:\Databases\WideWorldImporters\WideWorldImporters_InMemory_Data_1',NOUNLOAD, REPLACE, STATS =5;GO ALTER DATABASE [WideWorldImporters] SET COMPATIBILITY_LEVEL =110;WorldImporters_InMemory_Data_1',NOUNLOAD, REPLACE, STATS =5;GO ALTER DATABASE [WideWorldImporters] SET COMPATIBILITY_LEVEL =[Sawide;rGO] ] [int] NOT NULL, [CustomerID] [int] NOT NULL, [SalespersonPersonID] [int] NOT NULL, [PickedByPersonID] [int] NULL, [ContactPersonID] [int] NOT NULL, [BackorderOrderID] [int] [Дата на поръчката] [дата] NOT NULL, [ExpectedDeliveryDate] [date] NOT NULL, [CustomerPurchaseOrderNumber] [nvarchar](20) NULL, [IsUndersupplyBackordered] [bit] NOT NULL, [Коментари] [nvar ](max) NULL,[Инструкции за доставка] [nvarchar](max) NULL,[InternalComments] [nvarchar](max) NULL,[PickingCompletedWhen] [datetime2](7) NULL,[LastEditedBy] [int] NOT NULL,[LastEditedWhen ] [datetime2](7) НЕ НУЛЕВО, ОГРАНИЧЕНИЕ [PK_Sales_BigOrders] ПЪРВИЧЕН КЛЮСТ КОЛУСТРИРАН([OrderID] ASC) С (PAD_INDEX =ИЗКЛЮЧЕНО, STATISTICS_NORECOMPUTE =ИЗКЛЮЧЕНО, IGNORE_DUP_KEY =ИЗКЛЮЧЕНО =ИЗКЛЮЧЕНО, ALLCOWAGE_D) [ЗАКЛЮЧЕНО =OFF, ALLCOWAGE_D] ON [USERDATA] TEXTIMAGE_ON [USERDATA];

След това ще заредим около 24 милиона реда в BigOrders и ще създадем неклъстериран индекс на OrderDate.

ЗАДАДЕТЕ NOCOUNT ON; ДЕКЛАРИРАНЕ @Loops SMALLINT =0, @IDIncrement INT =75000; ДОКАТО @Loops <325 -- коригирайте това, за да увеличите или намалите броя на добавените редове BEGININSERT [Sales].[BigOrders]( [OrderID], [CustomerID], [SalespersonPersonID], [PickedByPersonID], [ContactPersonID], [Backor], [Дата на поръчка], [Очаквана дата на доставка], [CustomerPurchaseOrderNumber], [IsUndersupplyBackordered], [Коментари], [Инструкции за доставка], [Вътрешни коментари], [PickingCompletedWhen], [LastEditedBy], [LastEditedBy], [LastEditedBy], [LastEditedBy], [LastEditedBy], [ID]Incremented[OuderEdited [W], [ID]Incremented[OuderEdited] + ],[SalespersonPersonID],[PickedByPersonID],[ContactPersonID],[BackorderOrderID],[OrderDate],[ExpectedDeliveryDate],[CustomerPurchaseOrderNumber],[IsUndersupply,BackormentsP],[IsUndersupply,BackormentsP] [LastEditedBy],[LastEditedWhen]ОТ [Продажби].[Поръчки]; КОНТРОЛНА ТОЧКА; SET @Loops =@Loops + 1;SET @IDIncrement =@IDIncrement + 75000; КРАЙ СЪЗДАВАНЕ НА НЕКЛУСТРИРАН ИНДЕКС [NCI_BigOrders_OrderDate]НА [Продажби].[BigOrders] ([OrderDate], CustomerID);

Ако проверим хистограмата за неклъстерирания индекс, ще видим, че най-високата дата е 2016-05-31:

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


Статистика за NCI към Дата на поръчка

Ако правим заявка за дата извън тази, отбележете приблизителния брой редове:

ИЗБЕРЕТЕ CustomerID, OrderID, SalespersonPersonIDFROM [Sales].[BigOrders]WHERE [OrderDate] ='2016-06-01';


Планирайте при заявка за дата извън това, което е в хистограмата

Това е 1, защото стойността е извън хистограмата. И в този случай това е добре, защото в таблицата няма редове след 31 май 2016 г.  Но нека добавим някои и след това да изпълним отново същата заявка:

INSERT [Sales].[BigOrders]( [OrderID], [CustomerID], [SalespersonPersonID], [PickedByPersonID], [ContactPersonID], [BackorderOrderID], [OrderDate], [ExpectedDeliveryCumberDate],[ExpectedDeliveryUnderDate] ],[Коментари],[Инструкции за доставка],[InternalComments],[PickingCompletedWhen],[LastEditedBy],[LastEditedWhen])SELECT[OrderID] + 25000000,[CustomerID],[SalespersonPersonID],[PicktIDBer][PicktIDBy],[PicktIDBy] BackorderOrderID],'2016-06-01',[ExpectedDeliveryDate],[CustomerPurchaseOrderNumber],[IsUndersupplyBackordered],[Коментари],[Инструкции за доставка],[InternalComments],[PickingSapletedWhen],[PickingSapletedWhen],LastWhen]Edit .[Поръчки];ИЗБЕРЕТЕ ИД на клиента, ИД на поръчката, SalespersonPersonIDFROM [Sales].[BigOrders]WHERE [OrderDate] ='2016-06-01';


Планирайте след добавяне на редове след 31 май

Прогнозният брой редове все още е 1.  Но тук нещата стават интересни. Нека променим режима на съвместимост на 130, така че да използваме новия Cardinality Estimator и да видим какво ще се случи.

ИЗПОЛЗВАЙТЕ [главен]; ИЗБЕРЕТЕ ИЗПЪЛНЕНИЕ НА БАЗА ДАННИ [WideWorldImporters] SET COMPATIBILITY_LEVEL =130GO ИЗПОЛЗВАЙТЕ [WideWorldImporters]; ИЗБЕРЕТЕ ИД на клиента, идентификатор на поръчката, SalespersonPersonIDFROM [Sales].[BigOrders]DerDate-06 [BigOrders]WHERE; 


Планирайте след добавяне на редове за 1 юни, като използвате новия CE

Формата на нашия план е същата, но сега нашата оценка е 4898 реда. Новото СЕ третира ценностите извън историята по различен начин от старото СЕ. И така... имаме ли нужда дори от флаг за проследяване 2389?

Тестът – част I

За първия тест ще останем в режим на съвместимост 110 и ще преминем през това, което ще видим с 2389.  Когато използвате този флаг за проследяване, можете или да го активирате като параметър за стартиране в услугата SQL Server, или можете да използвате DBCC TRACEON, за да го активирате за целия екземпляр. Разберете, че във вашата производствена среда, ако използвате DBCC TRACEON за активиране на флага за проследяване, когато екземплярът се рестартира, флагът за проследяване няма да е в сила.

При активиран флаг за проследяване, статистиката трябва да бъде актуализирана три (3) пъти, преди оптимизаторът да я маркира като възходяща. Ще наложим четири актуализации за добра мярка и ще добавим още редове между всяка актуализация.

ИЗПОЛЗВАЙТЕ [главен];GO ALTER DATABASE [WideWorldImporters] SET COMPATIBILITY_LEVEL =110;GO DBCC TRACEON (2389, -1);GO ИЗПОЛЗВАЙТЕ [WideWorldImporters];GO UPDATE STATISTICS [Sales].[BigDaCIOrders].[BigCIOrders].[BigCIOrders].[BigCIOrders] INSERT [Sales].[BigOrders]( [OrderID],[CustomerID],[SalespersonPersonID],[PickedByPersonID],[ContactPersonID],[BackorderOrderID],[OrderDate],[ExpectedDeliveryDate],[ExpectedDeliveryDate],[ExpectedDeliveryDate],[ExpectedDeliveryDate],[ExpectedDeliveryDate],[ExpectedDeliveryDate],[ExpectedDeliveryDate],[ExpectedDeliveryDate],Npp] Коментари],[Инструкции за доставка],[Вътрешни коментари],[PickingCompletedWhen],[LastEditedBy],[LastEditedWhen])SELECT[OrderID] + 25100000,[CustomerID],[SalespersonPersonID],[PickedByPersonPersonID],[PickedByPersonID,DersonactID][DersonIDP] '2016-06-02',[ExpectedDeliveryDate],[CustomerPurchaseOrderNumber],[IsUndersupplyBackordered],[Коментари],[Инструкции за доставка],[InternalComments],[PickingCompletedWhen],[LastEdited]When],[LastEdited][FromEditedBy] ];ОТИДЕТЕ АКТУАЛИЗИРАНЕ НА СТАТИСТИКАТА [Продажби].[BigOrders] [NCI_BigOrders_OrderDate];GO INSERT [Sales].[BigOrders]( [OrderID],[CustomerID],[CustomerID]); ],[SalespersonPersonID],[PickedByPersonID],[ContactPersonID],[BackorderOrderID],[OrderDate],[ExpectedDeliveryDate],[CustomerPurchaseOrderNumber],[IsUndersupply,BackormentsP],[IsUndersupply,BackormentsP] [LastEditedBy][LastEditedWhen])SELECT[OrderID] + 25200000,[CustomerID],[SalespersonPersonID],[PickedByPersonID],[ContactPersonID],[BackorderOrderID],'2016-06-OrderID],'2016-06-OrderID],'2016-06-2016-06-2016-06-2016. [IsUndersupplyBackordered],[Коментари],[Инструкции за доставка],[Вътрешни коментари],[PickingCompletedWhen],[LastEditedBy],[LastEditedWhen]ОТ [Продажби].[Поръчки];ОТКЛЮЧЕТЕ АКТУАЛИЗИРАНЕ НА СТАТИСТИКА [Продажби].[NCIgOrders_Bi;gder] [ODCIgOrders_Bi;g] GO INSERT [Sales].[BigOrders]( [OrderID],[CustomerID],[SalespersonPersonID],[PickedByPersonID],[ContactPersonID],[BackorderOrderID],[OrderDate],[ExpectedDeliveryDate],[ExpectedDeliveryUstomer],[ExpectedDeliveryUstomer],[ExpectedDeliveryUstomerP],[PickedByPersonID],[ContactPersonID],[BackorderOrderID],[OrderDate],[ExpectedDeliveryDate],[ExpectedDeliveryOrderDate],[ExpectedDeliveryUstomerP],[ExpectedDeliveryUstomer] [Коментари], [Инструкции за доставка], [Вътрешни коментари], [Изборът е завършен, когато], [Последно редактирано от] , [Stasteditedwhen]) Изберете [OrderID] + 25300000, [CustomerId], [SalespersonPersonID], [PickedBypersonID], [ContactPersonID], [BackorderOdderId], '2016-06-04', [очаквандерийд], [CustomerPurchaseorderNumber], [isUnderSupplyBackededed ],[Коментари],[Инструкции за доставка],[Вътрешни коментари],[PickingCompletedWhen],[LastEditedBy],[LastEditedWhen]ОТ [Продажби].[Поръчки];ОТИДЕТЕ АКТУАЛИЗИРАНЕ НА СТАТИСТИКАТА [Продажби].[BigOrders] [NCI_BigDaOrders_Or]; 

Ако проверим отново статистиката и използваме флага за проследяване 2388, за да покажем допълнителна информация, виждаме, че статистиката вече е маркирана като Възходяща:

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


NCI на OrderDate, отбелязан като ASC

Ако направим заявка за бъдеща дата, когато статистиката е напълно актуална, виждаме, че тя все още изчислява 1 ред:

ИЗБЕРЕТЕ CustomerID, OrderID, SalespersonPersonIDFROM [Sales].[BigOrders]WHERE [OrderDate] ='2016-06-05';


Планирайте след активиране на TF 2389, но без редове извън хистограмата

Сега ще добавим редове за 5 юни и ще изпълним отново същата заявка:

INSERT [Sales].[BigOrders]( [OrderID], [CustomerID], [SalespersonPersonID], [PickedByPersonID], [ContactPersonID], [BackorderOrderID], [OrderDate], [ExpectedDeliveryCumberDate],[ExpectedDeliveryUnderDate] ],[Коментари],[Инструкции за доставка],[Вътрешни коментари],[PickingCompletedWhen],[LastEditedBy],[LastEditedWhen])SELECT[OrderID] + 25400000,[CustomerID],[SalespersonPersonID],[PicktIDBer][PicktIDBy] BackorderOrderID],'2016-06-05',[ExpectedDeliveryDate],[CustomerPurchaseOrderNumber],[IsUndersupplyBackordered],[Коментари],[Инструкции за доставка],[InternalComments],[PickingSapletedWhen],[PickingSapletedWhen],[LastWhen]Edit .[Поръчки];ИЗБЕРЕТЕ идентификатор на клиента, идентификатор на поръчката, SalespersonPersonIDFROM [Sales].[BigOrders]WHERE [OrderDate] ='2016-06-05';


План след активиране на TF 2389, добавени 70K+ реда извън хистограмата

Нашата оценка вече не е 1, а 22 595. Сега, само за забавление, нека деактивираме флага за проследяване и да видим каква е оценката (ще изчистя кеша на процедурите, тъй като деактивирането на флага за проследяване няма да повлияе на това, което в момента е в кеша).

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


Планът след TF 2389 е *деактивиран*, 70K+ реда добавени след това хистограма

Този път отново получавам оценка от 1 ред. Въпреки че статистиката е брандирана като възходяща, ако флагът за проследяване 2389 не е активиран, той изчислява само 1 ред, когато потърсите стойност извън хистограмата.

Ние демонстрирахме, че флагът за проследяване 2389 прави това, което очакваме – това, което винаги е правил – когато използваме стария оценител на кардиналността. Сега да видим какво ще се случи с новия.

Тестът – част II

За да бъда изчерпателен, ще нулирам всичко. Ще създам базата данни отново, ще задам режима на съвместимост на 130, ще заредя първоначално данните, след това ще включа флага за проследяване 2389 и ще заредя три набора данни с актуализации на статистиката между тях.

ИЗПОЛЗВАЙТЕ [главен]; ОТИВЯВАЙТЕ ВЪЗСТАНОВЯВАНЕ НА БАЗА ДАННИ [WideWorldImporters]ОТ  ДИСК =N'C:\Backups\WideWorldImporters-Full.bak'WITH  FILE =1,ПРЕМЕСТИ N'WWI_Primary' КЪМ N'C:\WorldImporters\Wideers WideWorldImporters.mdf',MOVE N'WWI_UserData' КЪМ N'C:\Databases\WideWorldImporters\WideWorldImporters_UserData.ndf',MOVE N'WWI_Log' КЪМ N'C:\Databases\WideWorldImporters'N'C:\Databases\WideWorldImporters'MOVE_Databases\WideWorldImporters'Importers.ndf' КЪМ N'C:\Databases\WideWorldImporters\WideWorldImporters_InMemory_Data_1',NOUNLOAD, REPLACE, STATS =5;GO ИЗПОЛЗВАЙТЕ [главен];GO ALTER DATABASE [WideWorldImporters] SET COMPATIBILITY_LEVATES [COPATIBILITY_LEVATE] .[BigOrders]([OrderID] [int] NOT NULL, [CustomerID] [int] NOT NULL, [SalespersonPersonID] [int] НЕ NULL, [PickedByPersonID] [int] NULL, [ContactPersonID] [int] NOT NULL, [INT] NOT NULL, [PickedByPersonID] [int] BackorderOrderID] [int] NULL,[OrderDate] [дата] NOT NULL,[ExpectedDeliveryDate] [дата] NOT NULL,[CustomerPurchaseOrderNumber] [nvarchar](20) NULL,[IsUndersupplyBackordered] [NCoordered] [NCoordered] mments] [nvarchar](max) NULL,[Инструкции за доставка] [nvarchar](max) NULL,[InternalComments] [nvarchar](max) NULL,[PickingCompletedWhen] [datetime2](7) NULL,[LastEditedBy] [int] НЕ NULL,[LastEditedWhen] [datetime2](7) NOT NULL,CONSTRAINT [PK_Sales_BigOrders] ПЪРВИЧЕН КЛУСТЕР КЛУСТРИРАН([OrderID] ASC)WITH (PAD_INDEX =OFF, STATISTICS_NORECOMPUTE =OFF, IGNORE_DUP_CONS. [USERDATA]) ON [USERDATA] TEXTIMAGE_ON [USERDATA];GO SET NOCOUNT ON; ДЕКЛАРИРАНЕ @Loops SMALLINT =0; ДЕКЛАРИРАНЕ @IDIncrement INT =75000; ДОКАТО @Loops <325 -- коригирайте това, за да увеличите или намалите броя на добавените редове BEGININSERT [Sales].[BigOrders]( [OrderID], [CustomerID], [SalespersonPersonID], [PickedByPersonID], [ContactPersonID], [Backor], [Дата на поръчка], [Очаквана дата на доставка], [CustomerPurchaseOrderNumber], [IsUndersupplyBackordered], [Коментари], [Инструкции за доставка], [Вътрешни коментари], [PickingCompletedWhen], [LastEditedBy], [LastEditedBy], [LastEditedBy], [LastEditedBy], [LastEditedBy], [ID]Incremented[OuderEdited [W], [ID]Incremented[OuderEdited] + ],[SalespersonPersonID],[PickedByPersonID],[ContactPersonID],[BackorderOrderID],[OrderDate],[ExpectedDeliveryDate],[CustomerPurchaseOrderNumber],[IsUndersupply,BackormentsP],[IsUndersupply,BackormentsP] [LastEditedBy],[LastEditedWhen]ОТ [Продажби].[Поръчки]; КОНТРОЛНА ТОЧКА; SET @Loops =@Loops + 1;SET @IDIncrement =@IDIncrement + 75000; КРАЙ СЪЗДАВАНЕ НА НЕКЛУСТЕРИРАН ИНДЕКС [NCI_BigOrders_OrderDate]ВЪВ [Продажби].[BigOrders] ([OrderDate], CustomerID);GO INSERT] [SalesOrder].[ig] ( [OrderID],[CustomerID],[SalespersonPersonID],[PickedByPersonID],[ContactPersonID],[BackorderOrderID],[OrderDate],[ExpectedDeliveryDate],[CustomerPurchaseOrderNumbersUmber],[CustomerPurchaseOrderNumbersUmber],[Decome] Вътрешни коментари],[PickingCompletedWhen],[LastEditedBy],[LastEditedWhen])SELECT[OrderID] + 25000000,[CustomerID],[SalespersonPersonID],[PickedByPersonID],[ContactPersonID],-0rBackID],-0rBack1,0rBack1 [ExpectedDeliveryDate],[CustomerPurchaseOrderNumber],[IsUndersupplyBackordered],[Коментари],[Инструкции за доставка],[Вътрешни коментари],[PickingCompletedWhen],[LastEditedBy],[LastEditedWhen]FROM 2CC [Sales].[GODCC 3] -1);ОТИДЕТЕ АКТУАЛИЗИРАНЕ НА СТАТИСТИКАТА [Продажби].[BigOrders] [NCI_BigOrders_OrderDate];GO INSERT [Sales].[BigOrders]( [OrderID],[CustomerID], [Продавач] PersonID],[PickedByPersonID],[ContactPersonID],[BackorderOrderID],[OrderDate],[ExpectedDeliveryDate],[CustomerPurchaseOrderNumber],[IsUndersupplyBackordered],[Comments]Instructions[Edit],[Comments]Instructions],[Comments]Instructions[Edit] , [Stastedited when]) изберете [orderId] + 25100000, [customerid], [salespersonpersonid], [pickedbypersonid], [contactpersonid], [backorderorderId], '2016-06-02', [очаквандерийд], [CustomerPurchaseOrderNumber], [isUnderSupplyBackedededdate ],[Коментари],[Инструкции за доставка],[Вътрешни коментари],[PickingCompletedWhen],[LastEditedBy],[LastEditedWhen]ОТ [Продажби].[Поръчки];ОТИДЕТЕ АКТУАЛИЗИРАНЕ НА СТАТИСТИКАТА [Продажби].[BigOrders] [NCI_BigSERTOrders_Or]; [Продажби].[BigOrders]( [OrderID],[CustomerID],[SalespersonPersonID],[PickedByPersonID],[ContactPersonID],[BackorderOrderID],[OrderDate],[ExpectedDeliveryDate],[ExpectedDeliveryDate],[CudermentDeliveryDate],[CuderDeliveryDate],[CuderSuderments[N]CuderSumber[N],[CuderMerson] ],[Инструкции за доставка],[Вътрешни коментари],[Изборът е завършенКогато],[LastEditedBy],[LastEditedW hen])SELECT[OrderID] + 25200000,[CustomerID],[SalespersonPersonID],[PickedByPersonID],[ContactPersonID],[BackorderOrderID],'2016-06-03',[ExpectedDeliveryCeliveryUnderSuderly],[ExpectedDeliveryUnderSuderIpp] [Коментари],[Инструкции за доставка],[Вътрешни коментари],[PickingCompletedWhen],[LastEditedBy],[LastEditedWhen]ОТ [Продажби].[Поръчки];ОТИДЕТЕ АКТУАЛИЗИРАНЕ НА СТАТИСТИКАТА [Продажби].[BigOrders] [NCI_BigOrders] [NCI_BigOrders]Sales_Order; ].[BigOrders]( [OrderID],[CustomerID],[SalespersonPersonID],[PickedByPersonID],[ContactPersonID],[BackorderOrderID],[OrderDate],[ExpectedDeliveryDate],[CustomerSuredPerson[Com],[CustomersouredPurments[Uck] [Инструкции за доставка],[InternalComments],[PickingCompletedWhen],[LastEditedBy],[LastEditedWhen])SELECT[OrderID] + 25300000,[CustomerID],[SalespersonPersonID],[PickedByPersonID],[PickedByPersonID],[PickedByPersonID],[PickedByPersonID],[PickedByPersonID],[PickedByPersonID],[PickedByPersonID],[Derson'2],[Derson'2] 06-04',[Очаквана дата на доставка],[CustomerPurchaseOrderNumber],[IsUndersupplyBackordered],[Коментари],[Инструкции за доставка],[InternalCo mments],[PickingCompletedWhen],[LastEditedBy],[LastEditedWhen]ОТ [Продажби].[Поръчки];ОТИДЕТЕ АКТУАЛИЗИРАНЕ НА СТАТИСТИКАТА [Продажби].[BigOrders] [NCI_BigOrders_OrderDate];

Добре, така че нашите данни са напълно заредени. Ако проверим отново статистиката и използваме флага за проследяване 2388, за да покажем допълнителна информация, ще видим, че статистиката отново е маркирана като възходяща:

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


Статистика за NCI OrderDate е маркирана като ASC с TF 2389 и режим на съвместимост 130

Добре, нека да потърсим отново 5 юни:

ИЗБЕРЕТЕ CustomerID, OrderID, SalespersonPersonIDFROM [Sales].[BigOrders]WHERE [OrderDate] ='2016-06-05';


Планирайте с нов CE, без редове извън това, което е в хистограмата

Нашата оценка е 4922. Не точно това, което беше в първия ни тест, но определено не 1.  Сега ще добавим няколко реда за 5 юни и ще направим повторна заявка:

INSERT [Sales].[BigOrders]( [OrderID], [CustomerID], [SalespersonPersonID], [PickedByPersonID], [ContactPersonID], [BackorderOrderID], [OrderDate], [ExpectedDeliveryCumberDate],[ExpectedDeliveryUnderDate] ],[Коментари],[Инструкции за доставка],[Вътрешни коментари],[PickingCompletedWhen],[LastEditedBy],[LastEditedWhen])SELECT[OrderID] + 25400000,[CustomerID],[SalespersonPersonID],[PicktIDBer][PicktIDBy] BackorderOrderID],'2016-06-05',[ExpectedDeliveryDate],[CustomerPurchaseOrderNumber],[IsUndersupplyBackordered],[Коментари],[Инструкции за доставка],[InternalComments],[PickingSapletedWhen],[PickingSapletedWhen],[LastWhen]Edit .[Поръчки];ИЗБЕРЕТЕ идентификатор на клиента, идентификатор на поръчката, SalespersonPersonIDFROM [Sales].[BigOrders]WHERE [OrderDate] ='2016-06-05';


Планирайте с нов CE, със 70K+ реда извън това, което е в хистограмата

Оценката е същата. И сега, какво ще стане, ако изключим флаг за проследяване 2389?

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


Планирайте с нов CE, но TF 2389 НЕ е активиран, с 70K+ редове извън това, което е в хистограма

Оценката се промени леко, до 4930, но се промени. Това ми казва, че флагът за проследяване 2389 има известен ефект върху оценката, но колко не е известно.

Тестът – част III

Проведох един последен тест, където възстанових базата данни, зададох режима на съвместимост на 130, заредих всички данни отново, актуализирах статистиката няколко пъти, но НЕ активирах флаг за проследяване 2389.  Кодът е същият като част II, с изключение на използването DBCC TRACEON за активиране на 2389.  Когато направих заявка за 5 юни, както преди, така и след добавяне на данните, прогнозният брой редове беше 4920.

Какво означава?

За да обобщим, когато използвате режим на съвместимост 110 или по-нисък, флагът за проследяване 2389 работи както винаги. Но когато използвате режим на съвместимост 120 или по-висок, и по този начин новият CE, оценките са не едни и същи в сравнение със стария CE и в този конкретен случай не са толкова различни независимо дали се използва флагът за проследяване или не.

И така, какво трябва да направите? Тествайте, както винаги. Не намерих нищо документирано в MSDN, което да гласи, че флагът за проследяване 2389 не се поддържа с режим на съвместимост 120 и по-висок, нито съм намерил нещо, което да документира промяна в поведението. Намирам за много интересно, че оценките са различни (в този случай много по-ниски) с новия CE. Това потенциално може да бъде проблем, но има множество фактори, които играят, когато става въпрос за оценки, и това беше много проста заявка (една таблица, един предикат). В този случай оценката е далеч (4920 реда срещу 22 595 реда за датата 5 юни).

Ако изпълня отново заявката за дата, която има същия брой редове, е в хистограмата получавам подобен план, но той работи паралелно:

ИЗБЕРЕТЕ CustomerID, OrderID, SalespersonPersonIDFROM [Sales].[BigOrders]WHERE [OrderDate] ='2016-06-02';


Планирайте заявка, която използва дата в хистограмата (нова CE, без TF)

Оценката също е по-точна (68 318). В този случай планът не се променя значително, но цената очевидно е по-висока. В даден момент, в зависимост от броя на редовете, които ще бъдат върнати, това може да насочи към сканиране на таблица.

Най-доброто ръководство за момента, ако използвате 2014 или по-нова версия и режим на съвместимост 120 или по-висок, и имате водещи колони в статистическите данни, които са нарастващи, е да тествате. Ако установите, че новият Cardinality Estimator не предоставя толкова добра оценка като стария CE, тогава бих препоръчал да подадете елемент на Connect, така че екипът на продукта да е наясно с него. Винаги има еднократни и уникални случаи, но ако много клиенти (четете:ВИЕ) постоянно намират едно и също поведение – и то не е идеално – тогава е важно да уведомите екипа за разработка за това.

Това е друг важен елемент, който трябва да имате предвид, когато надграждате до 2014 или 2016 г. – и напомняне да не пренебрегнете тестването си (и, между другото, Query Store ще бъде изключително полезен тук с 2016 г.). Приятели.


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Научете за конкатенацията в SQL с примери

  2. Анонимизирайте детайлите на плана си по естествен начин в Plan Explorer

  3. Добавяне на още хранилища за данни към Microsoft Power BI

  4. Проучване на грешка ORA 02063 DG4ODBC

  5. Конфигуриране на разрешения за ScaleGrid в AWS с помощта на шаблон за IAM политика