Que gagnent les bases de données relationnelles en définissant un type de données prédéfini pour chaque colonne?

44

Je travaille actuellement avec une base de données SQL, ce qui m'a toujours rendu curieux, mais les recherches sur Google ne sont pas très révélatrices: pourquoi les types de données stricts?

Je comprends pourquoi vous avez plusieurs types de données différents, par exemple, il est important de différencier les données binaires des données en texte brut . Plutôt que de stocker les 1 et les 0 des données binaires en texte clair, je comprends maintenant qu'il est plus efficace de stocker les données binaires dans leur propre format.

Mais ce que je ne comprends pas, c’est l’intérêt d’avoir autant de types de données différents:

  • Pourquoi mediumtext, longtextet text?
  • Pourquoi decimal, floatet int?
  • etc.

Quel est l'avantage de dire à la base de données "Il n'y aura que 256 octets de données en texte brut dans les entrées de cette colonne." ou "Cette colonne peut contenir jusqu'à 16 777 215 octets de texte"?

Est-ce un avantage de performance? Si oui, pourquoi connaître la taille de l'entrée avant la main contribue-t-il à la performance? Ou plutôt est-ce autre chose?

John Doe
la source
2
Je pensais que cette question devrait déjà exister ici, mais j'ai cherché sur le site et je n'ai rien trouvé d'utile.
John Doe
1
Très pertinent: joelonsoftware.com/2001/12/11/back-to-basics
8bittree
6
Si vous n'avez pas distincts decimal, floatet les inttypes, que voulez - vous attendre 1 / 3à faire? Qu'en est- il 1.0 / 3.0? Pouvez-vous avoir la certitude que lorsque vous divisez columnApar columnBce résultat, vous obtiendrez les résultats escomptés?
Andrew dit de réintégrer Monica
2
@johndoe Je ne pense pas que cela soit nécessaire, mais cela pourrait être très pratique. Supposons que vous souhaitiez imposer une contrainte selon laquelle l'inventaire d'un magasin ne peut être inférieur à 5% de ses ventes mensuelles prévues. Ou vous voulez vous assurer que le budget total de chaque division ne dépasse pas 20% du budget total. Il peut également apparaître dans les colonnes calculées que vous souhaitez calculer de la même manière dans plusieurs applications utilisant la même base de données.
Andrew dit de réintégrer Monica
2
Il est à noter que SQLite ne définit pas de type prédéfini par colonne : "SQLite est" sans type ", ce qui signifie que vous pouvez stocker n'importe quel type de données que vous souhaitez dans n'importe quelle colonne d'une table, quel que soit le type de données déclaré de cette colonne. "
Premier

Réponses:

50

SQL est un langage à typage statique . Cela signifie que vous devez savoir de quel type est une variable (ou un champ, dans ce cas) avant de pouvoir l'utiliser. C'est le contraire des langages à typage dynamique, où ce n'est pas nécessairement le cas.

À la base, SQL est conçu pour définir des données ( DDL ) et des données d'accès ( DML ) dans un moteur de base de données relationnelle . Le typage statique présente plusieurs avantages par rapport au typage dynamique pour ce type de système.

  • Les index , utilisés pour accéder rapidement à des enregistrements spécifiques, fonctionnent vraiment bien lorsque la taille est corrigée. Prenons une requête qui utilise un index, éventuellement avec plusieurs champs: si les types de données et les tailles sont connus à l'avance, je peux très rapidement comparer mon prédicat (clause WHERE ou critères JOIN) aux valeurs de l'index et rechercher plus rapidement les enregistrements souhaités. .

  • Considérons deux valeurs entières . Dans un système de type dynamique, ils peuvent être de taille variable (par exemple, Java BigIntegerou les entiers intégrés à précision arbitraire de Python). Si je veux comparer les entiers, je dois d'abord connaître leur longueur en bits. C'est un aspect de la comparaison d'entiers qui est en grande partie masqué par les langages modernes, mais qui est très réel au niveau du processeur. Si les tailles sont fixes et connues à l'avance, une étape entière est supprimée du processus. Encore une fois, les bases de données sont censées pouvoir traiter des millions de transactions le plus rapidement possible. La vitesse est roi.

  • SQL a été conçu dans les années 1970. Au début de la micro-informatique, la mémoire était rare. La limitation des données a permis de contrôler les exigences de stockage. Si un entier ne dépasse jamais un octet, pourquoi lui allouer plus de stockage? C'est un espace perdu à l'ère de la mémoire limitée. Même à l’époque moderne, ces octets supplémentaires perdus peuvent s’additionner et nuire aux performances du cache du processeur. N'oubliez pas que ces moteurs de base de données peuvent traiter des centaines de transactions par seconde, et pas uniquement votre petit environnement de développement.

  • Dans les limites du stockage limité, il est utile de pouvoir stocker un seul enregistrement dans une seule page en mémoire. Une fois que vous avez parcouru une page, il y a plus de pages manquées et un accès plus lent à la mémoire. Les nouveaux moteurs ont des optimisations pour réduire ce problème, mais ils sont toujours là. En dimensionnant les données de manière appropriée, vous pouvez atténuer ce risque.

  • Plus encore dans les temps modernes, SQL est utilisé pour brancher à d' autres langues via ORM ou ODBC ou d' une autre couche. Certains de ces langages ont des règles pour exiger des types forts et statiques. Il est préférable de se conformer aux exigences plus strictes, car les langages à typage dynamique peuvent traiter les types statiques plus facilement que l'inverse.

  • SQL prend en charge le typage statique car les moteurs de base de données en ont besoin pour leur performance, comme indiqué ci-dessus.

Il est intéressant de noter qu'il existe des implémentations de SQL qui ne sont pas fortement typées. SQLite est probablement l'exemple le plus populaire d'un tel moteur de base de données relationnelle. Là encore, il est conçu pour une utilisation mono-thread sur un seul système, de sorte que les problèmes de performances risquent de ne pas être aussi prononcés que, par exemple, dans une base de données Oracle d'entreprise traitant des millions de demandes par minute.

Gruszczy
la source
SQLite a des types de données qui distinguent les données numériques des données textuelles, mais il n’ya
FrustratedWithFormsDesigner
1
@FrustratedWithFormsDesigner Je le sais, mais il est loin d'être aussi strict que des moteurs comme SQL Server, Oracle ou PostgreSQL.
Non seulement le SQL est typé de manière statique - en raison de la présence de contraintes de vérification, il supporte efficacement les types de raffinement.
Gardenhead
4
Bien que cela soit impliqué dans le premier point Indexes, il est plus simple de dire : avoir un type de données permet au moteur de base de données de donner un sens aux données , d'effectuer des comparaisons (nombres plus grands / plus petits, dates antérieures / ultérieures, avant / après dans l'alphabet), et permet donc le tri et l'interrogation .
Basil Bourque
Donc, si les tailles sont importantes ... et que SQL doit savoir à l'avance ... quelle est la taille exacte d'une transaction en "Zillion"?
WernerCD
24

Premièrement: le texte brut est binaire (ce ne sont même pas les caractères UTF8 ou ASCII "0" et "1" mais les bits d'activation / désactivation réels)

Cela dit, certaines des raisons sont:

  • Contraintes métier / conception: autoriser le nombre 7626355112 dans la colonne HEIGHT du tableau PERSON serait erroné. Autoriser "Howya" dans la colonne DATE d'une FACTURE serait une erreur.
  • Moins de code source d'erreurs: vous n'avez pas à écrire de code pour vous assurer que les données extraites d'une colonne de date sont bien une date. Si les types de colonne étaient dynamiques, vous devrez effectuer de nombreuses vérifications de type lors de leur lecture.
  • Efficacité du calcul: si une colonne est de type INTEGER et que vous l’êtes SUM (), le SGBDR n’a pas à appliquer de calcul arithmétique à virgule flottante.
  • Efficacité du stockage: déclarer qu'une colonne est VARCHAR (10) permet au SGBDR d'allouer de l'espace plus précisément.
  • Intégrité référentielle et unicité: les PK (ou FK) d'une table ne doivent pas autoriser les flottants, car l'égalité en virgule flottante est délicate. Vous devez donc les déclarer dans un type non flottant, comme des caractères ou des entiers.
  • Il existe des SGBDR avec des types de colonnes dynamiques (non stricts) (SQLite) . Il utilise le concept de "type d'affinité" tout en vous permettant d'insérer pratiquement n'importe quoi dans n'importe quelle colonne sans vous plaindre. Il y a des compromis qui ne seront pas discutés ici. Voir cette question .
Tulains Córdova
la source
8

C'est pour que le code sous-jacent dans lequel la base de données est écrite puisse allouer et utiliser des enregistrements de taille fixe. S'il sait qu'un champ spécifique peut contenir de 0 à 256 caractères de texte, il peut allouer un bloc de 256 octets pour le stocker.

Cela accélère considérablement les choses. Par exemple, vous n'avez pas besoin d'allouer de mémoire supplémentaire à la saisie du type d'utilisateur, puisqu'un champ donné commence toujours x octets dans l'enregistrement. Une recherche ou une sélection sur ce champ sait qu'il faut toujours vérifier x octets dans chaque enregistrement, etc.

Steve Barnes
la source
Si seulement toutes les réponses pouvaient être aussi concises et pertinentes ...
Darren Ringer
6

Lorsque des types définis sont attribués aux colonnes d'une base de données, ceux-ci sont généralement définis comme ayant une certaine taille en bits. Par conséquent:

1) lorsque le moteur de base de données parcourt les lignes d'une table, il n'a pas à effectuer d'analyse élémentaire pour déterminer la fin de chaque enregistrement; il peut simplement savoir que chaque ligne est composée de 32 octets, par exemple, et donc enregistrement suivant, il suffit d’ajouter 32 octets à l’emplacement actuel des enregistrements.

2) lors de la recherche d'un champ dans une ligne, il est possible de connaître à nouveau le décalage exact pour ce champ sans rien analyser, de sorte que les recherches de colonne sont une simple opération arithmétique plutôt qu'une opération de traitement de données potentiellement coûteuse.

Utilisateur non trouvé
la source
Les champs de longueur fixe peuvent rendre le traitement plus efficace en raison de la longueur d'enregistrement et des décalages de champ cohérents, mais les champs de longueur variable peuvent annuler ces avantages, car la longueur d'enregistrement et le décalage des champs peuvent varier. De même, la compression au niveau de l'enregistrement aboutira à des enregistrements de longueur variable, de sorte que l'emplacement d'un enregistrement donné ne peut pas simplement être calculé.
Zenilogix
C’est vrai, et il était conseillé depuis longtemps d’éviter les champs de longueur variable pour cette raison. Je ne sais pas comment les gros joueurs y parviennent, mais il semble que vous pourriez être en mesure de reconquérir certains des avantages de la longueur fixe en faisant en sorte que le moteur stocke des champs de largeur variable dans une table non visible par l'utilisateur ou un bloc de mémoire. La représentation des tables primaires de ces champs soit un "pointeur" (à largeur fixe). Considérant que vous devriez effectuer régulièrement des analyses complètes des champs de longueur variable, le succès de l'indirection pourrait valoir la peine de conserver des largeurs fixes.
UserNotFound
3

Vous avez demandé pourquoi les SGBD ont des types de données statiques.

  1. Vitesse de recherche. L'intérêt d'un SGBD est de stocker beaucoup plus de données que vous ne pourriez en charger dans un programme. Pensez "à tous les bordereaux de carte de crédit générés dans le monde au cours des dix dernières années". Afin de rechercher efficacement ces données, les types de données de longueur fixe sont utiles. Cela est particulièrement vrai pour les données structurées telles que les horodatages et les numéros de compte. Si vous savez à quoi vous avez à faire à l'avance, il est plus facile de charger des index efficaces.

  2. Intégrité et contraintes. Il est plus facile de garder les données pures si elles ont des types de données fixes.

  3. Histoire. Les SGBDR ont été lancés alors que les ordinateurs ne disposaient que de quelques mégaoctets de RAM et que le stockage à l'échelle du téraoctet était extrêmement coûteux. Économiser une douzaine d'octets dans chaque ligne d'un tableau pourrait vous faire économiser des milliers de dollars et des heures de temps dans de telles circonstances.

  4. La malédiction de la clientèle. Les SGBDR sont aujourd'hui des progiciels très complexes, hautement optimisés et utilisés depuis des décennies pour accumuler des données. Ils sont matures. Ils travaillent. Un crash de SGBDR entraînant une perte de données à grande échelle est extrêmement rare de nos jours. Passer à quelque chose avec un système de saisie de données plus flexible ne vaut pas le coût ou le risque pour la plupart des organisations.

Analogie: il peut sembler évident que les réseaux de métro urbains fonctionneraient mieux (plus silencieux, plus rapidement, plus économes en énergie) avec un écartement de rail plus étroit. Mais comment allez-vous changer tous les rails du métro de la ville de New York pour réaliser ces améliorations? Vous n'êtes pas, alors vous optimisez ce que vous avez.

O. Jones
la source
3

En général, plus la base de données est informée de manière détaillée de ce que vous stockez, plus elle peut essayer d'optimiser diverses métriques de performance associées à ces données, telles que l'espace alloué sur le disque ou la mémoire allouée lors de l'extraction. .

Pourquoi mediumtext, longtext et text?

Vous ne savez pas quelle base de données vous utilisez , je vais donc devoir deviner: je suppose que deux de ces types de données ont des limites supérieures, mais pas l'un d'entre eux. L'utilisation de types de données pour le texte ayant des limites supérieures indique à la base de données l'espace de stockage nécessaire pour chaque enregistrement. Il est également possible que certaines bases de données aient différentes manières de stocker du texte volumineux (éventuellement illimité) par rapport à du texte de longueur fixe réduite (cela peut varier en fonction de la base de données, consultez votre manuel pour en savoir plus sur le vôtre).

Pourquoi décimal, float et int?

Différents niveaux de précision requièrent différentes quantités de stockage et chaque utilisation ne requiert pas le plus haut degré de précision. Par exemple, voir ici: https://docs.oracle.com/cd/B28359_01/server.111/b28286/sql_elements001.htm#SQLRF50950

Oracle propose un grand nombre de types numériques différents avec des exigences de stockage différentes et des capacités différentes en termes de niveau de précision et de taille du nombre pouvant être représentés.

FrustratedWithFormsDesigner
la source
2

Dans une certaine mesure, c'est historique.

Il était une fois des données tabulaires stockées dans des fichiers composés d’enregistrements de longueur fixe, eux-mêmes composés de champs prédéfinis, de sorte qu’un champ donné était toujours du même type et se trouvait au même endroit dans chaque enregistrement. Cela rend le traitement efficace et limite la complexité du codage.

Ajoutez des index à un tel fichier et vous avez le début d’une base de données relationnelle.

Au fur et à mesure de l'évolution des bases de données relationnelles, elles ont commencé à introduire davantage de types de données et d'options de stockage, notamment des champs de texte ou des champs binaires de longueur variable. Mais cela introduit des enregistrements de longueur variable et empêche de localiser les enregistrements de manière cohérente via des calculs ou des champs via un décalage fixe. Peu importe, les machines sont beaucoup plus puissantes aujourd'hui qu'elles ne l'étaient à l'époque.

Il est parfois utile de définir une taille spécifique pour un champ afin d’appliquer un peu de logique commerciale, par exemple 10 chiffres pour un numéro de téléphone nord-américain. La plupart du temps, il ne s'agit que d'un peu d'héritage informatique.

Zenilogix
la source
1

Si une base de données utilise des enregistrements de taille fixe, tout enregistrement de la base de données continuera à tenir dans le même emplacement, même si son contenu est modifié. En revanche, si une base de données essaie de stocker des enregistrements en utilisant exactement la quantité de stockage nécessaire pour leurs champs, changer le nom d'Emma Smith en Emma Johnson peut rendre son enregistrement trop volumineux pour tenir dans son emplacement actuel. Si l'enregistrement est déplacé vers un emplacement disposant de suffisamment de place, tout index permettant de savoir où il se trouve doit être mis à jour pour refléter le nouvel emplacement.

Il existe plusieurs moyens de réduire les coûts associés à ces mises à jour. Par exemple, si le système gère une liste de numéros d’enregistrement et d’emplacements de données, cette liste sera la seule chose qui devra être mise à jour si un enregistrement est déplacé. Malheureusement, ces approches ont toujours un coût important (par exemple, pour garder une correspondance entre les numéros d'enregistrement et les emplacements, la récupération des enregistrements nécessiterait une étape supplémentaire pour extraire les données associées à un numéro d'enregistrement donné). Utiliser des enregistrements de taille fixe peut sembler inefficace, mais cela simplifie beaucoup les choses.

supercat
la source
1

Pour beaucoup de ce que vous faites en tant que développeur web, il n'est pas nécessaire de comprendre ce qui se passe "sous le capot". Cependant, il y a des moments où cela aide.

Quel est l'avantage de dire à la base de données "Il n'y aura que 256 octets de données en texte brut dans les entrées de cette colonne." ou "Cette colonne peut contenir jusqu'à 16 777 215 octets de texte"?

Comme vous le soupçonnez, la raison est liée à l'efficacité. Les abstractions fuient . Une requête similaire SELECT author FROM bookspeut être exécutée assez rapidement lorsque la taille de tous les champs de la table est connue.

Comme le dit Joël,

Comment une base de données relationnelle est-elle implémentée SELECT author FROM books? Dans une base de données relationnelle, chaque ligne d'une table (par exemple, la table des livres) a exactement la même longueur en octets et chaque champ est toujours à un décalage fixe par rapport au début de la ligne. Ainsi, par exemple, si chaque enregistrement de la table des livres a une longueur de 100 octets et que le champ auteur a le décalage 23, les auteurs sont stockés aux octets 23, 123, 223, 323, etc. Quel est le code à déplacer l'enregistrement suivant dans le résultat de cette requête? En gros, c'est ça:

pointer += 100;

Une instruction du processeur. Faaaaaaaaaaast.

La plupart du temps, vous travaillez assez loin des fondements essentiels pour que vous n'ayez pas besoin de vous en soucier. En tant que développeur Web basé sur PHP, vous souciez- vous du nombre d'instructions de processeur utilisées par votre code? La plupart du temps, non, pas vraiment. Mais il est parfois utile de savoir, pour deux raisons: cela peut expliquer les décisions prises par vos bibliothèques; et parfois vous devez vous soucier de la vitesse dans votre propre code.

Trigonométrie
la source