Query mit "@id between minid and maxid" schneller machen

18/10/2009 - 10:35 von Christian Stüben | Report spam
Hallo allerseits,
auf meinem SQL-Server 2000 habe ich u.a. eine Datei mit ca 1.300.000
Eintràgen. Dort sind vier Werte drinn enthalten, sn bigint, locid bigint,
startipnum bigint, endipnum bigint.

3 Indizes sind vorhanden:
sn (nicht geclustert)
locid
startipnum endipnum (jetzt geclustert)

Wenn ich jetzt mit "select locid from blocks where @id between startipnum
and endipnum" (@id ebenfalls bigint) abfrage, braucht die Query mit 0,7
Sekunden eine halbe Ewigkeit.
Nach etwas stöbern in der msdn library habe ich den betreffenden Index auf
clustered gestellt, und siehe an, wie Zeit fiel von 0,7 auf 0,15 Sekunden.

Höhere Speicherzuteilung für den SQL-Server hat nichts gebracht, die
Umstellung von startipnum und endipnum im Index von ascending auf descending
ebenso nichts (man kommt auf die seltsamsten Ideen), ebenso nicht ... where
startipnum <= @ip and endipnum >= @ip.
Eine Umstellung der Bereiche auf Einzeleintràge habe ich schon angedacht (so
daß ich mit "where ip = @ip" arbeiten könnte) , aber würde in knapp einer
Milliarde Datensàtzen enden und den Rahmen von Datenbank, Festplatte, etc.
sprengen.

Welche Chance hàtte ich noch, die Query noch schneller zu machen? Von den
bei mir üblichen Zeiten von unter einer Hunderstel Sekunde ist sie noch um
Faktor 15 entfernt. Oder müß ich wegen der Bereichsabfrage damit leben? Die
Online-Library sagt ja klar daß Abfragen mit größer, kleiner, between,
langsamer sind.


Jeder Tipp ist willkommen.

mfg Chris
 

Lesen sie die antworten

#1 Josef Poetzl
18/10/2009 - 11:57 | Warnen spam
Hallo!

Christian Stüben schrieb:
[...]
3 Indizes sind vorhanden:
sn (nicht geclustert)
locid
startipnum endipnum (jetzt geclustert)

Wenn ich jetzt mit "select locid from blocks where @id between startipnum
and endipnum" (@id ebenfalls bigint) abfrage, braucht die Query mit 0,7
Sekunden eine halbe Ewigkeit.


[...]
Eine Umstellung der Bereiche auf Einzeleintràge habe ich schon angedacht (so
daß ich mit "where ip = @ip" arbeiten könnte) , aber würde in knapp einer
Milliarde Datensàtzen enden und den Rahmen von Datenbank, Festplatte, etc.
sprengen.

Welche Chance hàtte ich noch, die Query noch schneller zu machen? Von den
bei mir üblichen Zeiten von unter einer Hunderstel Sekunde ist sie noch um
Faktor 15 entfernt.



[OT]
Mal eine Grundsatzfrage: Warum spielt das so eine große Rolle?
0,15 sec sind zwar sicher keine berauschende Geschwindigkeit, aber
solange man das nicht innerhalb einer Schleife ausführt - was vom
Konzept her falsch wàre - wird das kaum einen Anwender auffallen,
oder?
[/OT]

Oder müß ich wegen der Bereichsabfrage damit leben? Die
Online-Library sagt ja klar daß Abfragen mit größer, kleiner, between,
langsamer sind.



Wie sieht der Ausführungsplan aus?
Wenn der Index passt, müsste auf jeden Fall ein Index-Seek laufen.
Wie lange dauert zum Vergleich diese Abfrage:
select locid from blocks where startipnum = @id


Sind die Indizes optimiert bzw. die Statistik aktuell?
(DBCC INDEXDEFRAG, DBCC DBREINDEX & Co.)


Wie führst du die SQL-Anweisung aus?
Muss der Ausführungsplan jedes Mal neu erstellt werden, oder
verwendest du eine gespeicherte Prozedur? (Das Erstellen des
Ausführungsplans sollte zwar ruck-zuck erledigt sein, aber wenn es auf
Mikrosekunden ankommt, bremst auch das. ;)



Auf gut Glück:
Hast du schon so einen Index versucht: endipnum, startipnum

Top 1 könnte eventuell auch noch helfen, damit nicht nach weiteren
Treffern gesucht wird.


mfg
Josef

Ähnliche fragen