J'ai la requête SQL suivante:
SELECT
Event.ID,
Event.IATA,
Device.Name,
EventType.Description,
Event.Data1,
Event.Data2
Event.PLCTimeStamp,
Event.EventTypeID
FROM
Event
INNER JOIN EventType ON EventType.ID = Event.EventTypeID
INNER JOIN Device ON Device.ID = Event.DeviceID
WHERE
Event.EventTypeID IN (3, 30, 40, 41, 42, 46, 49, 50)
AND Event.PLCTimeStamp BETWEEN '2011-01-28' AND '2011-01-29'
AND Event.IATA LIKE '%0005836217%'
ORDER BY Event.ID;
J'ai également un index sur la Event
table pour la colonne TimeStamp
. Je crois comprendre que cet index n'est pas utilisé à cause de la IN()
déclaration. Donc, ma question est de savoir s'il existe un moyen de créer un index pour cette IN()
instruction particulière afin d'accélérer cette requête?
J'ai également essayé d'ajouter en Event.EventTypeID IN (2, 5, 7, 8, 9, 14)
tant que filtre pour l'index TimeStamp
, mais en regardant le plan d'exécution, il ne semble pas utiliser cet index. Toutes suggestions ou informations à ce sujet seraient grandement appréciées.
Voici le plan graphique:
Et voici un lien vers le fichier .sqlplan .
Réponses:
Étant donné les tableaux de la forme générale suivante:
L'index suivant est utile:
Pour la requête:
Le filtre répond à l'
AND
exigence de la clause, la première clé de l'index permet une recherche sur[TimeStamp]
le filtréEventTypeIDs
et l'inclusion de laDeviceID
colonne rend l'index couvrant (car ilDeviceID
est requis pour la jointure à laDevice
table).La deuxième clé de l'index -
EventTypeID
n'est pas strictement requise (il peut également s'agir d'uneINCLUDEd
colonne); Je l'ai inclus dans la clé pour les raisons indiquées ici . En général, je conseille aux gens d'au moins desINCLUDE
colonnes d'uneWHERE
clause d' index filtré .Sur la base de la mise à jour de la requête et du plan d'exécution dans la question, je conviens que l'index plus général suggéré par SSMS est probablement le meilleur choix ici, à moins que la liste des filtrés ne
EventTypeIDs
soit statique comme Aaron le mentionne également dans sa réponse:Index suggéré (le déclarer unique si cela est approprié):
Informations de cardinalité du plan d'exécution (syntaxe non documentée, ne pas utiliser dans les systèmes de production):
Requête mise à jour (la répétition de la
IN
liste pour laEventType
table aide l'optimiseur dans ce cas spécifique):Plan d'exécution estimé:
Le plan que vous obtiendrez sera probablement différent, car j'utilise des statistiques devinées. L'idée générale est de fournir à l'optimiseur autant d'informations que possible et de fournir une méthode d'accès efficace (index) sur la
[Event]
table de 4 millions de lignes .la source
La majorité du coût est l'analyse d'index en cluster, et à moins que cette table ne soit vraiment large ou que vous n'ayez pas vraiment besoin de toutes ces colonnes dans la sortie, je crois que SQL Server est le chemin optimal dans le scénario actuel avec rien d'autre changé . Il utilise un balayage de plage (étiqueté comme une recherche de CI) pour réduire la plage de lignes qui l'intéresse, mais en raison de la sortie, il va toujours nécessiter une recherche ou un balayage de CI, même avec l'index filtré que vous avez créé qui est ciblé sur cette plage, et même dans ce cas, l'analyse CI est probablement toujours la moins chère (ou du moins SQL Server l'estime comme telle).
Le plan d'exécution vous dit que cet index serait utile:
Bien que selon votre asymétrie de données, il pourrait être préférable de l'inverse, par exemple:
Mais je testerais les deux pour être sûr de ce qui est le mieux, si l'un ou l'autre - la différence entre l'un de ces indices et ce que vous avez maintenant ne peut être que marginale (trop de variables pour que nous le sachions) et vous devez tenir compte du fait qu'un supplément l'index nécessite une maintenance supplémentaire, ce qui peut sensiblement affecter vos opérations DML (insérer / mettre à jour / supprimer). Vous pouvez également envisager d'inclure les critères de filtrage dans cet index comme suggéré par @SQLKiwi , mais uniquement s'il s'agit de l'ensemble de valeurs EventTypeID que vous recherchez fréquemment. Si cet ensemble change au fil du temps, l'index filtré ne sera utile que pour cette requête spécifique.
Avec un nombre de lignes aussi bas, je dois me demander à quel point les performances pourraient être mauvaises actuellement? Cette requête renvoie 3 lignes (mais il n'y a aucune indication du nombre de lignes qu'elle a rejetées). Combien de lignes dans le tableau?
la source
Je viens de découvrir que SQL Server 2008 R2 a effectivement fait une suggestion d'index lorsque j'ai exécuté le plan d'exécution. Cet index suggéré accélère l'exécution de la requête d'environ 90%.
L'indice qu'il a suggéré était le suivant:
la source