Quintet au lieu de Byte - approche de stockage et de récupération des données

Quintet est un moyen de présenter des données atomiques indiquant leur rôle dans le domaine des affaires. Les quintettes peuvent décrire n'importe quel élément, tandis que chacun d'eux contient des informations complètes sur lui-même et ses relations avec les autres quintettes. Cette description ne dépend pas de la plateforme utilisée. Son objectif est de simplifier le stockage des données et d'améliorer la visibilité de leur présentation.



Nous discuterons d'une approche de stockage et de traitement des informations et partagerons quelques réflexions sur la création d'une plateforme de développement dans ce nouveau paradigme. Pourquoi? Pour développer des itérations plus rapides et plus courtes: esquissez votre projet, assurez-vous qu'il correspond bien à ce que vous pensiez, affinez-le, puis affinez le résultat.

Le quintet a des propriétés: type, valeur, parent et ordre parmi les pairs. Ainsi, il y a 5 composants dont l'identifiant. Il s'agit de la forme universelle la plus simple pour enregistrer des informations, une nouvelle norme qui pourrait répondre à toutes les exigences de programmation. Les quintets sont stockés dans le système de fichiers de la structure unifiée, dans une masse indexée homogène continue de données. Le modèle de données de quintet - un modèle de données qui décrit toute structure de données comme une liste interconnectée unique de types de base et de termes basés sur eux (métadonnées), ainsi que des instances d'objets stockés conformément à ces métadonnées (données).

Une demi-minute de paroles
De nos jours, il existe un nombre infini de normes pour enregistrer des données, de nombreuses approches et règles, dont la connaissance est nécessaire pour travailler avec ces enregistrements. Les normes sont décrites séparément et ne se rapportent pas directement aux données correspondantes. Dans le cas des quintets, en prenant l'un d'entre eux, vous pouvez obtenir des informations pertinentes sur sa nature, ses propriétés et ses règles de traitement dans le domaine d'activité de l'utilisateur. Son standard est unifié et fixe pour tous les domaines. Le quintette est caché à l'utilisateur - les métadonnées et les données sont disponibles pour ce dernier d'une manière compréhensible commune.

Le quintet n'est pas seulement une information, il pourrait également représenter du code exécutable. Mais surtout, ce sont les données que vous souhaitez enregistrer, stocker et récupérer. Puisque dans notre cas les quintets sont directement adressables, interconnectés et indexés, nous les stockerons dans une sorte de base de données.


Pourquoi Quintet au lieu de Byte?


Pas de bit ou d'impulsion électronique qui orientent le spin magnétique.

Nous sommes habitués à mesurer les données en octets, qu'il s'agisse d'un document ou d'une photo, d'une limite de trafic Internet ou de l'espace disponible sur votre appareil mobile. Nous proposons une autre mesure - Quintet - qui n'a pas une taille fixe comme Byte, mais représente une quantité atomique de données, qui a une certaine valeur pour l'utilisateur.

Par exemple, vous pouvez dire que votre base de données occupe 119 mégaoctets de stockage ou vous pouvez déclarer que cette base de données stocke 1,37 méga-quintets. Peu vous importe ce qu'est un octet dans ce contexte, mais vous comprenez que cette base de données contient 1,37 million de vos descriptions de termes, objets, leurs attributs, liens, événements, requêtes avec leurs détails, etc. Posséder 1,37 million de précieuses données semble plus sexy que d'avoir 119 mégaoctets de données sur vous.

Ainsi, il ne s'agit pas de remplacer la façon dont les informations sont stockées sur le support de données, mais de passer à un autre niveau d'abstraction.

Structure du quintette


L'idée principale de cet article est de remplacer les types de machines par des termes humains et de remplacer les variables par des objets. Pas par les objets qui ont besoin d'un constructeur, d'un destructeur, d'interfaces et d'un garbage collector, mais par des unités d'informations claires qu'un client gère. Autrement dit, si le client dit "Client", alors pour sauvegarder l'essence de cette déclaration sur le support ne nécessiterait pas l'expertise d'un programmeur.



Il est logique de concentrer l'attention de l'utilisateur uniquement sur la valeur de l'objet, tandis que son type, son parent, son ordre (entre égaux en subordination) et son identifiant doivent être évidents d'après le contexte ou simplement cachés. Cela signifie que l'utilisateur ne sait rien du tout sur les quintettes, il donne simplement une tâche, s'assure qu'elle est acceptée correctement, puis démarre son exécution.

Concepts de base


Il existe un ensemble de types de données que tout le monde comprend: chaîne, nombre, fichier, texte, date, etc. Un ensemble aussi simple suffit pour esquisser la solution et la "programmer" avec les termes nécessaires à sa mise en œuvre. Les types de base représentés par des quintets peuvent ressembler à ceci:



Dans ce cas, certains des composants du quintet ne sont pas utilisés, tandis que le quintet lui-même est utilisé comme type de base. Cela facilite la navigation du noyau du système lors de la collecte des métadonnées.

Le fond


En raison de l'écart analytique entre l'utilisateur et le programmeur, une déformation importante des concepts se produit au stade de la description d'un projet. L'euphémisme, l'incompréhensibilité et l'initiative non sollicitée transforment souvent une idée simple et raisonnable du client en un gâchis logiquement impossible, si elle est évaluée du point de vue de l'utilisateur.



Le transfert de connaissances devrait se produire sans perte ni distorsion. Par ailleurs, en organisant le stockage de ces connaissances, mieux vaut se débarrasser des restrictions imposées par le système de gestion des données choisi.

Comment nous stockons les données maintenant


En règle générale, il existe de nombreuses bases de données sur le serveur; chacun d'eux contient une description du schéma de données avec un ensemble spécifique de détails - des données interconnectées logiquement. Ils sont stockés sur le support de données dans un ordre spécifique, idéalement - optimal pour réduire les efforts de récupération.
Le système de stockage d'informations proposé est un compromis entre diverses méthodes bien connues: orientée colonne, relationnelle et NoSQL. Il est conçu pour résoudre les tâches généralement effectuées par l'une de ces approches.

Par exemple, la théorie du SGBD orienté colonnes est magnifique: nous lisons uniquement la colonne souhaitée, mais pas toutes les lignes d'enregistrements dans leur ensemble. Cependant, dans la pratique, il est peu probable que des données soient placées sur le support de sorte qu'il soit pratique de récupérer des dizaines de dimensions analytiques différentes. Notez que les attributs et les mesures analytiques peuvent être ajoutés et supprimés, parfois plus rapidement que nous ne pouvons reconstruire notre stockage en colonnes. Sans oublier que les données de la base de données peuvent être modifiées, ce qui violera également la beauté du schéma de stockage en raison de la fragmentation inévitable.

Métadonnées


Nous avons introduit un concept - un terme - pour décrire tous les objets avec lesquels nous opérons: entité, propriété, requête, fichier, etc. Nous définirons tous les termes que nous utilisons dans notre domaine d'activité. Et avec leur aide, nous décrirons toutes les entités qui ont des détails, y compris la forme des relations entre les entités. Par exemple, un attribut - un lien vers une entrée du dictionnaire d'état. Le terme est écrit comme un quintet de données.

Un ensemble de descriptions de termes est constitué de métadonnées identiques à celles représentées par la structure des tables et des champs d'une base de données standard. Par exemple, il existe la structure de données suivante: une demande de service à une certaine date qui a le contenu (description de la demande) et un statut, auquel les participants d'un processus de production ajoutent des commentaires indiquant la date. Dans un constructeur de base de données traditionnel, cela ressemblera à ceci:



Puisque nous avons décidé de cacher à l'utilisateur tous les détails non essentiels, tels que les ID de liaison, par exemple, le schéma sera quelque peu simplifié: les mentions des ID sont supprimées et les noms des entités et leurs valeurs clés sont combinés.

L'utilisateur "dessine" la tâche: une requête à partir de la date du jour qui a un état (valeur de référence) et à laquelle vous pouvez ajouter des commentaires indiquant la date:



Maintenant, nous voyons 6 champs de données différents au lieu de 9, et l'ensemble du schéma nous propose de lire et de comprendre 7 mots au lieu de 13. Bien que ce ne soit pas l'essentiel, bien sûr.

Les quintets suivants sont générés par le noyau de traitement des quintets pour décrire cette structure:



Des explications à la place des valeurs de quintette surlignées en gris sont fournies pour plus de clarté. Ces champs ne sont pas remplis, car toutes les informations nécessaires sont déterminées sans ambiguïté par les composants restants.

Découvrez comment les quintettes sont liés


Ce que nous avons ici:

  • les attributs avec les ID 80, 81, 83 ont le même parent - Demande
  • le quintette # 82 est l'attribut de Commentaire, qui est à son tour un attribut de Demande
  • l'attribut # 74 est une référence au type décrit par le quintet # 73 et est utilisé comme attribut # 81 de Request

Cela peut sembler un peu compliqué pour les humains, mais la bonne nouvelle est qu'un humain ne verra jamais cela. Le noyau représentera les métadonnées sous forme de diagrammes compréhensibles et les données sous forme de simples tableaux plats.

Données utilisateur


Permettez-moi de montrer comment nous stockons un tel ensemble de données pour la tâche ci-dessus:



Les données elles-mêmes sont stockées dans des quintets en fonction des métadonnées. Nous pouvons les visualiser de la même manière que ci-dessus:



Nous voyons une structure hiérarchique familière écrite à l'aide de quelque chose comme la méthode de la liste d'adjacence.

Stockage physique


Les données sont écrites dans la mémoire sous la forme d'une séquence d'éléments de quintet en octets de données. Afin de rechercher par index, le noyau traite ces octets de données selon le type de données défini pour eux par des types de base.
C'est tout: une énorme liste de cinq éléments de données.

Les principes de stockage ne sont pas très différents des mêmes dans le SGBDR, ce qui nous permet de créer des requêtes SQL sur les données pour effectuer la récupération des données, les JOIN, les fonctions d'agrégation et d'autres choses que nous aimons dans les bases de données relationnelles.
Pour tester le prototype d'une plateforme de développement basée sur le système de stockage de quintet, nous utilisons une base de données relationnelle.

Performances


L'exemple ci-dessus est très simple, mais que se passera-t-il lorsque la structure sera mille fois plus complexe et qu'il y aura des gigaoctets de données?

Ce dont nous avons besoin:

  1. La structure hiérarchique discutée - 1 pc.
  2. Arbre B pour la recherche par ID, parent et type - 3 pièces.

Ainsi, tous les enregistrements de notre base de données seront indexés, y compris les données et les métadonnées. Une telle indexation est nécessaire pour obtenir les avantages d'une base de données relationnelle - l'outil le plus simple et le plus populaire. L'index parent est en fait composite (ID parent + type). L'index par type est également composite (type + valeur) pour une recherche rapide des objets d'un type donné.

Les métadonnées nous permettent de nous débarrasser de la récursivité: par exemple, pour trouver tous les détails d'un objet donné, nous utilisons l'index par ID parent. Si vous devez rechercher des objets d'un certain type, nous utilisons l'index par ID de type. Le type est un analogue d'un nom de table et d'un champ dans un SGBD relationnel.



Dans tous les cas, nous n'analysons pas l'ensemble des données, et même avec un grand nombre de valeurs de tout type, la valeur souhaitée peut être trouvée en un petit nombre d'étapes.

La base de la plateforme de développement


En soi, une telle base de données n'est pas autosuffisante pour la programmation d'applications et n'est pas complète, comme on dit, selon Turing. Cependant, nous parlons ici non seulement de la base de données, mais essayons de couvrir tous les aspects: les objets sont, entre autres, des algorithmes de contrôle arbitraires qui peuvent être lancés, et ils fonctionneront.

En conséquence, au lieu de structures de bases de données complexes et de code source d'algorithmes de contrôle stockés séparément, nous obtenons un champ d'information uniforme, limité par le volume de l'espace de stockage et régi par des métadonnées. Les données elles-mêmes lui sont présentées sous une forme compréhensible - la structure du domaine et les entrées correspondantes. L'utilisateur modifie arbitrairement la structure et les données, y compris en effectuant des opérations en masse avec eux.

Nous n'avons rien inventé de nouveau: toutes les données sont déjà stockées dans le système de fichiers et leur recherche s'effectue à l'aide d'arbres B, soit dans le système de fichiers, soit dans la base de données. Nous venons de réorganiser la présentation des données afin qu'il soit plus simple et plus clair de travailler avec.



Pour travailler avec cette représentation de données, vous aurez besoin d'un logiciel de noyau très compact - notre moteur de base de données est de la taille plus petite qu'un BIOS d'ordinateur, et, par conséquent, il peut être fait sinon en matériel, puis au moins aussi rapide et bug- gratuit que possible. Pour des raisons de sécurité, il peut également être en lecture seule.

En ajoutant une nouvelle classe à un assembly dans mon .Net préféré, nous pouvons observer la perte de 200-300 Mo de RAM uniquement sur la définition de cette classe. Ces mégaoctets ne rentreront pas dans le cache du bon niveau, ce qui entraînera l'échange du système sur le disque avec tous les frais généraux qui en découlent. Une situation similaire est avec Java. La description de la même classe avec des quintets prendra des dizaines ou des centaines d'octets, car la classe utilise uniquement des opérations primitives pour travailler avec des données que le noyau connaît déjà.

Vous pourriez penser que cette approche est déjà implémentée plusieurs fois dans diverses applications, mais ce n'est pas vrai.


Nous avons effectué une recherche approfondie dans les bases d'Internet et de propriété intellectuelle (brevets), et personne ne prétend faire exactement la même solution pour briser la limite de performance des constructeurs, des solutions à table unique et d'autres systèmes basés sur l'EAV. Néanmoins, nous avons mis des centaines de gigaoctets dans une telle application de quintet et l'avons trouvé fonctionnant assez bien. Si vous souhaitez voir des preuves, créer et tester votre propre instance, n'hésitez pas à visiter notre compte github.

Le prototype de la plateforme que nous avons construite comprend quatre composants:

  1. Éditeur de type visuel pour définir les métadonnées
  2. Outil de navigation de données comme un simple navigateur SQL
  3. Concepteur de rapport visuel pour créer des requêtes SQL sur les données
  4. Un processeur de modèles pour combiner des modèles avec des données récupérées par des requêtes



Comme prévu, en travaillant avec le prototype, aucun utilisateur ne penserait qu'il y a des quintettes à l'intérieur - cela ressemble à un constructeur ordinaire.

Comment gérer différents formats: SGBDR, NoSQL, bases de colonnes
L'approche discutée couvre deux domaines principaux: RDBMS et NoSQL. Lors de la résolution de problèmes qui tirent parti des bases de données en colonnes, nous devons indiquer au noyau que certains objets doivent être stockés, en tenant compte de l'optimisation de l'échantillonnage de masse des valeurs d'un certain type de données (notre terme). Par conséquent, le noyau pourra placer les données sur le disque de la manière la plus rentable.

Ainsi, pour une base de données en colonnes, nous pouvons économiser de manière significative l'espace occupé par les quintettes: utilisez uniquement un ou deux de ses composants pour stocker des données utiles au lieu de cinq, et utilisez également l'index uniquement pour indiquer le début des chaînes de données. Dans de nombreux cas, seul l'indice sera utilisé pour l'échantillonnage à partir de notre analogue d'une base en colonnes, sans avoir besoin d'accéder aux données de la liste de quintettes elle-même.

Il convient de noter que l'idée n'est pas destinée à collecter tous les développements avancés de ces trois types de bases de données. Au contraire, le moteur du nouveau système sera réduit autant que possible, n'incarnant que le minimum de fonctions nécessaires - tout ce qui couvre les requêtes DDL et DML dans le concept décrit ici.


Paradigme de programmation


L'approche décrite ne se limite pas seulement à l'utilisation des quintettes, mais promeut un paradigme différent de celui auquel les programmeurs sont habitués. Au lieu d'un langage impératif, déclaratif ou objet, nous proposons le langage de requête comme plus familier aux humains et nous permettant de définir la tâche directement sur l'ordinateur, en contournant les programmeurs et la couche impénétrable des environnements de développement existants.

Bien sûr, un traducteur d'une langue d'utilisateur profane vers une langue d'exigences claires sera toujours nécessaire dans la plupart des cas.

Ce sujet sera décrit plus en détail dans des articles séparés avec des exemples et des développements existants.

Donc, sous peu, cela fonctionne comme suit:

  1. Nous avons décrit les types de données primitifs à l'aide de quintets: chaîne, nombre, fichier, texte et autres, et avons également formé le noyau à travailler avec eux. La formation signifie la présentation correcte des données et la mise en œuvre d'opérations simples avec elles.
  2. Nous décrivons maintenant les termes utilisateur (types de données) - sous forme de métadonnées. La description spécifie simplement un type de données primitif pour chaque type d'utilisateur et détermine les relations.
  3. Nous entrons des quintets de données selon la structure spécifiée par les métadonnées. Chaque quintet de données contient un lien vers son type et son parent, ce qui vous permet de le trouver rapidement dans le stockage de données.
  4. Les tâches du noyau se résument à récupérer des données et à effectuer des opérations simples avec elles pour implémenter des algorithmes arbitrairement complexes définis par l'utilisateur.
  5. L'utilisateur gère les données et les algorithmes à l' aide d'une interface visuelle qui les présente tous les deux.


L'intégralité de Turing de l'ensemble du système est assurée par la réalisation des exigences de base: le noyau peut effectuer des opérations séquentielles, effectuer des branchements conditionnels, traiter les données et arrêter le travail lorsqu'un certain résultat est atteint.

Pour une personne, l'avantage est la simplicité de perception, par exemple, au lieu de déclarer un cycle impliquant des variables

for (i = 0; i <length (A); i ++) if A [i] meets a condition do something with A [i] 


une forme plus compréhensible est utilisée, comme

 with every A, that match a condition, do something 


Nous rêvons de faire abstraction des subtilités de bas niveau des systèmes d'information: boucles, constructeurs, fonctions, manifestes, bibliothèques - tout cela prend trop de place dans le cerveau d'un programmeur, laissant peu de place au travail créatif et au développement.

Évolutivité


Une application est souvent inutile sans moyen de mise à l'échelle: une capacité illimitée à étendre la capacité de charge d'un système d'information est requise. Dans l'approche décrite, compte tenu de l'extrême simplicité de l'organisation des données, la mise à l'échelle s'avère ne pas être plus compliquée que dans les architectures existantes.

Dans l'exemple ci-dessus avec les demandes de service, vous pouvez les séparer, par exemple, par leur ID, ce qui rend la génération d'ID avec des octets HIGH fixes pour différents serveurs. Autrement dit, lorsque vous utilisez 32 bits pour stocker l'ID, les deux ou trois ou quatre bits de gauche, selon les besoins, indiqueront le serveur sur lequel ces applications sont stockées. Ainsi, chaque serveur aura son propre pool d'ID.

Le noyau d'un seul serveur peut fonctionner indépendamment des autres serveurs, sans rien savoir d'eux. Lors de la création d'un objet, il sera accordé une priorité élevée au serveur avec le nombre minimum d'identifiants utilisés, afin d'assurer une répartition uniforme de la charge.

Étant donné un ensemble limité de variations possibles des demandes et des réponses dans une telle organisation de données, vous aurez besoin d'un répartiteur assez compact qui distribue les demandes sur les serveurs et agrège leurs résultats.

Source: https://habr.com/ru/post/fr468927/


All Articles