2011-01-04 6 views
1

In meiner Anwendung verwende ich eine einfache Tabelle, die angibt, wie oft auf eine Datei zugegriffen wurde und an welchem ​​Datum sie zuletzt aufgerufen wurde.SQL Server-Tabelle in Datenbank sortieren

Ich versuche, die gespeicherten Einträge so zu sortieren, dass die Dateien mit der höchsten Anzahl von Zugriffen in der Datenbank immer oben sind. Außerdem möchte ich nur die Dateien sortieren, auf die in den letzten 7 Tagen zugegriffen wurde.

Welche Methode soll ich verwenden (unter Berücksichtigung der Ausführungsgeschwindigkeit)? Soll ich vielleicht eine Stored Procedure schreiben, die sich um die Sortierung kümmert und sie einfach jedes Mal aufrufen, wenn ich einen Eintrag hinzufüge oder ändere? Sollte ich die Einträge in meiner Anwendung, die neuer als 7 Tage sind, abfragen, sie sortieren und oben in der Datenbank hinzufügen? Andere Methoden sind sehr willkommen.

Danke, Catalin

Antwort

3

Wenn Sie ein clustered index auf den Spalten, die Reihenfolge definieren hinzufügen, wird SQL Server, dass verwendet physisch Zeilen in der Tabelle zu organisieren.

Sie sollten jedoch immer eine ORDER BY-Klausel in Ihren Abfragen verwenden, da die Datenbank keine Zeilen in einer bestimmten Reihenfolge zurückgeben muss. Der Vorteil der Verwendung eines gruppierten Index besteht jedoch darin, dass dadurch die Gesamtkosten für das Sortieren von Zeilen beim Abrufen verringert werden können und die Abfragen für den Leistungsbereich in den indizierten Spalten verbessert werden.

+1

Es gibt * keine * Garantie, dass die * physische * Reihenfolge der Zeilen in der Datenbankdatei der Reihenfolge entspricht, die durch den gruppierten Index definiert wurde. Alles, was ein Clustered-Index garantiert, ist, dass Bereichsabfragen, die für dieselben Spalten wie die im Clustered-Index aufgeführten ausgedrückt werden, mit weniger Suchvorgängen als mit einem Nicht-Clustered-Index erfüllt werden können. Aber Sie haben richtig zu sagen, immer eine ORDER BY-Klausel anzugeben. –

+0

@Damien_The_Unbeliever: Mein Verständnis war mit einem gruppierten Index, Datensätze innerhalb einer einzelnen Seite würde durch den Cluster-Schlüssel geordnet werden. Der Nettoeffekt besteht darin, dass, während sich einzelne Seiten nicht in einer bestimmten Reihenfolge auf der Platte befinden, die Kosten für das Sortieren von Datensätzen etwas verringert werden (es wird effektiv zu einer Zusammenführungs-Sortieroperation). Aber vielleicht habe ich etwas falsch verstanden. – LBushkin

0

Die Datenbankindizes wichtige Spalten (und alle anderen Spalten, die Sie angeben), so können Sie die Reihenfolge der Zeilen in der Datenbank ignorieren und nur sicherstellen, dass die richtigen Spalten indiziert sind. Von dort aus wird ein einfacher OrderBy in Ihrer Abfrage dafür sorgen, dass die Datensätze in der richtigen Reihenfolge zurückgegeben werden.

2

In Ihrer Frage gibt es eine implizite Annahme, dass eine relationale Datenbanktabelle irgendwie geordnet ist. Es ist nicht. Es stellt einen Satz dar. Mengen sind per Definition ungeordnet (z. B. ist die Menge [a, b, c] dieselbe Menge wie [b, c, a]).

Daher garantiert SQL ausdrücklich keine bestimmte Reihenfolge für eine Ergebnismenge, es sei denn, eine wird über eine ORDER BY-Klausel angegeben. Die Ausführung genau derselben Abfrage ohne ORDER BY zweimal hintereinander könnte theoretisch identische Ergebnismengen mit unterschiedlicher Reihenfolge zurückgeben (zum Beispiel könnten bestimmte Seiten der Tabelle bereits im Cache sein und überprüft werden, bevor die Ausführungsmaschine andere Seiten betrachtet). In der Praxis wird ein Clustering-Index für die Tabelle (in SQL Server) zurückgegeben, wenn die Ergebnisse in Clustersequenz (sofern die Abfrage den Clusterindex oder Nicht-Index verwendet) als Nettoeffekt des Hinzufügens eines Clusterindex zurückgegeben werden ist, die Datenseiten der Tabelle zu den Blattknoten des B-Baums zu machen, der der Clusterindex ist. Ohne einen Clustering-Index befinden sich die Datenseiten der Tabelle in einem Heap, und jeder (nicht geclusterte) Index ist ein B-Baum, bei dem die Blattknoten Zeiger auf eine Datenseite im Heap sind.

Zurück zu Ihrer Frage ...

Betrachten Sie die Tabelle:

create table dbo.PublicFile 
(
    id    int   not null , 
    name    varchar(500) not null , 
    access_cnt  int   not null , 
    dt_last_access datetime  not null , 

    primary key nonclustered (id) , 
    unique  nonclustered (name) , 

) 

Die beiden Spalten access_cnt und dt_last_access sind von Ihrer Beschreibung hochdynamischen beide. Jeder Zugriff auf eine Datei führt zu einer Aktualisierung dieser beiden Spalten.Wenn Sie einen Clustering-Index auf diese setzen, treten Performance-Probleme aufgrund der hohen Anzahl von Seitenaufteilungen auf, die auftreten, wenn Zeilen im Index verschoben werden. (Sie haben das gleiche Problem mit einem nicht gruppierten Index, aber die Seitenaufteilung betrifft nur die Indexseiten, nicht die Datenseiten, eine viel kleinere Spalte.)

Zuerst schreiben Sie die Abfrage an Erhalten Sie die gewünschten Ergebnisse ohne Berücksichtigung der Indizierung (das ist eine Optimierung). Diese Abfrage wird Ihnen die Liste der öffentlichen Dateien in den letzten 7 Tagen zugegriffen wird, durch die Anzahl der Zugriffe in absteigender Reihenfolge geordnet:

select * 
from dbo.PublicFile f 
where f.dt_last_access >= dateadd(day,-7,current_timestamp) 
order by f.access_cnt desc , f.name 

Je nach Größe der Daten, könnte dies auch Server, wie es steht. Wenn Sie 4 oder 5 Millionen Zeilen haben, wird es wahrscheinlich nicht. Ihr DBA wird wahrscheinlich einen Index für die Daten des letzten Zugriffs und die Zugriffsanzahl hinzufügen. Ich würde wahrscheinlich nur einen Index verwenden:

create nonclustered index PublicFile_IX01 
on dbo.PublicFile (dt_last_access , 
        access_cnt desc 
       ) 

Aber es gibt eine gewisse Menge an Experimenten beteiligt. Abhängig von der Semantik der Abfrage und der Form der Daten mag der Abfrageoptimierer sie mögen oder auch nicht.

+0

Wird es ausprobieren. Danke für die Antwort. –