Drapeau vs séparation de table


10

Je suis en train de concevoir un tableau d'articles qui contiendra (potentiellement) des dizaines de millions d'enregistrements. Certains éléments ne seront pas disponibles jusqu'à ce qu'ils soient «approuvés» par l'administrateur. Par «utiliser», je veux dire que ces éléments ne seront référencés dans aucun autre tableau tant qu'ils ne seront pas «approuvés». Jusqu'à 50% des articles peuvent être «non approuvés» à tout moment. Les enregistrements peuvent devenir "approuvés", mais pas l'inverse.

Je considère deux options de conception:

  • un peu de drapeau
  • un tableau séparé des articles "non approuvés" - lorsque l'article est approuvé, il est déplacé vers le tableau "normal" (le renouvellement de l'ID de l'article n'est pas un problème)

Je pense que la deuxième option est bien meilleure. L'indicateur de bit ne prend qu'un octet par ligne, donc ce n'est pas un problème. Mais si nous avons un million d'enregistrements approuvés et un million d'enregistrements non approuvés dans le même tableau - le temps d'analyse augmente pour les opérations avec des enregistrements approuvés.

La question est: devrais-je considérer la première option (indicateur de bit) à la place? At-il des avantages dans la situation décrite?


1
Il peut être utile de se rappeler que vous pouvez utiliser des index filtrés pour accélérer l'accès aux enregistrements approuvés. brentozar.com/archive/2013/11/…
mendosi

Malheureusement, les index filtrés ne sont pas utilisés dans les requêtes paramétrées.
Dima

@Dima ce n'est pas tout à fait vrai. Si un index filtré a par exemple WHERE status='A'et une requête a WHERE status = 'A' AND (... other columns and parameters here...), l'indice pourrait encore être utilisé.
ypercubeᵀᴹ

Réponses:


6

Vous pouvez l'avoir dans les deux sens avec des vues partitionnées .

Vous créez une table sous-jacente pour chaque statut, imposée par des contraintes, avec des valeurs mutuellement exclusives. Puis une vue qui UNIONs ensemble les tables sous-jacentes. La vue ou chaque table de base peut être référencée explicitement. Si le statut d'une ligne est mis à jour via la vue, le SGBD la supprimera d'une table de base et l'insérera dans celle correspondant au nouveau statut. Chaque table de base peut être indexée indépendamment selon son modèle d'utilisation. L'optimiseur résoudra les références d'index à une seule table de base correspondante si c'est possible.

Les avantages sont
a) des indices moins profonds. Faites le calcul sur le fan-out d'index, cependant. À cette échelle et réparti entre vos valeurs de statut, il est possible que les index aient la même profondeur sur les tables fractionnées qu'ils le seraient sur la table combinée.
b) aucun code d'application ne doit changer. Les données continuent d'apparaître comme un tout continu.
c) de nouvelles valeurs de statut futures peuvent être incluses en ajoutant une nouvelle table de base, avec contrainte, et en recréant la vue.

Le coût est tout ce mouvement de données; deux pages et les index associés sont écrits pour chaque mise à jour de statut. Beaucoup d'E / S à gérer. Cette quantité de mouvements entraînera également une fragmentation.


5

un tableau d'articles qui contiendra (potentiellement) des dizaines de millions d'enregistrements.

Ce n'est en fait pas tant que ça, étant donné ce que SQL Server peut gérer efficacement. Bien sûr, je me souviens d'un de mes emplois précédents où l'une des plus grandes tables (un système à instance unique) avait 2 millions de lignes et c'était le plus que j'avais jamais traité. Ensuite, le travail suivant avait 17 instances de production avec certaines tables ayant des centaines de millions de lignes, et qui ont toutes été regroupées dans un entrepôt de données avec plusieurs tables de faits ayant plus d'un milliard de lignes. Ne vous méprenez pas, je ne me moque pas de dizaines de millions de lignes, je souligne simplement qu'avec un bon modèle de données et une indexation (et une maintenance d'index) appropriées, SQL Server peut gérer beaucoup .

Jusqu'à 50% des articles peuvent être «non approuvés» à tout moment.

Hmm. Cela ne semble pas juste. Le taux «d'approbation» des entrées sera la moitié du taux d'obtention de nouvelles entrées? Pour chaque 2 nouvelles entrées, une seule sera "approuvée"? Dans votre exemple de 2 millions de lignes, et 1 million chacune pour "approuvé" et "non approuvé", quelques années plus tard avec encore 10 millions d'entrées, vous vous attendez à 6 millions chacune pour "approuvé" et "non approuvé"? Ou est-ce que le 1 million "non approuvé" restera quelque peu constant, de sorte qu'avec 10 millions de nouvelles entrées, il y aura 11 millions "approuvé" et toujours 1 million "non approuvé"?

Les enregistrements peuvent devenir "approuvés", mais pas l'inverse.

C'est vrai aujourd'hui , mais les choses changent avec le temps et il y a donc toujours la possibilité que l'entreprise décide d'autoriser "non approuvé", ou peut-être un autre statut, comme "archivé", etc.

Alors, regardons les choix:

Drapeau (ou peut-être même TINYINT"statut")

  • Légèrement plus lent pour les requêtes de chaque statut
  • Plus flexible dans le temps / facile à incorporer un changement tel qu'un troisième état (par exemple "Archivé") avec seulement une nouvelle valeur de statut de recherche. Pas de nouvelle table (nécessairement), du nouveau code, seulement du code mis à jour.
  • Moins de travail (c.-à-d. Code, tests, etc.) et moins de place pour l'erreur de mise à jour d'une seule TINYINTcolonne
  • Moins compliqué = coûts de maintenance réduits au fil du temps, temps de formation plus court pour les nouveaux employés à comprendre
  • (éventuellement) Impact plus faible sur le journal des transactions car une table est mise à jour
  • Juste besoin d'une table de recherche pour "RecordStatus" et FK entre les deux tables.

Deux tableaux distincts (un pour «approuvé», un pour «non approuvé»)

  • Légèrement plus rapide pour les requêtes de chaque statut
  • Moins flexible dans le temps / plus difficile à incorporer un changement tel qu'un troisième état (par exemple "Archivé"); un nouvel état nécessiterait très probablement une autre table, et certainement un code nouveau et mis à jour.
  • Plus de travail (c.-à-d. Code, tests, etc.) et plus d'espace pour les erreurs de déplacement des enregistrements de la table "Non approuvé" vers la table "Approuvé"
  • Plus compliqué = coûts de maintenance plus élevés au fil du temps, temps de formation plus long pour les nouveaux employés à comprendre
  • (éventuellement) Plus grand impact sur le journal des transactions car une table est supprimée et une est insérée
  • Pas besoin de vous soucier du " renouvellement de l'ID de l'article ": la table non approuvée a une colonne ID qui est une IDENTITYcolonne, et la table approuvée a une colonne ID qui n'est pas une IDENTITY(car elle n'est pas nécessaire à cet endroit). Par conséquent, les valeurs d'ID restent cohérentes lorsque l'enregistrement se déplace entre les tables.

Personnellement, je me pencherais vers la table unique avec StatusIDcolonne pour commencer. L'utilisation de deux tables semble être une optimisation trop compliquée et prématurée. Ce type d'optimisation peut être discuté si / lorsque le nombre d'enregistrements est de plusieurs centaines de millions et que l' indexation n'apporte aucun gain de performances.


Il s'agit d'un tableau avec des données qui se déplacent rapidement: assez souvent rempli de nombreuses nouvelles lignes, très souvent les lignes sont supprimées. J'ai essayé de supprimer tous les détails (comme la décision commerciale, le codage client, etc.) pour me concentrer uniquement sur un seul sujet. Fondamentalement, nous avons la table de conception ancienne avec un drapeau peu. Et je sais pour 100% que les lignes où le drapeau est défini sur 1 ne sont jamais utilisées dans aucune autre table. J'ai donc l'impression qu'ils n'ont lieu que là-bas et peuvent être déplacés vers une table distincte. La table est analysée presque à chaque requête vers DB. Donc, réduire son "poids" peut potentiellement réduire les opérations CPU / IO.
Dima

3
Autre avantage des tables fractionnées: vous pouvez avoir des FK qui ne font référence qu'à la table "Approuvée".
ypercubeᵀᴹ

L'autre problème avec les tables fractionnées pour une seule entité est l'intégrité des contraintes. Les références provenant d'autres tables ne seront pas agréables lorsque l'enregistrement se déplacera. Cela nécessitera l'écriture de code pour contourner ces problèmes, tels que les tables de référence miroir pour la table fractionnée -> Très gênant
user1567453
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.