Mamy dużą partycjonowaną bazę danych SQL Server wykorzystującą statystyki przyrostowe. Wszystkie indeksy są podzielone na partycje. Kiedy próbujemy odbudować partycję online według partycji, wszystkie statystyki znikają po odbudowaniu indeksu.
Poniżej znajduje się skrypt do replikacji problemu w SQL Server 2014 z bazą danych AdventureWorks2014.
--Example against AdventureWorks2014 Database
CREATE PARTITION FUNCTION TransactionRangePF1 (DATETIME)
AS RANGE RIGHT FOR VALUES
(
'20130501', '20130601', '20130701', '20130801',
'20130901', '20131001', '20131101', '20131201',
'20140101', '20140201', '20140301'
);
GO
CREATE PARTITION SCHEME TransactionsPS1 AS PARTITION TransactionRangePF1 TO
(
[PRIMARY], [PRIMARY], [PRIMARY], [PRIMARY], [PRIMARY],
[PRIMARY], [PRIMARY], [PRIMARY], [PRIMARY], [PRIMARY],
[PRIMARY], [PRIMARY], [PRIMARY]
);
GO
CREATE TABLE dbo.TransactionHistory
(
TransactionID INT NOT NULL, -- not bothering with IDENTITY here
ProductID INT NOT NULL,
ReferenceOrderID INT NOT NULL,
ReferenceOrderLineID INT NOT NULL DEFAULT (0),
TransactionDate DATETIME NOT NULL DEFAULT (GETDATE()),
TransactionType NCHAR(1) NOT NULL,
Quantity INT NOT NULL,
ActualCost MONEY NOT NULL,
ModifiedDate DATETIME NOT NULL DEFAULT (GETDATE()),
CONSTRAINT CK_TransactionType
CHECK (UPPER(TransactionType) IN (N'W', N'S', N'P'))
)
ON TransactionsPS1 (TransactionDate);
INSERT INTO dbo.TransactionHistory
SELECT * FROM Production.TransactionHistory
-- SELECT * FROM sys.partitions
-- WHERE object_id = OBJECT_ID('dbo.TransactionHistory');
CREATE NONCLUSTERED INDEX IDX_ProductId ON dbo.TransactionHistory (ProductId)
WITH (DATA_COMPRESSION = ROW, STATISTICS_INCREMENTAL=ON)
ON TransactionsPS1 (TransactionDate)
DBCC SHOW_STATISTICS('dbo.TransactionHistory', IDX_ProductId);
PRINT 'Stats are avialable'
ALTER INDEX [IDX_ProductId] ON [dbo].[TransactionHistory] REBUILD
PARTITION = 9 WITH (ONLINE = ON , DATA_COMPRESSION = ROW)
PRINT 'After online index rebuild by partition stats are now gone'
DBCC SHOW_STATISTICS('dbo.TransactionHistory', IDX_ProductId);
PRINT 'Rebuild the stats with a rebuild for all paritions (this works)'
ALTER INDEX [IDX_ProductId] ON [dbo].[TransactionHistory] REBUILD
PARTITION = ALL WITH (ONLINE = ON , DATA_COMPRESSION = ROW,
STATISTICS_INCREMENTAL = ON)
PRINT 'Stats are back'
DBCC SHOW_STATISTICS('dbo.TransactionHistory', IDX_ProductId);
PRINT 'Works correctly for an offline rebuild by partition'
ALTER INDEX [IDX_ProductId] ON [dbo].[TransactionHistory] REBUILD
PARTITION = 9 WITH (ONLINE = OFF , DATA_COMPRESSION = ROW)
--stats still there
DBCC SHOW_STATISTICS('dbo.TransactionHistory', IDX_ProductId);
ALTER INDEX [IDX_ProductId] ON [dbo].[TransactionHistory] REBUILD
PARTITION = 9 WITH (ONLINE = ON , DATA_COMPRESSION = ROW)
DBCC SHOW_STATISTICS('dbo.TransactionHistory', IDX_ProductId);
PRINT' stats are gone!!!!!!'
Jak pokazano, nie możemy odbudować indeksów według partycji online bez utraty wszystkich statystyk dla indeksu. Jest to dla nas poważny problem z utrzymaniem. Wygląda na to, że opcja przyrostowa statystyki musi być częścią składni przebudowy pojedynczego indeksu lub opcja online musi odpowiednio ją obsługiwać, tak jak robi to opcja offline.
Daj mi znać, jeśli coś mi umknie?
Aktualizacje:
O ile potrzebujemy statystyk przyrostowych: dzielimy się na wewnętrzny identyfikator klienta, a nie na datę. Kiedy więc zostaje wprowadzony nowy klient (duże obciążenie danych), możemy po prostu zaktualizować statystyki partycji i szybko uniknąć tworzenia brzydkich planów dla tego nowego klienta. Myślę, że napiszę to do Microsoft jako błąd i zobaczę, co mają do powiedzenia, i zastosuję rozwiązanie polegające na ponownym próbkowaniu statystyk dla tej partycji.
Połącz raport o błędzie:
Statystyki znikają po odbudowaniu indeksu online ze statystykami przyrostowymi
Aktualizacja: Microsoft potwierdził, że jest to błąd.
Odpowiedzi:
Nie wiem, czy jest to błąd, per se , ale to z pewnością interesujące zjawisko. Przebudowy partycji online są nowe w SQL Server 2014, więc mogą być pewne elementy wewnętrzne do posortowania z tym.
Oto moje najlepsze wytłumaczenie dla ciebie. Przyrostowe statystyki absolutnie wymagają, aby wszystkie partycje były próbkowane w tym samym tempie, aby podczas łączenia stron statystyk silnik miał pewność, że rozkład próbkowania jest porównywalny.
REBUILD
koniecznie próbkuje dane ze 100% częstotliwością próbkowania. Nie ma gwarancji, że 100% częstotliwości próbkowania na partycji 9 zawsze będzie dokładną częstotliwością próbkowania dla pozostałych partycji. Z tego powodu wygląda na to, że silnik nie może scalić próbek i kończy się pustą kroplą statystyk. Jednak obiekt statystyk wciąż tam jest:Kroplę można wypełnić na wiele sposobów:
UPDATE STATISTICS dbo.TransactionHistory (IDX_ProductId) WITH RESAMPLE;
lub
UPDATE STATISTICS dbo.TransactionHistory (IDX_ProductId) WITH RESAMPLE ON PARTITIONS (9);
lub możesz poczekać na aktualizację AutoStats przy pierwszej kompilacji planu zapytań przy użyciu tego obiektu:
Powiedziawszy to wszystko, ten oświecający post Erin Stellato podkreśla to, co zostało uznane za poważny brak statystyk przyrostowych. Dane na poziomie partycji nie są wykorzystywane przez optymalizator do generowania planu zapytań, co zmniejsza przypuszczalną korzyść statystyki przyrostowej. Jaka jest zatem obecna korzyść ze statystyki przyrostowej? Twierdzę, że ich podstawową użytecznością jest możliwość bardziej spójnego próbkowania dużych tabel z wyższą częstotliwością niż w przypadku tradycyjnych statystyk.
Korzystając z Twojego przykładu, oto jak to wygląda:
Aktualizacja statystyk fullscan dotycząca statystyki przyrostowej kosztuje 131 ms. Aktualizacja statystyki fullscan statystyki nieprzystosowanej do partycji kosztuje 66 ms. Nieprzystosowana statystyka jest wolniejsza, najprawdopodobniej z powodu ogólnych kosztów związanych z łączeniem poszczególnych stron statystyki z powrotem do głównego histogramu. Jednak za pomocą obiektu statystycznego wyrównanego do partycji możemy zaktualizować jedną partycję i scalić ją z powrotem w główny obiekt blob histogramu w 5 ms. W tym momencie administrator z przyrostową statystyką musi podjąć decyzję. Mogą skrócić całkowity czas utrzymywania statystyk, aktualizując tylko partycje, lub tradycyjnie musiałyby być aktualizowane, lub mogą eksperymentować z wyższymi częstotliwościami próbkowania, aby potencjalnie uzyskać więcej wierszy próbkowanych w tym samym okresie czasu, co poprzednie okresy konserwacji. Ten pierwszy pozwala odetchnąć w oknie konserwacji, ten drugi może przesunąć statystyki na bardzo dużym stole do miejsca, w którym zapytania uzyskują lepsze plany w oparciu o dokładniejsze statystyki. Nie stanowi to gwarancji, a przebieg może się różnić.
Czytelnik widzi, że 66 ms nie jest bolesnym czasem aktualizacji statystyk w tej tabeli, więc próbowałem skonfigurować test na zestawie danych wymiany stosów. W ostatnim zrzucie, który pobrałem, jest 6 418 608 postów (z wyłączeniem postów StackOverflow i wszystkich postów z 2012 r. - z mojej strony błąd danych).
Dane podzieliłem na partycje,
[CreationDate]
ponieważ ... demo.Oto niektóre czasy dla niektórych dość standardowych scenariuszy (100% - przebudowa indeksu, domyślnie - automatyczna aktualizacja statystyk lub
UPDATE STATISTICS
bez określonej częstotliwości próbkowania:Powiedzmy, że jesteśmy bardziej wyrafinowani niż te domyślne scenariusze i zdecydowaliśmy, że 10% częstotliwość próbkowania jest minimalną częstotliwością, która powinna zapewnić nam potrzebne plany, przy jednoczesnym utrzymaniu rozsądnego czasu konserwacji.
Jak dotąd nie ma wyraźnych korzyści z posiadania przyrostowej statystyki. Jeśli jednak wykorzystamy nieudokumentowane
sys.dm_db_stats_properties_internal()
DMV (poniżej), możesz uzyskać wgląd w to, które partycje chcesz zaktualizować. Załóżmy, że wprowadziliśmy zmiany w danych na partycji 3 i chcemy mieć pewność, że statystyki będą aktualne dla zapytań przychodzących. Oto nasze opcje:Oto, gdzie musimy podjąć decyzję. Czy przyjmujemy zwycięstwo 63 ms. aktualizacja statystyk oparta na partycjach, czy też zwiększamy częstotliwość próbkowania jeszcze wyżej? Powiedzmy, że jesteśmy gotowi przyjąć początkowe trafienie próbkowania na poziomie 50% na podstawie przyrostowej statystyki:
Jesteśmy w stanie próbkować o wiele więcej danych, być może konfigurując optymalizator, aby lepiej odgadywać nasze dane (nawet jeśli nie używa to jeszcze statystyk na poziomie partycji) i jesteśmy w stanie zrobić to szybciej, gdy już mamy statystyki przyrostowe.
Jeszcze jedna fajna rzecz do wymyślenia. Co z aktualizacjami statystyk synchronicznych? Czy 50% częstotliwość próbkowania jest zachowana nawet po uruchomieniu autostatów?
Usunąłem dane z partycji 3 i uruchomiłem zapytanie w CreationDate i sprawdziłem, a następnie sprawdziłem stawki za pomocą tego samego zapytania poniżej. Częstotliwość próbkowania 50% została zachowana.
Krótko mówiąc: statystyki przyrostowe mogą być użytecznym narzędziem przy odpowiedniej ilości przemyślenia i początkowej konfiguracji. Musisz jednak znać problem, który próbujesz rozwiązać, a następnie odpowiednio go rozwiązać. Jeśli otrzymujesz złych oszacowań liczności, to może być w stanie uzyskać lepsze plany strategiczne z częstotliwością próbkowania i niektórych zainwestowanego interwencji. Otrzymujesz jednak tylko niewielką część korzyści, ponieważ użyty histogram to pojedyncza, scalona strona statystyk, a nie informacje na poziomie partycji. Jeśli odczuwasz ból w oknie konserwacji, być może pomocne mogą być statystyki przyrostowe, ale prawdopodobnie będzie to wymagało skonfigurowania interwencji konserwacyjnej w trybie szybkiego dotyku. Bez względu,:
Mam nadzieję że to pomoże
źródło