Als uns letzte Woche Darius Parys das neue Entity-Framework von Microsoft vorstellte, warfen wir auch einen Blick auf das (unter der Haube) produzierte SQL. Dabei viel mir auf, dass dort das Paging-Problem – Die Daten werden in Häppchen von SQl-Server angefordert und gelesen – mittels ROW_NUMBER gelöst wird. Das ist natürlich ein sehr pragmatischer Ansatz, der aber nur dann wirklich performant klappen kann, wenn auf dem Ordnungskriterium (meist dem Schlüssel) auch wirklich der Clustered-Index liegt. Die Variante von Microsoft war jedenfalls erheblich komplizierter als der gängige, deswegen kann ich den auch nicht auswendig hinschrieben.
In der Regel würde ich aber sowieso empfehlen den Clustered-Index aber eher auf fachliche Kriterien zu legen, damit alle Datensätze, die zugleich bearbeitet werden auf den gleichen (oder benachbarten) Datenseiten liegen. Damit ist aber fast jede Art des Paging auf den technischen Schlüsseln langsam.
Blöd ist natürlich auch, dass Einfügevorgänge seltsame Nebenwirkungen haben können. Wenn ich z.B. eine "Seite" von Daten am Bildschirm sehe und dann eine Minute später die zweite abrufe, dann bekomme ich als ersten unter Umständen Sätze angezeigt, die ich schon auf der ersten Seite sah, wenn inzwischen Datensätze eingefügt wurden. Dito beim Löschen, nur umgekehrt. 🙂
Bei uns werden daher meistens die letzten IDs gespeichert und dann die danach folgenden Daten abgerufen. Mit TOP kann man dann steuern, wie viele man bekommen möchte. Wie gesagt, auch sollte wenigstens ein Index auf den Schlüssel liegen, am besten ein Clustered…
Tom Rizzo von Microsoft schlug uns 2002 hingegen vor, dass wir zu dem Zweck zwei verschachtelte TOPs verwenden, was auch wieder nur dann schnell ist, wenn der Index stimmt. 😀