Ich speichere Sensordaten in einer Tabelle SensorValues . Die Tabelle und der Primärschlüssel lauten wie folgt:
CREATE TABLE [dbo].[SensorValues](
[DeviceId] [int] NOT NULL,
[SensorId] [int] NOT NULL,
[SensorValue] [int] NOT NULL,
[Date] [int] NOT NULL,
CONSTRAINT [PK_SensorValues] PRIMARY KEY CLUSTERED
(
[DeviceId] ASC,
[SensorId] ASC,
[Date] DESC
) WITH (
FILLFACTOR=75,
DATA_COMPRESSION = PAGE,
PAD_INDEX = OFF,
STATISTICS_NORECOMPUTE = OFF,
SORT_IN_TEMPDB = OFF,
IGNORE_DUP_KEY = OFF,
ONLINE = OFF,
ALLOW_ROW_LOCKS = ON,
ALLOW_PAGE_LOCKS = ON)
ON [MyPartitioningScheme]([Date])
Wenn ich jedoch den Sensorwert auswähle, der für eine bestimmte Zeit gültig ist, teilt mir der Ausführungsplan mit, dass eine Sortierung durchgeführt wird. Warum das?
Ich hätte gedacht, dass die Sortierung nicht stattfinden würde, da ich die nach der Datumsspalte sortierten Werte speichere. Oder liegt es daran, dass der Index nicht nur nach der Datumsspalte sortiert ist, sondern nicht davon ausgehen kann, dass die Ergebnismenge sortiert ist?
SELECT TOP 1 SensorValue
FROM SensorValues
WHERE SensorId = 53
AND DeviceId = 3819
AND Date < 1339225010
ORDER BY Date DESC
Edit: Kann ich das stattdessen machen?
Da die Tabelle nach DeviceId, SensorId, Date sortiert ist und ich ein SELECT durchführe , das nur eine DeviceId und eine SensorId angibt , sollte der Ausgabesatz bereits nach Date DESC sortiert sein . Ich frage mich also, ob die folgende Frage in allen Fällen das gleiche Ergebnis liefern würde.
SELECT TOP 1 SensorValue
FROM SensorValues
WHERE SensorId = 53
AND DeviceId = 3819
AND Date < 1339225010
Gemäß @Catcall unten stimmt die Sortierreihenfolge nicht mit der Speicherreihenfolge überein. Dh wir können nicht davon ausgehen, dass die zurückgegebenen Werte bereits sortiert sind.
Edit: Ich habe diese CROSS APPLY-Lösung ausprobiert, kein Glück
@ Martin Smith schlug vor, ich würde versuchen, mein Ergebnis auf die Partitionen anzuwenden. Ich fand einen Blogeintrag ( Ausgerichtete nicht gruppierte Indizes für partitionierte Tabellen ), in dem dieses ähnliche Problem beschrieben wurde, und versuchte die etwas ähnliche Lösung für das, was Smith vorgeschlagen hatte. Leider ist die Ausführungszeit mit meiner ursprünglichen Lösung vergleichbar.
WITH Boundaries(boundary_id)
AS
(
SELECT boundary_id
FROM sys.partition_functions pf
JOIN sys.partition_range_values prf ON pf.function_id = prf.function_id
WHERE pf.name = 'PF'
AND prf.value <= 1339225010
UNION ALL
SELECT max(boundary_id) + 1
FROM sys.partition_functions pf
JOIN sys.partition_range_values prf ON pf.function_id = prf.function_id
WHERE pf.name = 'PF'
AND prf.value <= 1339225010
),
Top1(SensorValue)
AS
(
SELECT TOP 1 d.SensorValue
FROM Boundaries b
CROSS APPLY
(
SELECT TOP 1 SensorValue
FROM SensorValues
WHERE SensorId = 53
AND DeviceId = 3819
AND "Date" < 1339225010
AND $Partition.PF(Date) = b.boundary_id
ORDER BY Date DESC
) d
ORDER BY d.Date DESC
)
SELECT SensorValue
FROM Top1
Antworten:
Für eine nicht partitionierte Tabelle erhalte ich den folgenden Plan
Es gibt ein einzelnes Suchprädikat für
Seek Keys[1]: Prefix: DeviceId, SensorId = (3819, 53), Start: Date < 1339225010
.Dies bedeutet, dass SQL Server eine Gleichheitssuche für die ersten beiden Spalten ausführen und dann eine Bereichssuche beginnen kann, die bei
1339225010
und nach Reihenfolge beginntFORWARD
(da der Index mit definiert ist[Date] DESC
).Der
TOP
Bediener fordert nach dem Aussenden der ersten Zeile keine weiteren Zeilen mehr von der Suche an.Wenn ich das Partitionsschema und die Funktion erstelle
Füllen Sie die Tabelle mit den folgenden Daten
Der Plan für SQL Server 2008 sieht folgendermaßen aus.
Die tatsächliche Anzahl der von der Suche ausgegebenen Zeilen beträgt
500
. Der Plan zeigt SuchprädikateUm dies anzuzeigen, wird der hier beschriebene Ansatz zum Überspringen des Scans verwendet
Bei diesem Plan handelt es sich um einen seriellen Plan. Wenn SQL Server also sicherstellt, dass die Partitionen in absteigender Reihenfolge verarbeitet werden
date
,TOP
funktioniert der ursprüngliche Plan weiterhin und die Verarbeitung wird möglicherweise abgebrochen, nachdem die erste übereinstimmende Zeile vorhanden war gefunden, anstatt die verbleibenden 499 Übereinstimmungen fortzusetzen und auszugeben.In der Tat sieht der Plan für 2005 so aus
Ich bin mir nicht sicher, ob es ohne Weiteres möglich ist, den gleichen Plan für 2008 zu erstellen, oder ob für die Simulation ein
OUTER APPLY
On erforderlich wäresys.partition_range_values
.quelle
Viele Leute glauben, dass ein Clustered-Index eine Sortierreihenfolge bei der Ausgabe garantiert . Aber das ist nicht was es tut; es garantiert eine Speicherreihenfolge auf der Festplatte.
Siehe zum Beispiel diesen Blog-Beitrag und diese längere Diskussion .
quelle
Ich spekuliere, dass die SORT wegen des parallelen Plans benötigt wird. Ich stütze mich auf einen trüben und fernen Blog-Artikel, aber ich fand diesen auf MSDN, der dies möglicherweise rechtfertigt oder nicht
Versuchen Sie es mit MAXDOP 1 und sehen Sie, was passiert ...
Auch angedeutet in @sql Kiwis Blog-Post auf Simple Talk unter "Exchange Operator" denke ich. Und "DOP-Abhängigkeit" hier
quelle
date
. Jetzt habe ich und scheint Partitionierung ist der Schuldige mit 2005 möglicherweise besseres Verhalten für diese bestimmte Abfrage.Grundsätzlich haben Sie Recht - da sich der Primärschlüssel in der Reihenfolge "DeviceId, SensorId, Date" befindet, sind die Daten im Schlüssel nicht nach Datum sortiert und können daher nicht verwendet werden. Wenn Sie Ihren Schlüssel in einer anderen Reihenfolge war „Datum, DeviceId, SensorId“, dann werden die Daten in dem Schlüssel würde nach Datum sortiert werden, so verwendet werden könnte ...
quelle