Ich teste verschiedene Architekturen für große Tabellen und ein Vorschlag, den ich gesehen habe, ist die Verwendung einer partitionierten Ansicht, bei der eine große Tabelle in eine Reihe kleinerer, "partitionierter" Tabellen aufgeteilt wird.
Beim Testen dieses Ansatzes habe ich etwas entdeckt, das für mich keinen Sinn ergibt. Wenn ich in der Faktensicht nach "Partitionierungsspalte" filtere, sucht der Optimierer nur in den relevanten Tabellen. Wenn ich in der Dimensionstabelle nach dieser Spalte filtere, entfernt das Optimierungsprogramm darüber hinaus unnötige Tabellen.
Wenn ich jedoch nach einem anderen Aspekt der Dimension filtere, sucht der Optimierer nach dem PK / CI jeder Basistabelle.
Hier sind die fraglichen Fragen:
select
od.[Year],
AvgValue = avg(ObservationValue)
from dbo.v_Observation o
join dbo.ObservationDates od
on o.ObservationDateKey = od.DateKey
where o.ObservationDateKey >= 20000101
and o.ObservationDateKey <= 20051231
group by od.[Year];
select
od.[Year],
AvgValue = avg(ObservationValue)
from dbo.v_Observation o
join dbo.ObservationDates od
on o.ObservationDateKey = od.DateKey
where od.DateKey >= 20000101
and od.DateKey <= 20051231
group by od.[Year];
select
od.[Year],
AvgValue = avg(ObservationValue)
from dbo.v_Observation o
join dbo.ObservationDates od
on o.ObservationDateKey = od.DateKey
where od.[Year] >= 2000 and od.[Year] < 2006
group by od.[Year];
Hier ist ein Link zur SQL Sentry Plan Explorer-Sitzung.
Ich arbeite daran, die größere Tabelle tatsächlich zu partitionieren, um festzustellen, ob die Partitionseliminierung auf ähnliche Weise reagiert.
Für die (einfache) Abfrage, die nach einem Aspekt der Dimension filtert, wird die Partition entfernt.
In der Zwischenzeit ist hier eine Nur-Statistiken-Kopie der Datenbank:
https://gist.github.com/swasheck/9a22bf8a580995d3b2aa
Der "alte" Kardinalitätsschätzer bekommt einen günstigeren Plan, aber das liegt an den niedrigeren Kardinalitätsschätzungen für jeden der (unnötigen) Index-Suchvorgänge.
Ich möchte wissen, ob es eine Möglichkeit gibt, das Optimierungsprogramm dazu zu bringen, die Schlüsselspalte beim Filtern nach einem anderen Aspekt der Dimension zu verwenden, damit Suchvorgänge für irrelevante Tabellen vermieden werden.
SQL Server Version:
Microsoft SQL Server 2014 - 12.0.2000.8 (X64)
Feb 20 2014 20:04:26
Copyright (c) Microsoft Corporation
Developer Edition (64-bit) on Windows NT 6.3 <X64> (Build 9600: ) (Hypervisor)
quelle
CREATE STATISTICS [_WA_Sys_00000008_2FCF1A8A] ON [dbo].[Observation_2010]([StationStateCode]) WITH STATS_STREAM = 0x01000000010000000000000000000000D4531EDB00000000D5080000000000009508000000000000AF030000AF000000020000000000000008D000340000000007000000E65DE0007DA5000076F9780000000000867704000000000000000000ABAAAA3C0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
ObservationDates
Tabelle vor. Ich bekomme nicht den gleichen Plan wie Paul, auch mit 4199, und ich denke, das ist der Grund.ObservationDates
. Am Ende lief ichUPDATE STATISTICS ObservationDates WITH ROWCOUNT = 10000
manuell, um den Plan zu erhalten, den Paul demonstrierte.ObservationDates
ja , sie sind Indizes), daher bin ich mir nicht sicher, was damit los ist. Ich bin auch nicht in der Lage, den Plan zu generieren, den Paul erstellt hat. Ich werde versuchen, das Update zu sehen.Antworten:
Aktivieren Sie das Trace-Flag 4199.
Ich musste auch folgendes ausstellen:
um die unten gezeigten Pläne zu erhalten. Statistiken für diese Tabelle fehlten im Upload. Die Zahl 73.049 stammt aus den Informationen zur Tabellenkardinalität im Plan-Explorer-Anhang. Ich habe SQL Server 2014 SP1 CU4 (Build 12.0.4436) mit zwei logischen Prozessoren, maximalem Speicher auf 2048 MB und keinen Ablaufverfolgungsflags außer 4199 verwendet.
Sie sollten dann einen Ausführungsplan erhalten, der die dynamische Eliminierung von Partitionen beinhaltet:
Planfragment:
Dies könnte schlechter aussehen, aber die Filter sind alle Start-up - Filter. Ein Beispiel-Prädikat ist:
Pro Iteration der Schleife wird das Start-Prädikat getestet, und nur wenn es true zurückgibt, wird der darunter liegende Clustered-Index-Suchlauf ausgeführt. Daher dynamische Partitionsbeseitigung.
Dies ist möglicherweise nicht ganz so effizient wie die statische Beseitigung, insbesondere wenn der Plan parallel ist.
Unter Umständen müssen Sie Hinweise , wie versuchen
MAXDOP 1
,FAST 1
oderFORCESEEK
auf der Ansicht , den gleichen Plan zu erhalten. Optimierer-Kalkulationsoptionen mit partitionierten Ansichten (wie partitionierten Tabellen) können schwierig sein.Der Punkt ist, dass Sie einen Plan benötigen, der Startfilter enthält, um eine dynamische Partitionsbeseitigung mit partitionierten Ansichten zu erreichen.
Abfragen mit eingebetteten
USE PLAN
Hinweisen: (über gist.github.com):quelle
Meine Beobachtung war immer, dass Sie den Wert (oder Wertebereich) für die Partitionsspalte explizit in der Abfrage angeben müssen, um "Tabelleneliminierung" in einer partitionierten Ansicht zu erhalten. Dies basiert auf Erfahrungen mit partitionierten Ansichten in der Produktion von SQL Server 2000 bis SQL Server 2014.
In SQL Server gibt es kein Konzept für einen Schleifenverknüpfungsoperator, bei dem das Modul die Suche dynamisch direkt auf die richtige Tabelle auf der Innenseite der Schleife ausrichten kann, basierend auf dem Wert der Zeile auf der Außenseite der Schleife. Wie Pauls Antwort erklärt , gibt es jedoch die Möglichkeit, einen Plan mit Startfiltern zu erstellen, um irrelevante Tabellen auf der Innenseite der Schleife in konstanter Zeit dynamisch zu überspringen (im Gegensatz zur logarithmischen Ausführung der Suche).
Beachten Sie, dass für partitionierte Tabellen diese Art der Suche (für eine bestimmte Partition) unterstützt wird.
Wenn Sie nur partitionierte Ansichten verwenden möchten, können Sie Ihre Abfrage auch in mehrere Abfragen aufteilen, z.
Dies ergibt den folgenden Plan. Es gibt jetzt eine zusätzliche Abfrage, die auf die Dimensionstabelle trifft, aber die Abfrage über die (vermutlich viel größere) Faktentabelle ist optimiert.
quelle
20000101
und20051231
anstelle der Variablen (oder über zwei separate Abfragen in Ihrer Anwendung etwas Ähnliches tun), dann wird derselbe Effekt erzielt, ohne die Variablen zu verwenden.