Nicht sicher , ob es ein Fehler ist, per se , aber es ist auf jeden Fall ein interessantes Ereignis. Online-Neuerstellungen von Partitionen sind neu in SQL Server 2014, daher müssen möglicherweise einige Interna hiermit sortiert werden.
Hier ist meine beste Erklärung für dich. Inkrementelle Statistiken erfordern unbedingt, dass alle Partitionen mit der gleichen Rate abgetastet werden, damit beim Zusammenführen der Statistikseiten durch die Engine sichergestellt werden kann, dass die abgetastete Verteilung vergleichbar ist. REBUILD
Daten müssen unbedingt mit einer Abtastrate von 100% abgetastet werden. Es gibt keine Garantie dafür, dass die 100% -Abtastrate auf Partition 9 immer die genaue Abtastrate der übrigen Partitionen ist. Aus diesem Grund sieht es so aus, als ob die Engine die Samples nicht zusammenführen kann und Sie einen leeren Statistik-Blob erhalten. Das Statistikobjekt ist jedoch noch vorhanden:
select
check_time = sysdatetime(),
schema_name = sh.name,
table_name = t.name,
stat_name = s.name,
index_name = i.name,
stats_column = index_col(quotename(sh.name)+'.'+quotename(t.name),s.stats_id,1),
s.stats_id,
s.has_filter,
s.is_incremental,
s.auto_created,
sp.last_updated,
sp.rows,
sp.rows_sampled,
sp.unfiltered_rows,
modification_counter
from sys.stats s
join sys.tables t
on s.object_id = t.object_id
join sys.schemas sh
on t.schema_id = sh.schema_id
left join sys.indexes i
on s.object_id = i.object_id
and s.name = i.name
outer apply sys.dm_db_stats_properties(s.object_id, s.stats_id) sp
where t.name = 'TransactionHistory' and sh.name = 'dbo'
Sie können den Blob mit einer beliebigen Anzahl von Mitteln füllen:
UPDATE STATISTICS dbo.TransactionHistory (IDX_ProductId) WITH RESAMPLE;
oder
UPDATE STATISTICS dbo.TransactionHistory (IDX_ProductId) WITH RESAMPLE ON PARTITIONS (9);
Sie können auch warten, bis AutoStats bei der ersten Kompilierung eines Abfrageplans mit diesem Objekt aktualisiert wurde:
-- look at my creative query
select *
from dbo.TransactionHistory
where TransactionDate = '20140101';
Having said all das, dieser erhellende Beitrag von Erin Stellato Höhepunkten , was als Hauptmangel von inkrementalen Statistiken wahrgenommen werden muss kommen. Ihre Daten auf Partitionsebene werden vom Optimierer bei der Abfrageplanerstellung nicht verwendet, wodurch der vermutete Nutzen inkrementeller Statistiken verringert wird. Was ist der aktuelle Nutzen von inkrementellen Statistiken? Ich würde behaupten, dass ihr primärer Nutzen darin besteht, große Tabellen mit einer höheren Rate konsistenter zu testen als mit herkömmlichen Statistiken.
Anhand Ihres Beispiels sehen die Dinge folgendermaßen aus:
set statistics time on;
update statistics dbo.TransactionHistory(IDX_ProductId)
with fullscan;
--SQL Server Execution Times:
-- CPU time = 94 ms, elapsed time = 131 ms.
update statistics dbo.TransactionHistory(IDX_ProductId)
with resample on partitions(2);
--SQL Server Execution Times:
-- CPU time = 0 ms, elapsed time = 5 ms.
drop index IDX_ProductId On dbo.TransactionHistory;
CREATE NONCLUSTERED INDEX IDX_ProductId ON dbo.TransactionHistory (ProductId)
WITH (DATA_COMPRESSION = ROW)
ON [PRIMARY]
update statistics dbo.TransactionHistory(IDX_ProductId)
with fullscan;
--SQL Server Execution Times:
-- CPU time = 76 ms, elapsed time = 66 ms.
Ein Fullscan-Statistik-Update der inkrementellen Statistik kostet 131 ms. Ein Fullscan-Statistik-Update der nicht partitionierten Statistik kostet 66 ms. Die nicht ausgerichtete Statistik ist mit größter Wahrscheinlichkeit langsamer, da durch das Zusammenführen der einzelnen Statistikseiten mit dem Haupthistogramm ein Mehraufwand entsteht. Mit dem partitionierten Statistikobjekt können wir jedoch eine Partition aktualisieren und sie in 5 ms wieder mit dem Haupthistogramm-Blob zusammenführen. An diesem Punkt steht der Administrator mit der inkrementellen Statistik vor einer Entscheidung. Sie können die Gesamtwartungszeit für Statistiken verkürzen, indem sie normalerweise nur Partitionen aktualisieren, die aktualisiert werden müssen, oder sie können mit höheren Abtastraten experimentieren, sodass möglicherweise mehr Zeilen im gleichen Zeitraum wie in ihrem vorherigen Wartungszeitraum abgetastet werden. Ersteres ermöglicht eine Atempause im Wartungsfenster, letzteres kann Statistiken auf einem sehr großen Tisch an einen Ort verschieben, an dem Abfragen bessere Pläne auf der Grundlage genauerer Statistiken erhalten. Dies ist keine Garantie und Ihr Kilometerstand kann variieren.
Der Leser kann erkennen, dass 66 ms keine schmerzhafte Statistikaktualisierungszeit für diese Tabelle darstellt. Daher habe ich versucht, einen Test für den Stapelaustauschdatensatz einzurichten. Es gibt 6.418.608 Posts (ohne StackOverflow-Posts und alle Posts aus 2012 - ein Datenfehler meinerseits) in dem kürzlich von mir heruntergeladenen Dump.
Ich habe die Daten aufgeteilt nach [CreationDate]
weil ... Demo.
Hier sind einige Zeitangaben für einige hübsche Standardszenarien (100% - Indexwiederherstellung, Standardeinstellung - automatische Aktualisierung der Statistiken oder UPDATE STATISTICS
ohne festgelegte Abtastrate):
- Nicht inkrementelle Statistik mit Fullscan erstellen: CPU-Zeit = 23500 ms, verstrichene Zeit = 22521 ms.
- Inkrementelle Statistik mit Vollabtastung erstellen: CPU-Zeit = 20406 ms, verstrichene Zeit = 15413 ms.
- Aktualisieren Sie die nicht inkrementelle Statistik mit der Standardabtastrate: CPU-Zeit = 406 ms, verstrichene Zeit = 408 ms.
- Inkrementelle Statistik mit Standardabtastrate aktualisieren: CPU-Zeit = 453 ms, verstrichene Zeit = 507 ms.
Nehmen wir an, wir sind ausgefeilter als diese Standardszenarien und haben entschieden, dass eine Abtastrate von 10% die Mindestrate ist, mit der wir die erforderlichen Pläne erstellen und gleichzeitig die Wartungszeit auf einen angemessenen Zeitraum beschränken können.
- Aktualisieren Sie die nicht inkrementelle Statistik mit Beispiel 10 Prozent: CPU-Zeit = 2344 ms, verstrichene Zeit = 2441 ms.
- Inkrementelle Statistik mit Beispiel 10 Prozent aktualisieren: CPU-Zeit = 2344 ms, verstrichene Zeit = 2388 ms.
Bisher gibt es keinen klaren Vorteil einer inkrementellen Statistik. Wenn wir jedoch die undokumentierte sys.dm_db_stats_properties_internal()
DMV (unten) nutzen, können Sie einen Einblick in die Partitionen erhalten, die Sie aktualisieren möchten. Nehmen wir an, wir haben Änderungen an den Daten in Partition 3 vorgenommen und möchten sicherstellen, dass die Statistiken für eingehende Abfragen aktuell sind. Hier sind unsere Optionen:
- Standardmäßig nicht inkrementelles Update (auch das Standardverhalten von Auto-Stats Update): 408 ms.
- Aktualisierung nicht inkrementell bei 10%: 2441 ms.
- Inkrementelle Statistik aktualisieren, Partition 3 mit Resample (10% - unsere definierte Abtastrate): CPU-Zeit = 63 ms, verstrichene Zeit = 63 ms.
Hier müssen wir eine Entscheidung treffen. Nehmen wir den Gewinn einer 63 ms. Partitionsbasierte Aktualisierung der Statistiken, oder erhöhen wir die Samplerate noch weiter? Nehmen wir an, wir sind bereit, den ersten Stichprobenerfolg mit einer inkrementellen Statistik bei 50% anzunehmen:
- Aktualisierung der inkrementellen Statistik um 50%: verstrichene Zeit = 16840 ms.
- Update Incremental Statistics, Partition 3 mit Resample (50% - unsere neue Update-Zeit): verstrichene Zeit = 295 ms.
Wir sind in der Lage, viel mehr Daten abzutasten und möglicherweise das Optimierungsprogramm einzurichten, um bessere Vermutungen über unsere Daten anzustellen (obwohl noch keine Partitionsebenenstatistiken verwendet werden), und wir können dies jetzt schneller tun inkrementelle Statistiken.
Eine letzte lustige Sache, um herauszufinden, aber. Was ist mit synchronen Statistik-Updates? Wird die Abtastrate von 50% auch dann beibehalten, wenn die Autostaten aktiviert werden?
Ich habe Daten aus Partition 3 gelöscht und eine Abfrage für CreationDate ausgeführt und die Raten mit derselben Abfrage wie unten überprüft. Die 50% ige Abtastrate wurde beibehalten.
Um es kurz zu machen: Inkrementelle Statistiken können ein nützliches Werkzeug sein, das über die richtige Menge an Gedanken und anfänglichen Einrichtungsarbeiten verfügt. Sie müssen jedoch das Problem kennen, das Sie lösen möchten, und müssen es dann entsprechend lösen. Wenn Sie schlechte Kardinalitätsschätzungen erhalten, können Sie möglicherweise bessere Pläne mit einer strategischen Abtastrate und einigen investierten Eingriffen erzielen. Sie erhalten jedoch nur einen kleinen Teil des Vorteils, da das verwendete Histogramm die einzelne Seite mit zusammengeführten Statistiken und nicht die Informationen auf Partitionsebene ist. Wenn Sie Schmerzen in Ihrem Wartungsfenster verspüren, können Ihnen möglicherweise inkrementelle Statistiken helfen, aber Sie müssen wahrscheinlich einen Eingriffsprozess für die Wartung einrichten, der einen hohen Grad an Aufmerksamkeit erfordert. Ungeachtet,:
- Statistiken, die mit Indizes erstellt wurden, die nicht auf die Basistabelle partitioniert sind.
- Statistiken, die für von AlwaysOn lesbare sekundäre Datenbanken erstellt wurden.
- Statistiken, die für schreibgeschützte Datenbanken erstellt wurden.
- Auf gefilterten Indizes erstellte Statistiken.
- Auf Ansichten erstellte Statistiken.
- Auf internen Tabellen erstellte Statistiken.
- Statistiken, die mit räumlichen Indizes oder XML-Indizes erstellt wurden.
Hoffe das hilft
select
sysdatetime(),
schema_name = sh.name,
table_name = t.name,
stat_name = s.name,
index_name = i.name,
leading_column = index_col(quotename(sh.name)+'.'+quotename(t.name),s.stats_id,1),
s.stats_id,
parition_number = isnull(sp.partition_number,1),
s.has_filter,
s.is_incremental,
s.auto_created,
sp.last_updated,
sp.rows,
sp.rows_sampled,
sp.unfiltered_rows,
modification_counter = coalesce(sp.modification_counter, n1.modification_counter)
from sys.stats s
join sys.tables t
on s.object_id = t.object_id
join sys.schemas sh
on t.schema_id = sh.schema_id
left join sys.indexes i
on s.object_id = i.object_id
and s.name = i.name
cross apply sys.dm_db_stats_properties_internal(s.object_id, s.stats_id) sp
outer apply sys.dm_db_stats_properties_internal(s.object_id, s.stats_id) n1
where n1.node_id = 1
and (
(is_incremental = 0)
or
(is_incremental = 1 and sp.partition_number is not null)
)
and t.name = 'Posts'
and s.name like 'st_posts%'
order by s.stats_id,isnull(sp.partition_number,1)