Ab wann wird ein Index effizient?

9

Ich habe viele Ressourcen gefunden, die erwähnen, dass das Hinzufügen eines Index zu einer Tabelle die Suche beschleunigt und Einfügungen langsamer macht, aber nur, wenn die Tabelle groß ist. Dies führt zu einem Kompromiss, der eine Entwurfsentscheidung darstellt. Es sollte jedoch eine ungefähre Tabellengröße geben, vor der die Verwendung eines Index absurd ist. (10 Zeilen zum Beispiel liegen wahrscheinlich weit unter dieser Grenze)

Weiß jemand, wo diese Grenze liegen würde, oder kennt er eine Ressource, die mich in die richtige Richtung weisen würde?

SeanVDH
quelle
Wie ist das Lese- / Schreibverhältnis für Ihre Anwendung? Wenn Sie wirklich intensiv schreiben, ist dies möglicherweise der Punkt, an dem Sie den Kompromiss zwischen Schreibvorgängen berücksichtigen müssen. Wenn es sich jedoch um eine übliche Anwendung handelt, würde ich in 99% der Fälle den erforderlichen Index hinzufügen (die Tabellen wachsen normalerweise kaum in Größe zurück gehen).
Marian

Antworten:

12

Das genaue Limit ist wirklich schwer im Voraus zu bestimmen.

Eine Sache, die die meisten Leute unterschätzen, sind die hohen Anforderungen, die ein Index erfüllen muss, bevor er zu einem Kandidaten für eine Abfrage wird.

Ein effizienter (nicht gruppierter) Index

  • bietet eine große Selektivität , z. B. gibt nur einen sehr kleinen Prozentsatz (<1%, <2%) der gesamten Zeilen zurück. Wenn die Selektivität nicht gegeben ist, ignoriert der SQL Server-Abfrageoptimierer diesen Index höchstwahrscheinlich

  • sollte idealerweise die Abfrage abdecken , dh alle für die Abfrage erforderlichen Spalten zurückgeben. Wenn Sie einen Index erstellen können, der 1 oder 2 Indexspalten enthält und eine weitere Handvoll (2-4) Spalten als eingeschlossene Spalten enthält, und somit eine Abfrage abdecken können, verwendet der Abfrageoptimierer wahrscheinlich diesen Index. Das bedeutet auch: Wenn Ihr Code immer SELECT * .....zum Abrufen aller Spalten verwendet wird , sinkt die Wahrscheinlichkeit, dass Indizes verwendet werden - eigentlich ziemlich dramatisch

Ich bin mir sicher, dass es auch eine Menge anderer Kriterien gibt - aber ich würde glauben, dass diese beiden die kritischsten sind. Natürlich sollten Sie Ihre Indizes immer ordnungsgemäß pflegen (neu organisieren, neu erstellen) und sicherstellen, dass die mit Ihren Indizes verknüpften Statistiken auf dem neuesten Stand sind.

PS: Nicht gruppierte Indizes für Fremdschlüsselspalten sind ein Sonderfall. Standardmäßig würde ich immer empfehlen, diese hinzuzufügen, da sie sowohl die referenzielle Integritätsprüfung als auch JOINdie FK-Einschränkungen beschleunigen . Aber auch hier ist es absolut gültig, diese FK-Spaltenindizes durch Hinzufügen einiger zusätzlicher "Include" -Spalten zu "erweitern", um sie noch nützlicher zu machen.

marc_s
quelle
2
Obwohl diese Antwort die Frage möglicherweise nicht direkt beantwortet, ist sie viel besser, indem sie die wichtigen Gestaltungsprinzipien für den Index angibt und die Frage beantwortet, die ich eigentlich hätte stellen sollen.
SeanVDH
6

Möglicherweise sehen Sie eine Verbesserung gegenüber einem Index mit nur 10 Zeilen.

Im folgenden Test auf meinem Computer wurde die Version ohne Index in 10.5Sekunden und die Version mit einem Index in 9.8Sekunden abgeschlossen (konsistent über 3 Läufe).

Der Index besteht in diesem Fall nur aus einer Blattseite. Da das Slot-Array jedoch in der Reihenfolge der Indexschlüssel angeordnet ist, kann SQL Server aufgrund seiner Anwesenheit nur die einzelne interessierende Zeile zurückgeben, anstatt eine Aggregation für alle 10 durchzuführen.

CREATE TABLE T
(
X INT,
Y CHAR(100) NULL
)

INSERT INTO T (X)
SELECT number 
FROM master..spt_values
WHERE type='P' AND number BETWEEN 1 AND 10

set nocount on;

DECLARE @I INT, @X INT

DECLARE @Time DATETIME2(7) = SYSUTCDATETIME()

SET @I = 1
    WHILE (@I < 1000000)
    BEGIN
    SELECT @X = MAX(X)
    FROM T
    SET @I += 1
    END

SELECT DATEDIFF(MICROSECOND, @Time, SYSUTCDATETIME())

CREATE CLUSTERED INDEX IX ON T(X)
SET @Time = SYSUTCDATETIME()
SET @I = 1
    WHILE (@I < 1000000)
    BEGIN
    SELECT @X = MAX(X)
    FROM T
    SET @I += 1
    END

SELECT DATEDIFF(MICROSECOND, @Time, SYSUTCDATETIME())

DROP TABLE T
Martin Smith
quelle
Sind Einsätze ähnlich betroffen oder ist die Verlangsamung minimal?
SeanVDH
@ SeanVDH - Das Beispiel in meiner Antwort ist der Vergleich eines Clustered-Index mit einem Heap. Es liegt auf der Hand, dass Einfügungen zwischen vorhandenen Zeilen langsamer sind, da die Zeilen an eine bestimmte Stelle verschoben werden müssen und das Slot-Array auch die Möglichkeit von Seitenteilungen umschreibt. Bei größeren Einfügungen können die Daten auch in der CI-Schlüsselreihenfolge sortiert werden, was beim Einfügen in einen Heap nicht erforderlich ist. Kimberley Tripp argumentiert hier jedoch, dass das Einfügen in ein CI manchmal besser sein kann als das Einfügen in einen Heap.
Martin Smith
Vielen Dank für den Artikel, sie präsentiert einige interessante Punkte. Ich habe mich gefragt, ob die Einfügungen genauso dramatisch betroffen sind wie die Auswahlen in der kleinen Tabelle, aber Sie haben Recht, der Kompromiss sollte am Anfang ähnlich sein wie später.
SeanVDH