À quel moment un indice devient-il efficace

9

J'ai trouvé beaucoup de ressources qui mentionnent que l'ajout d'un index à une table rend les recherches plus rapides et les insertions plus lentes, mais seulement si la table est grande. Cela crée un compromis, qui est une décision de conception, mais il devrait y avoir une taille de table approximative avant laquelle l'utilisation d'un index est absurde. (10 lignes, par exemple, est probablement bien en dessous de cette limite)

Quelqu'un sait-il où se situerait cette limite ou connaît-il une ressource qui me dirigerait dans la bonne direction?

SeanVDH
la source
Quel est le taux de lecture / écriture pour votre application? Si vous êtes vraiment intensif en écriture, c'est peut-être le point où vous devez prendre en compte le compromis d'écriture, mais si c'est une application habituelle, j'ajouterais l'index nécessaire dans 99% des cas (les tables augmentent généralement, elles revenir en taille).
Marian

Réponses:

12

La limite exacte est vraiment difficile à déterminer à l'avance.

La plupart des gens sous-estiment les exigences élevées qu'un index doit remplir avant de devenir un candidat à utiliser dans une requête.

Un index efficace (non clusterisé)

  • offre une grande sélectivité , par exemple, ne renvoie qu'un très petit pourcentage (<1%, <2%) du nombre total de lignes. Si la sélectivité n'est pas une donnée - l'optimiseur de requêtes de SQL Server ignorera très probablement cet index

  • devrait idéalement couvrir la requête, c'est-à-dire renvoyer toutes les colonnes requises par la requête. Si vous pouvez créer un index qui a 1 ou 2 colonnes d'index et inclut une autre poignée (2-4) de colonnes comme colonnes incluses et ainsi vous pouvez couvrir une requête - alors il y a de fortes chances que l'optimiseur de requête utilise cet index. Ce qui signifie également: si votre code est toujours utilisé SELECT * .....pour récupérer toutes les colonnes , la probabilité d'utilisation d'indices diminue - de manière assez spectaculaire

Je suis sûr qu'il existe également une tonne d'autres critères - mais je pense que ces deux-là sont les plus critiques. Bien sûr, vous devez toujours garder vos indices correctement entretenus (réorganiser, reconstruire) et vous assurer que les statistiques associées à vos indices sont à jour.

PS: les indices non clusterisés sur les colonnes de clés étrangères sont un cas particulier; par défaut, je recommanderais toujours d'ajouter ceux-ci, car ils aident à accélérer les deux vérifications d'intégrité référentielle, ainsi que JOINcelles sur ces contraintes FK. Mais même ici, il est absolument valable "d'étendre" ces index de colonnes FK en ajoutant des colonnes "include" supplémentaires pour les rendre encore plus utiles.

marc_s
la source
2
Bien que cette réponse ne réponde pas directement à la question, elle fait beaucoup mieux en donnant les principes de conception importants pour l'index, et répond à la question que j'aurais dû poser en premier lieu.
SeanVDH
6

Vous pourriez voir une amélioration d'un index avec seulement 10 lignes.

Dans le test suivant sur ma machine, la version sans index terminée en 10.5quelques secondes et la version avec un index en 9.8secondes (cohérente sur 3 runs).

L'index dans ce cas se compose uniquement d'une page feuille, mais comme le tableau des emplacements est ordonné dans l'ordre des clés d'index, sa présence permet à SQL Server de renvoyer la seule ligne d'intérêt plutôt que d'effectuer une agrégation sur les 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
Martin Smith
la source
Les insertions sont-elles affectées de la même manière ou le ralentissement est-il minimal?
SeanVDH
@SeanVDH - L'exemple dans ma réponse compare un index clusterisé à un tas. Il va de soi que les insertions entre les lignes existantes seraient plus lentes car les lignes doivent aller à un endroit spécifique et le tableau des emplacements réécrit également la possibilité de fractionner les pages. Pour les insertions plus importantes, les données peuvent également être triées dans l'ordre des clés CI, ce qui n'est pas nécessaire lors de l'insertion dans un segment de mémoire. Kimberley Tripp fait valoir ici cependant que parfois l'insertion dans un CI peut être meilleure que l'insertion dans un tas.
Martin Smith
Merci pour l'article, elle présente quelques points intéressants. Je me demandais si les insertions seraient affectées de manière aussi spectaculaire que les sélections dans le petit tableau, mais vous avez raison, le compromis devrait être similaire au début comme il le serait plus tard.
SeanVDH