Lors de notre dernière réunion hebdomadaire, une personne qui n'a aucune expérience en administration de base de données a soulevé cette question:
"Y aurait-il un scénario qui justifie le stockage de données en ligne (chaîne) au lieu de plusieurs lignes?"
Supposons un tableau appelé countryStates
où nous voulons stocker les états d'un pays; J'utiliserai les États-Unis pour cet exemple et ne listerai pas tous les États par souci de paresse.
Là, nous aurions deux colonnes; l'un appelé Country
et l'autre appelé States
. Comme discuté ici , et proposé par la réponse de @ srutzky , le PK
sera le code défini par ISO 3166-1 alpha-3 .
Notre table ressemblerait à ceci:
+---------+-----------------------+-------------------------------------------------------+
| Country | States | StateName |
+---------+-----------------------+-------------------------------------------------------+
| USA | AL, CA, FL,OH, NY, WY | Alabama, California, Florida, Ohio, New York, Wyoming |
+---------+-----------------------+-------------------------------------------------------+
En posant cette même question à un ami développeur, il a dit que du point de vue de la taille du trafic de données, cela pourrait être utile, mais pas si nous devons manipuler ces données. Dans ce cas, il devrait y avoir une intelligence sur le code d'application qui pourrait transformer cette chaîne en liste (disons que le logiciel qui a accès à cette table doit créer une zone de liste déroulante).
Nous avons conclu que ce modèle n'est pas très utile, mais je me méfie qu'il pourrait y avoir un moyen de le rendre utile.
Ce que j'aimerais demander, c'est si l'un d'entre vous a déjà vu, entendu ou fait quelque chose comme ça d'une manière qui fonctionne vraiment .
la source
a;b;c
, utilisez l'avant pour analyser votre chaîne vous obtenez alorsa
,b
,c
et continuez l' exécution de faire quelque chose avec eux, peut - être ?. Sentez-vous que cela pourrait répondre à une sorte de besoin spécifique de cette façon ... À la réflexion, non. Vous pouvez toujours stocker des ID, rejoindre vos tables et créer une chaîne concaténée qui peut envoyer du contenu à la FE ...Réponses:
Pour commencer, le titre actuel de la question faisant référence au "stockage de données sous forme de chaîne au lieu de colonnes" est un peu déroutant. Lorsque vous parlez de stocker des données sous forme de chaînes au lieu de quelque chose d'autre, cela fait généralement référence à la sérialisation de tout dans un format de chaîne au lieu d'un type de données correct / fort (par exemple
INT
ouDATETIME
). Mais si vous vous interrogez sur le stockage de données sous forme de valeurs multiples dans un seul champ par opposition à des lignes distinctes, c'est un peu différent. Et pour être juste, bien que la concaténation de valeurs se fasse plus facilement avec des chaînes, elle peut également être effectuée avecINT
et desBINARY
types, soit en masquant les bits, soit en réservant de manière similaire certaines positions pour avoir des significations différentes. Étant donné que la deuxième interprétation est ce qui est réellement demandé, sur la base du texte de la Question, abordons cela.En un mot: Non. Si vous stockez des points de données réels, cela ne fera que causer de la douleur (en termes de code et de performances) car c'est une complication inutile. S'il s'agit d'une valeur qui ne sera jamais stockée que comme une seule unité, mise à jour comme une seule unité et jamais désassemblée dans la base de données, cela pourrait être correct car elle est à peu près analogue au stockage d'une image ou d'un PDF. Sinon, toute tentative d'analyse des données invalidera l'utilisation de tout index (par exemple en utilisant
LIKE '%something%'
, ouCHARINDEX
, ouPATINDEX
, ouSUBSTRING
, etc.).Si vous devez stocker des valeurs distinctes dans un seul champ d'une seule ligne, il existe des moyens plus appropriés de le faire: XML ou JSON. Ce sont des formats analysables ( XML / JSON ) et XML peut même être indexé . Mais idéalement, ces données seraient stockées dans des champs correctement saisis afin de pouvoir être vraiment utiles.
Et n'oubliez pas que le but d'un SGBDR est de stocker des données de manière à ce qu'elles puissent être récupérées et manipulées aussi efficacement que possible, dans les limites imposées par la conformité avec ACID . La récupération des valeurs concaténées est suffisamment mauvaise en raison de la nécessité d'analyser les valeurs en premier, et cela n'est pas indexable. Mais manipuler signifie souvent remplacer l'intégralité du blob juste pour en mettre à jour une partie (en supposant qu'il n'existe aucun modèle à utiliser avec une
REPLACE
fonction). Le type de données XML autorise au moins XML DML pour les mises à jour simplistes, bien que celles-ci ne soient toujours pas aussi rapides qu'une simple mise à jour de données correctement modélisées.De plus, étant donné un scénario tel que ce qui est montré dans la question ci-dessus, en concaténant tous les StateCodes ensemble, vous ne pourriez pas clé étrangère (dans les deux sens) ces valeurs.
Et que se passe-t-il si les exigences commerciales changent au fil du temps et que vous devez suivre les propriétés supplémentaires de ces éléments? En termes d '«États», qu'en est-il des capitales, ou de la population, ou d'un ordre de tri, ou autre chose? Stocké correctement en tant que lignes, vous pouvez ajouter plus de colonnes pour des propriétés supplémentaires. Bien sûr, vous pouvez avoir plusieurs niveaux de données analysables, comme,
|StateCode,Capital,Population |StateCode,Capital,Populate|...
mais avec un peu de chance, tout le monde peut voir le problème se développer de manière exponentielle hors de contrôle. Bien sûr, ce problème particulier est assez facilement traité avec les formats XML et JSON, et c'est leur valeur, comme mentionné ci-dessus. Mais vous auriez toujours besoin d'une très bonne raison d'utiliser l'un ou l'autre comme moyen initial de modélisation, car aucun ne sera jamais aussi efficace que l'utilisation de champs discrets sur des lignes distinctes.la source
J'ai effectivement utilisé quelque chose comme ça dans un but très limité. Nous avons créé un tableau d'en-têtes pour les fichiers de sortie. Ils ont été spécifiquement construits et n'étaient pour la plupart que des en-têtes de colonnes, mais pas tout à fait. Donc, les données ressemblaient à quelque chose
Il ressemblait essentiellement à une liste délimitée. Et d'une certaine façon, ça l'était. Mais pour nous, c'était une seule longue chaîne.
Voilà l'astuce ici. Si vous ne prévoyez jamais d'analyser la liste, cela vaut la peine d'enregistrer la liste. Si toutefois vous avez besoin ou même besoin d'analyser la liste, cela vaut la peine d'avoir plus d'espace et de temps pour la diviser et l'enregistrer dans des lignes distinctes.
la source
Je l'ai utilisé une fois avec une table plutôt petite, par exemple:
Et puis stocker les valeurs
CRM,SMS,SELF-CARE
dansvalid_channel
.La table entière a quelque chose comme 10 enregistrements.
valid_channel
contient des valeurs qui devraient en fait se trouver dans une table de liaison qui décrit la relation plusieurs-à-plusieurs. La tablet1
ne va pas être utilisée de manière intensive, nous avons donc décidé de suivre cette voie. Certaines politiques ont cependant été impliquées dans cette décision (voir ci-dessous).Mais en général je l'évite, ce n'est pas 3NF.
L'endroit où je travaille actuellement a des dizaines de telles colonnes partout. Leur justification est que cela rend leurs requêtes plus faciles: au lieu de joindre trois tables à l'aide de la table de liaison, elles peuvent aller directement à la table de définition
LIKE
. Par exempleHorrible + sur Oracle, il désactive l'utilisation de l'index en raison du démarrage
'%,'
.la source
LIKE
ou une simple jointure?LIKE
serait plus lent, surtout si les données sont correctement modélisées pour utiliser unTINYINT
champ PK danschannel_def
. Il suffit ensuite de comparer un seul octet entre les deux tables. Ici, il doit analyser la chaîne, caractère par caractère (au moins jusqu'à ce que la condition soit remplie), et il effectue une recherche insensible à la casse (basée sur la table donnée def ne montrant pas de_BIN2
classement utilisé). Cela invalide également les index sur SQL Server. J'ai résolu ce problème dans ma réponse en disant que l'analyse syntaxique ne peut pas utiliser d'index. Je viens de mettre à jour ma réponse pour la rendre plus claire.LIKE
clause et ne produisait pas de résultats étranges, elle pouvait toujours causer d'autres problèmes ou au moins rendre le débogage plus difficile / plus long). Cela rend également la mise à jour duvalid_channels
champ plus compliquée. Cela ne veut pas dire que cela ne fonctionne pas, il n'y a tout simplement aucune bonne raison de le faire.Cela a été fait ici sur SE. Comme l' écrit Marc Gravell :
Ce "nouveau format" était la prochaine étape de "l'ancien format" qui était un peu différent et a été choisi pour utiliser la fonction de recherche de texte intégral de SQL Server, donc certains des avantages ne sont pas pertinents si vous le faites à partir de zéro.
Ils n'ont vraisemblablement pas complètement normalisé la chose à la fois pour la quantité de travail et pour des raisons de performance.
la source
Eh bien, l'un des principaux avantages possibles de l'utilisation de chaînes et d'autres types de données est de les envoyer de SQL Server à C #, C, C ++ (etc.) à l'aide de SQLCLR lorsque des performances absolues peuvent être nécessaires. Vous pouvez même créer une vue ou une procédure stockée pour représenter des données relationnelles de manière non relationnelle - comme vous l'avez fait avec votre exemple ci-dessus à cet effet.
Voir cet exemple:
http://aboutsqlserver.com/2013/07/22/clr-vs-t-sql-performance-considerations/
par Wikipedia: SQL CLR ou SQLCLR (SQL Common Language Runtime) est une technologie pour l'hébergement du moteur d'exécution de langage commun Microsoft .NET dans SQL Server. Le SQLCLR permet au code managé d'être hébergé et exécuté dans l'environnement Microsoft SQL Server.
la source
À mon avis, la réponse serait non. Je n'ai pas utilisé cette approche et je l'éviterais - je ne peux pas penser à une raison pour laquelle je choisirais cette voie. Vous vous penchez vers le monde de JSON / NoSQL avec un tableau.
Nous avions des choix de conception similaires dans un rôle précédent où l'équipe d'architectes voulait avoir un champ "Données" qui était délimité puis converti en binaire. Nous n'avons finalement pas choisi cette voie pour plusieurs raisons.
Si vous deviez vous joindre à ce type de données, ce serait une expérience laide. La mise à jour d'éléments uniques de la chaîne serait également désagréable.
la source