web-dev-qa-db-fra.com

Favoriser l'immuabilité dans la conception de la base de données

L'un des éléments de Joshua Bloch's Efficace Java est la notion selon laquelle les classes doivent permettre la mutation des instances le moins possible et de préférence pas du tout.

Souvent, les données d'un objet sont persistées à une base de données de forme. Cela m'a amené à penser à l'idée d'immuabilité dans une base de données, en particulier pour les tables qui représentent une seule entité dans un système plus vaste.

Quelque chose que j'ai expérimenté récemment est l'idée d'essayer de minimiser les mises à jour que je fais pour table des lignes représentant ces objets et d'essayer d'effectuer des inserts autant que possible.

Un exemple concret de quelque chose que j'avais expérimenté récemment. Si je sais que je pourrais ajouter un enregistrement avec des données supplémentaires plus tard, je vais créer une autre table pour la représenter, en quelque sorte comme les deux définitions de table suivantes:

create table myObj (id integer, ...other_data... not null);
create table myObjSuppliment (id integer, myObjId integer, ...more_data... not null);

Espérons-le que ce soit évident que ces noms ne sont pas verbatim, mais simplement pour démontrer l'idée.

Est-ce une approche raisonnable de la modélisation de la persistance des données? Est-il à la peine d'essayer de limiter les mises à jour effectuées sur une table, en particulier pour le remplissage de NULLS pour les données qui pourraient ne pas exister lorsque l'enregistrement est créé à l'origine? Y a-t-il des moments où une approche comme celle-ci pourrait causer une douleur intense plus tard?

27
Ed Carrel

Le but principal de l'immutabilité est de veiller à ce qu'il n'y ait pas d'instant dans le temps lorsque les données de la mémoire sont dans un état invalide. (L'autre est que des notations mathématiques sont principalement statiques, et les choses extrêmement immuables sont plus faciles à conceptualiser et à modeler mathématiquement.) En mémoire, si un autre thread essaie de lire ou d'écrire des données pendant qu'il est fonctionnel, cela pourrait finir de manière corrompue, ou Cela pourrait être en état de corrompu. Si vous avez plusieurs opérations d'affectation dans les champs d'un objet, dans une application multithreadée, un autre thread pourrait essayer de travailler avec elle parfois entre - ce qui pourrait être mauvais.

L'immuabilité remède cela en écrivant d'abord toutes les modifications apportées à un nouvel endroit en mémoire, puis effectuez la mission finale comme une étape de réécriture de la réécriture du pointeur sur l'objet pour pointer vers le nouvel objet - qui sur tous les processeurs est un Fonctionnement Atomic .

Les bases de données font la même chose à l'aide transactions atomiques : Lorsque vous démarrez une transaction, il écrit toutes les nouvelles mises à jour d'un nouvel endroit sur disque. Lorsque vous avez terminé la transaction, il modifie le pointeur sur disque sur l'endroit où les nouvelles mises à jour sont - qu'elle fait dans un instant court au cours de laquelle d'autres processus ne peuvent pas le toucher.

C'est aussi la même chose que votre idée de créer de nouvelles tables, à l'exception plus automatique et plus flexible.

Donc, pour répondre à votre question, oui, l'immuabilité est bonne dans les bases de données, mais non, vous n'avez pas besoin de faire des tables séparées uniquement à cette fin. Vous pouvez simplement utiliser toutes les commandes de transaction atomique disponibles pour votre système de base de données.

25
Rei Miyasaka

Si vous êtes intéressé par les avantages, vous pouvez obtenir de l'immutabilité dans une base de données ou au moins une base de données offrant l'illusion de l'immutabilité, vérifiez Dateomic.

DATOMIC est une base de données inventée par Rich Hickey dans Alliance avec la pertinence de réflexion, il existe de nombreuses vidéos où elles expliquent l'architecture, les objectifs, le modèle de données. Rechercher l'infoQ, un en particulier est intitulé DaTomic, base de données en tant que valeur. Dans Confonfroms, vous trouverez une note claquement Riche Hickey donnée à la conférence Euroclojure en 2012. Confreaks.com/Videos/2077-Euroclojure2012-Day-2-keNote-the-Datomic-architecture-and-Data-Model

Il y a une conversation dans Vimeo.com/53162418, qui est plus orientée développement.

Voici un autre de Stuart Halloway at.pscdn.net/008/00102/Videoplatform/kv/121105Techconf_close.html

  • DATOMIC est une base de données de faits dans le temps, appelée Datums, dans 5-tuples [E, A, V, T, O] [.____]
    • [~ # ~] e [~ # ~ ~] ID d'entité
    • A Nom d'attribut dans l'entité (peut avoir des espaces de noms)
    • [~ # ~] v [~ # ~ ~] valeur de l'attribut
    • [~ # ~] t [~ # ~ ~] ID de transaction, avec cela, vous avez une notion de temps.
    • [~ # ~] o [~ # ~ ~] une opération d'affirmation (valeur actuelle ou actuelle), rejet (valeur passée);
  • Utilise son propre format de données, appelé EDN (notation de données extensible)
  • Les transactions sont acides
  • Utilise Datalog en tant que langue de requête, qui est déclarative sous forme de requêtes SQL + Rursive. Les requêtes sont représentées avec des structures de données et étendues avec votre langue JVM, vous n'avez pas besoin d'utiliser Robojure.
  • La base de données est découplée dans 3 services distincts (processus, machines):
    • Transaction
    • Espace de rangement
    • Moteur de requête.
  • Vous pouvez séparer séparément chaque service.
  • Ce n'est pas une source ouverte, mais il y a une version gratuite (comme dans la bière) de Datomic.
  • Vous pouvez indiquer un schéma flexible.
    • l'ensemble d'attributs est ouvert
    • ajouter de nouveaux attributs à tout moment
    • aucune rigidité de la définition ou de la requête

Maintenant, comme l'info est stockée en tant que faits à temps:

  • tout ce que vous faites est d'ajouter des faits à la base de données, vous ne les supprimez jamais (sauf lorsque la loi est requise)
  • vous pouvez tout cacher pour toujours. Moteur de requête, vit dans le serveur d'applications comme base de données de mémoire (pour les langues JVM langues non-JVM ayant accès via a REST API.)
  • vous pouvez interroger auparavant dans le passé.

La base de données est une valeur et un paramètre sur le moteur de requête, le QE gère la connexion et la mise en cache. Puisque vous pouvez voir la base de données comme valeur et structure de données immuable en mémoire, vous pouvez la fusionner avec une autre structure de données fabriquée à partir de valeurs "à l'avenir" et transmettez-la au QE & Requête avec les valeurs futures, sans changer la base de données réelle. .

Il y a un projet open source de Rich Hickey, appelé -Codeq, vous pouvez le trouver dans GitHub DaTomic/CodeQ, qui étend le modèle GIT et stocke des références aux objets GIT dans une base de données sans daomique et Faites des requêtes de votre code, vous pouvez voir un exemple comment utiliser Dateomic.

Vous pouvez penser à DATOMIC comme acide NOSQL, avec des données que vous pouvez modéliser des tables ou des documents ou des magasins KV ou des graphiques.

15
kisai

L'idée d'éviter les mises à jour et de préférer des insertions est l'une des pensées derrière la construction de votre stockage de données en tant que source d'événement, une idée que vous trouverez souvent avec les CQRS. Dans un modèle de source d'événement, il n'y a pas de mise à jour: un agrégat est représenté comme une séquence de sa "transformation" (événements) et, par conséquent, le stockage est uniquement ajouté.
[.____] - ce site contient des discussions intéressantes sur les CQRS et l'approvisionnement de l'événement, si vous êtes curieux de cela!

7
Mathias

Cela porte une relation très étroite avec ce que l'on appelle "des dimensions changeantes lentement" dans le monde de l'entreposage de données et des tables "temporelles" ou "bi-temporelles" dans d'autres domaines.

La construction de base est:

  1. Utilisez toujours une clé de substitution générée comme clé primaire.
  2. L'identifiant unique de tout ce que vous décrivez devient la "clé logique".
  3. Chaque rangée doit avoir au moins un horodatage "valide" et éventuellement un horodatage "validant" et encore plus éventuellement une "dernière version".
  4. Sur la "création" d'une entité logique, vous insérez une nouvelle ligne avec un "Valide de" de l'horodatage actuel. La validation optionnelle définie sur "Forever" (9999-12-31 23:59:59) et la dernière version à "True".
  5. Sur une mise à jour ultérieure de l'entité logique. Vous insérez au moins une nouvelle ligne comme ci-dessus. Vous devrez peut-être également régler la validation de la version précédente à "Now () - 1 seconde" et la dernière version à "False" [.____]
    1. Sur la suppression logique (cela ne fonctionne que avec le chyestamp ValidTo!) Vous définissez le drapeau validto dans la ligne actuelle sur "Now () -1 seconde".

Les avantages de ce système sont que vous pouvez recréer l'état de votre entité logique à tout moment, vous avez des antécédents de votre entité au fil du temps et que vous minimisez la conflit si votre "entité logique" est fortement utilisée.

Les inconvénients sont votre stockage beaucoup plus de données et vous devez maintenir plus d'index (à tout le moins sur la clé logique + validefrom + validto). Un index sur la clé logique + la dernière version accélère considérablement la plupart des requêtes. Il complique également votre SQL!

Que cela vaut la peine d'être effectué, sauf si vous avez vraiment besoin de maintenir une histoire et d'avoir une obligation de recréer l'état de vos entités à un moment donné à temps à vous.

6
James Anderson

Une autre raison possible de disposer d'une base de données immuable serait de soutenir un meilleur traitement parallèle. Les mises à jour que les mises à jour ne se produisent pas peuvent gâcher les données de manière permanente, alors le verrouillage doit donc se produire pour empêcher cela, détruisant des performances parallèles. Beaucoup d'inserts d'événements peuvent aller dans n'importe quel ordre, et l'état sera au moins finalement tant que tous les événements sont finalement traités. Cependant, il est si difficile de travailler dans la pratique par rapport à la pratique de mises à jour de la base de données que vous devriez avoir vraiment besoin de beaucoup de parallélisme pour envisager de faire des choses de cette façon - je suis non recommander.

1
psr

Disclaimer: Je suis à peu près un nouveau dans dB: p

Cela étant dit, cette approche des données satellisations a un impact immédiat sur la performance:

  • bon moins de trafic sur la table principale
  • Bien Rangements plus petits sur la table principale
  • mauvais nécessitant les données satellites signifie une autre recherche est nécessaire
  • mauvais Plus d'espace occupé si tous les objets existent dans les deux tables

selon vos besoins, vous pouvez vous accueillir ou non, mais c'est certainement un point à prendre en compte.

0
Matthieu M.