A che punto avere un indice diventa efficiente


9

Ho trovato molte risorse che menzionano che l'aggiunta di un indice a una tabella rende le ricerche più veloci e inserisce più lentamente, ma solo se la tabella è grande. Questo crea un compromesso, che è una decisione di progettazione, ma dovrebbe esserci una dimensione approssimativa della tabella prima della quale l'uso di un indice è assurdo. (10 righe, ad esempio, è probabilmente molto al di sotto di tale limite)

Qualcuno sa dove sarebbe questo limite o conosce una risorsa che mi indirizzerebbe nella giusta direzione?


Qual è il rapporto lettura / scrittura per la tua applicazione? Se stai davvero scrivendo intensamente, forse è il punto in cui devi prendere in considerazione il compromesso delle scritture, ma se è un'applicazione normale, aggiungerei l'indice necessario nel 99% dei casi (le tabelle di solito crescono, difficilmente tornare indietro di dimensioni).
Marian,

Risposte:


12

Il limite esatto è davvero difficile da determinare in anticipo.

Una cosa che la maggior parte delle persone sottovaluta sono i requisiti elevati che un indice deve soddisfare, prima che diventi un candidato da utilizzare in una query.

Un indice efficiente (non cluster)

  • offre un'ottima selettività , ad es. restituisce solo una percentuale molto piccola (<1%, <2%) delle righe totali. Se la selettività non è un dato, l'ottimizzatore delle query di SQL Server probabilmente ignorerà questo indice

  • dovrebbe idealmente coprire la query, ovvero restituire tutte le colonne richieste dalla query. Se puoi creare un indice con 1 o 2 colonne di indice e include un'altra manciata (2-4) colonne come colonne incluse e quindi puoi coprire una query, allora è probabile che Query Optimizer utilizzerà questo indice. Il che significa anche: se il tuo codice viene sempre utilizzato SELECT * .....per recuperare tutte le colonne , la probabilità che gli indici vengano utilizzati diminuisce, in modo abbastanza drammatico, in realtà

Sono sicuro che ci sono anche molti altri criteri, ma credo che questi due siano i più critici. Naturalmente, dovresti sempre mantenere gli indici correttamente mantenuti (riorganizzare, ricostruire) e assicurarti che le statistiche associate ai tuoi indici siano aggiornate.

PS: gli indici non cluster su colonne di chiavi esterne sono un caso speciale; per impostazione predefinita, consiglierei sempre di aggiungerli, poiché aiutano ad accelerare sia i controlli di integrità referenziale, sia JOINquelli sui vincoli di FK. Ma anche qui, è assolutamente valido "estendere" quegli indici di colonna FK aggiungendo alcune colonne "include" aggiuntive per renderle ancora più utili.


2
Sebbene questa risposta potrebbe non rispondere direttamente alla domanda, fa molto meglio fornendo gli importanti principi di progettazione per l'indice e risponde alla domanda che avrei dovuto porre in primo luogo.
SeanVDH,

6

Potresti notare un miglioramento da un indice con solo 10 righe.

Nel seguente test sulla mia macchina la versione senza indice è stata completata in 10.5pochi secondi e la versione con un indice in 9.8secondi (coerente su 3 esecuzioni).

L'indice in questo caso è composto solo da 1 pagina foglia ma poiché l'array di slot è ordinato in ordine di chiave indice, la sua presenza consente a SQL Server di restituire solo la singola riga di interesse anziché eseguire un'aggregazione su tutti e 10.

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

Gli inserti sono interessati in modo simile o il rallentamento è minimo?
SeanVDH,

@SeanVDH - L'esempio nella mia risposta è il confronto di un indice cluster con un heap. Sarebbe ovvio che gli inserimenti tra le righe esistenti sarebbero più lenti in quanto le righe devono andare in un posto specifico e l'array di slot riscritto anche possibilità di divisioni di pagina. Per inserti più grandi, i dati possono essere ordinati anche nell'ordine delle chiavi CI che non è necessario quando si inseriscono in un heap. Kimberley Tripp sostiene qui che a volte l'inserimento in un elemento della configurazione può essere migliore che l'inserimento in un heap.
Martin Smith,

Grazie per l'articolo, presenta alcuni punti interessanti. Mi chiedevo se gli inserti sarebbero stati influenzati in modo drammatico quanto le selezioni nella tabella piccola, ma hai ragione, il compromesso dovrebbe essere simile all'inizio come sarebbe in seguito.
SeanVDH,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.