Ich habe einen Tisch wie diesen:
CREATE TABLE Updates
(
UpdateId INT NOT NULL IDENTITY(1,1) PRIMARY KEY,
ObjectId INT NOT NULL
)
Verfolgen Sie im Wesentlichen Aktualisierungen von Objekten mit zunehmender ID.
Der Konsument dieser Tabelle wählt einen Teil von 100 verschiedenen Objekt-IDs aus, die nach UpdateId
einem bestimmten geordnet sind und von diesem ausgehen UpdateId
. Verfolgen Sie im Wesentlichen, wo es aufgehört hat, und fragen Sie dann nach Updates.
Ich habe dies als interessantes Optimierungsproblem empfunden, da ich nur durch das Schreiben von Abfragen einen maximal optimalen Abfrageplan generieren konnte passieren zu tun , was ich Indizes auf Grund will, aber nicht garantieren , was ich will:
SELECT DISTINCT TOP 100 ObjectId
FROM Updates
WHERE UpdateId > @fromUpdateId
Wo @fromUpdateId
ist ein Parameter einer gespeicherten Prozedur?
Mit einem Plan von:
SELECT <- TOP <- Hash match (flow distinct, 100 rows touched) <- Index seek
Aufgrund der Suche nach dem verwendeten UpdateId
Index sind die Ergebnisse bereits gut und werden von der niedrigsten zur höchsten Update-ID sortiert, wie ich es möchte. Und dies erzeugt einen Flow-eigenen Plan, den ich mir wünsche. Aber die Bestellung ist offensichtlich kein garantiertes Verhalten, deshalb möchte ich es nicht verwenden.
Dieser Trick führt auch zum gleichen Abfrageplan (allerdings mit einem redundanten TOP):
WITH ids AS
(
SELECT ObjectId
FROM Updates
WHERE UpdateId > @fromUpdateId
ORDER BY UpdateId OFFSET 0 ROWS
)
SELECT DISTINCT TOP 100 ObjectId FROM ids
Ich bin mir jedoch nicht sicher (und vermute nicht), ob dies wirklich eine Bestellung garantiert.
Eine Abfrage, von der ich gehofft habe, dass SQL Server so intelligent ist, dass sie vereinfacht werden kann, generiert jedoch einen sehr schlechten Abfrageplan:
SELECT TOP 100 ObjectId
FROM Updates
WHERE UpdateId > @fromUpdateId
GROUP BY ObjectId
ORDER BY MIN(UpdateId)
Mit einem Plan von:
SELECT <- Top N Sort <- Hash Match aggregate (50,000+ rows touched) <- Index Seek
Ich versuche einen Weg zu finden, um einen optimalen Plan mit einer Indexsuche UpdateId
und einem bestimmten Fluss zu generieren , um doppelte ObjectId
s zu entfernen . Irgendwelche Ideen?
Beispieldaten, wenn Sie es wollen. Objekte werden selten mehr als ein Update haben und sollten fast nie mehr als ein Update in einem Satz von 100 Zeilen haben. Aus diesem Grund bin ich nach einem bestimmten Flow strebend , es sei denn, es gibt etwas Besseres, von dem ich nichts weiß. Es gibt jedoch keine Garantie dafür, dass eine einzelne ObjectId
Tabelle nicht mehr als 100 Zeilen enthält. Die Tabelle hat über 1.000.000 Zeilen und wird voraussichtlich schnell wachsen.
Angenommen, der Benutzer hat einen anderen Weg, um den entsprechenden nächsten zu finden @fromUpdateId
. In dieser Abfrage muss es nicht zurückgegeben werden.