Que se passe-t-il lors des insertions «importantes» sur une table avec une clé composite en cluster?

8

Ma connaissance de SQL est limitée, donc les termes que j'utiliserai ne sont probablement pas les bons.

J'ai un tableau qui stockera les résultats des tests, pour plusieurs emplacements.

Les tests seront enregistrés dans différentes bases de données à différents emplacements (pas de connexion réseau) et l'emplacement «maître» importera régulièrement les résultats des tests des autres emplacements.

J'ai l'intention d'avoir une clé primaire composite en cluster sur les colonnes LocationId (int) et Date (datetime), dans cet ordre. Le raisonnement est qu'il devrait conserver tous les résultats d'un emplacement ensemble et je ne ferai presque jamais de requête par plage de dates, mais plutôt par plage de dates et par emplacement.

La taille des lignes sera de 80 à 100 octets et le nombre de résultats de test ne devrait pas dépasser quelques millions. Une "importation" typique insérera 50 à 100 milliers de résultats d'un autre emplacement.

Que se passera-t-il lors des importations? SQL "déplacera-t-il" les lignes existantes pour maintenir le clustering, ou laissera-t-il la table devenir "fragmentée"? Cela pourrait-il entraîner une baisse importante des performances si l'importation est effectuée une ligne à la fois? Dois-je plutôt ne pas me soucier de l'ordre des lignes et simplement ajouter une colonne d'identité comme clé primaire et un index sur la colonne Date pour aider avec mes requêtes?

Sacha K
la source

Réponses:

19

Sainte vache, vous avez beaucoup de questions ici. Décomposons cela.

Q: SQL "déplacera-t-il" les lignes existantes pour maintenir le clustering, ou laissera-t-il la table devenir "fragmentée"?

Considérez une base de données comme une collection de pages - des morceaux de papier littéraux disposés sur votre bureau. Pensez au dictionnaire pour l'instant. Si vous souhaitez ajouter plus de mots au dictionnaire, vous pouvez les ajouter en place si les pages ont un espace vide.

Lorsque vous commencez avec un dictionnaire vide, cela est relativement facile. Mais pensez à un dictionnaire mature avec des milliers de pages papier, toutes pleines.

Lorsque vous souhaitez ajouter plus de mots à ce dictionnaire mature, il y a de fortes chances qu'il ne reste plus d'espace sur la page. SQL Server "déchirera" une page - il faudra une nouvelle page ailleurs et déplacer certains des mots sur cette nouvelle page. La nouvelle page serait à la fin du dictionnaire. La bonne nouvelle est qu'immédiatement après cette action, il y a maintenant une page à moitié vide à la fin de votre dictionnaire, et aussi au milieu, toutes deux avec de l'espace pour ajouter des mots.

S'il vous arrive de les ajouter dans cet ordre, c'est. (C'est pourquoi la façon dont vous chargez les données devient de plus en plus importante.)

Cela pourrait-il entraîner une baisse importante des performances si l'importation est effectuée une ligne à la fois?

Oubliez l'index pendant une seconde - l'ajout de données une ligne à la fois est tout simplement inefficace quelle que soit la structure d'indexation. SQL Server est un système basé sur des ensembles - chaque fois que vous pouvez travailler dans des ensembles, vous devriez probablement le faire.

Que se passe-t-il lorsque je recherche les données?

Vous ne l'avez pas demandé, mais je vous le demande, hahaha.

Repensez aux conséquences de nos encarts. Nous avons maintenant un dictionnaire qui est généralement commandé, mais lorsque vous arrivez à quelques points du dictionnaire, vous devrez sauter vers l'arrière pour lire à partir de quelques autres pages. Si ces pages sont toutes mises en cache dans votre mémoire (RAM, pool de tampons, etc.), la surcharge ne va tout simplement pas être aussi importante. La plupart des accès à la mémoire sont aléatoires de toute façon - ce n'est pas comme si SQL Server stocke votre dictionnaire en mémoire dans l'ordre.

D'un autre côté, si vous devez récupérer les données à partir de disques durs magnétiques conventionnels (rouille tournoyante), vous pouvez finir par obtenir un petit avantage en termes de performances si ces données sont stockées dans l'ordre. Le véritable objectif de conception ici, cependant, est d'obtenir les données de la RAM au lieu de les obtenir des lecteurs. La différence entre les données défragmentées sur disque et les données fragmentées sur disque est loin d'être aussi importante que la différence entre les obtenir à partir du disque et les obtenir à partir de la RAM .

Dois-je plutôt ne pas me soucier de l'ordre des lignes et simplement ajouter une colonne d'identité comme clé primaire et un index sur la colonne Date pour aider avec mes requêtes?

Bingo: c'est la différence entre la conception d'une base de données physique et la conception d'une base de données logique. Les programmeurs doivent s'inquiéter beaucoup de la conception d'une base de données physique au départ, mais tant que votre base de données est inférieure, disons, à 100 Go, vous pouvez corriger la conception logique en post, pour ainsi dire. Mettez un champ d'identité là-bas pour commencer, regroupez-le, puis après avoir été en direct pendant quelques mois, revisitez la conception de l'index pour maximiser les performances.

Maintenant, cela dit, une fois que vous êtes expérimenté avec ce type de prise de décision, vous serez mieux équipé pour évaluer les indices dès le départ. Malgré cela, je ne pense même pas au début à la conception d'index. Les utilisateurs ne semblent jamais interroger les données comme je m'y attendais.

Brent Ozar
la source
1
L'encart un par un était une question théorique. Semblait douteux pour moi, en termes de performances, que "les lignes sont stockées physiquement sur le disque dans le même ordre que l'index clusterisé" comme vous le lisez dans la plupart des endroits.
Sacha K
J'irai pour une colonne d'identité. Les données seront ajoutées «à la fin» et naturellement triées par date. Les mêmes dates pour différents endroits ne seront pas «rapprochées», mais cela ne m'importe pas du tout.
Sacha K