2008-11-06 5 views
3

Nous avons une application orientée objet de taille convenable. Chaque fois qu'un objet de l'application est modifié, les modifications de l'objet sont enregistrées dans la base de données. Cependant, cela est devenu moins qu'idéal.Quel est le meilleur moyen de stocker et de rechercher dans les transactions d'objets?

Actuellement, les transactions sont stockées en tant que transaction et ensemble de transactionLI.

La table de transaction contient des champs pour who, what, when, why, foreignKey et foreignTable. Les quatre premiers sont explicites. ForeignKey et foreignTable sont utilisés pour déterminer quel objet a été modifié. TransactionLI a horodatage, clé, val, oldVal, et un transactionID. Ceci est fondamentalement un système de stockage key/value/oldValue.

Le problème est que ces deux tables sont utilisées pour chaque objet de l'application, ce sont donc de très grandes tables maintenant. Les utiliser pour tout est lent. Les index aident tellement. Donc, nous pensons à d'autres façons de faire quelque chose comme ça. Ce que nous avons considéré jusqu'à maintenant: - Sharding ces tableaux par quelque chose comme l'horodatage. - Dénormaliser les deux tables et les fusionner en une seule. - Une combinaison des deux ci-dessus. - Faire quelque chose dans le sens de sérialiser chaque objet après un changement et le stocker dans subversion. - Probablement autre chose, mais je ne peux pas y penser maintenant.

Tout le problème est que nous aimerions avoir un mécanisme pour stocker et rechercher correctement les données transactionnelles. Oui, vous pouvez forcer l'alimentation dans une base de données relationnelle, mais vraiment, ce sont des données transactionnelles et doivent être stockées en conséquence.

Que font tous les autres?

+0

quelle base de données utilisez-vous? Vous pouvez rechercher le suivi des modifications SQL dans SQL 2008. Il ne suit pas vos objets, mais il suit vos modifications de données et les exécute. – D3vtr0n

Répondre

0

Je n'ai jamais trouvé une bonne solution pour ce type de problème. Certaines choses que vous pouvez essayer est si votre DB supporte le partioning (ou même si vous ne pouvez pas implémenter le même concept), mais partitionnez cette table de journal par type d'objet et ensuite vous pouvez continuer la partition par date/heure ou par ID de l'objet (si votre ID est un numérique, cela fonctionne bien, je ne sais pas comment un guid serait partion).

Ceci aidera à maintenir la taille de la table et à garder toutes les transactions liées à une seule instance d'un objet à elle-même. Une idée que vous pourriez explorer est au lieu de stocker chaque champ dans une table de paires de valeurs de nom, vous pouvez stocker les données sous forme de blob (texte ou binaire). Par exemple sérialiser l'objet en Xml et le stocker dans un champ. L'inconvénient de ceci est que lorsque votre objet change, vous devez considérer comment cela affecte toutes les données historiques si vous utilisez Xml alors il y a des moyens faciles de mettre à jour les structures xml historiques, si vous utilisez des binaires mais vous avez être plus conscient de l'effort.

J'ai eu beaucoup de succès en stockant un modèle d'objet plutôt complexe qui a des tonnes d'interélations en tant que blob (le sérialiseur xml dans .net ne gérait pas les relations entre les objets). Je pourrais très facilement me voir stocker les données binaires. Un inconvénient majeur de le stocker en tant que données binaires est que pour y accéder, vous devez le sortir de la base de données avec Xml si vous utilisez une base de données moderne comme MSSQL, vous pouvez accéder aux données.

Une dernière approche consiste à diviser les deux modèles, vous pouvez définir un schéma de différence (et je suppose que plus d'un changement de propriété à la fois) donc par exemple imaginer le stockage ce xml:

<objectDiff> 
<field name="firstName" newValue="Josh" oldValue="joshua"/> 
<field name="lastName" newValue="Box" oldValue="boxer"/> 
</objectDiff> 

Cette volonté Aidez-nous à réduire le nombre de lignes, et si vous utilisez MSSQL, vous pouvez définir un schéma XML et obtenir une partie de la capacité d'interrogation riche autour de l'objet. Vous pouvez toujours partitionner la table.

Josh

0

En fonction des caractéristiques de votre application une approche alternative est de garder révisions des entités elles-mêmes dans leurs tables respectives, ainsi que le qui, quoi, pourquoi et quand par la révision. Le qui, quoi et quand peut encore être des clés étrangères.

Bien que je serais très prudent d'utiliser cette approche, car ce n'est viable que pour les applications avec une quantité relativement faible de changements par entité/type d'entité.

0

Si l'interrogation des données est importante, j'utiliserais le véritable partitionnement dans SQL Server 2005 et versions ultérieures si vous possédez une édition d'entreprise de SQL Server. Nous avons des millions de lignes partitionnées d'une année à l'autre pour le mois en cours - vous pouvez être aussi précis que l'exige votre application avec un nombre maximum de 1000 partitions.

Alternativement, si vous utilisez SQL 2008, vous pouvez consulter les index filtrés.

Ce sont des solutions qui vous permettront de conserver la structure simplifiée dont vous disposez tout en fournissant les performances dont vous avez besoin pour interroger ces données.

Le fractionnement/archivage des anciennes modifications doit évidemment être pris en compte.

1

Nous avons pris l'approche suivante: -

  1. Tous les objets sont sérialisés (en utilisant le XMLSeriliser standard) mais nous avons décoré nos classes avec des attributs sérialisation afin que le XML résultant est beaucoup plus petit (stockage des éléments comme attributs et suppression de voyelles sur les noms de champs par exemple). Cela pourrait être pris une étape supplémentaire en compressant le XML si nécessaire.

  2. Le référentiel d'objets est accessible via une vue SQL. La vue affiche un certain nombre de tables dont la structure est identique mais le nom de la table est ajouté avec un GUID. Une nouvelle table est générée lorsque la table précédente a atteint la masse critique (un nombre prédéterminé de lignes)

  3. Nous exécutons une routine d'archivage nocturne qui génère les nouvelles tables et modifie les vues en conséquence afin que les applications d'appel ne voient pas des différences. Enfin, dans le cadre de la routine de nuit, nous archivons toutes les anciennes instances d'objets qui ne sont plus nécessaires au disque (et ensuite à la bande).

Questions connexes