2010-11-23 8 views
8

J'ai une table dire:révisions de manutention au sein d'Oracle

CREATE TABLE "DataNode" (
    "ID" NUMBER(7,0), 
    "TYPE" NUMBER(7,0), 
    "NAME" VARCHAR2(100), 
    "STATUS" NUMBER(7,0), 
    "REVISION" NUMBER(4,0), 
    "MODIFIEDAT" DATE 
); 

CREATE TABLE "DataNode_Revisions" (
    "ID" NUMBER(7,0), 
    "NODEID" NUMBER(7,0), 
    "TYPE" NUMBER(7,0), 
    "NAME" VARCHAR2(100), 
    "STATUS" NUMBER(7,0), 
    "REVISION" NUMBER(4,0), 
    "MODIFIEDAT" DATE 
) COMPRESS; 

J'ai donc ces deux tables. Je fais toutes mes lectures de "DataNode" et quand une modification se produit j'écris l'entrée courante à "DataNode_Revisions" et puis modifie mon enregistrement "DataNode" existant. Logique?

Est-ce la meilleure façon de procéder? Je peux déjà dire que je vais rencontrer des problèmes lorsque le schéma change. Je ne vois pas une meilleure alternative mais s'il y en a une s'il vous plaît faites le moi savoir! Je suppose que garder tout cela dans un seul tableau entraînerait des pertes de performance massives sans cela? Je veux dire que je quadruplerais le nombre de disques et qu'il y en a déjà pas mal. Je pense que Drupal stocke les révisions de nœud comme ça, et je suis curieux de voir comment ils ne souffrent pas de problèmes de performance.

"DataNode" est constamment lu par de nombreux utilisateurs. Cependant, très peu d'écritures se produisent. "DataNode_Revisions" est seulement lu à l'occasion. Je suis juste inquiet de maintenir autant de tables. "DataNode" est l'une des ~ 25 tables très similaires à celle-ci.

Répondre

6

Si l'enregistrement des anciennes lignes dans la table DataNode aura des conséquences sur les performances, cela dépend de la façon dont les lignes DataNode sont accédées.Si les lectures sont toutes des recherches à une seule ligne pour la ligne en cours, le nombre de lignes dans la table est relativement négligeable - il ne faudra pas plus de travail pour trouver la ligne courante pour un ID particulier que pour obtenir la ligne pour cet ID de la table DataNode actuelle (je suppose ici que ID est la clé de la table). D'un autre côté, si vous avez un certain nombre de requêtes qui effectuent des analyses de table de la table DataNode, le quadruplement du nombre de lignes augmentera le temps requis pour exécuter ces requêtes.

Si vous souhaitez suivre le chemin de la mise en place des lignes historiques dans la table DataNode, vous souhaiterez probablement ajouter une colonne EXPIRATION_DATE qui est NULL pour la ligne actuelle et remplie pour les lignes expirées. Vous pouvez ensuite créer un index basé sur une fonction basée sur la EXPIRATION_DATE qui aurait des données uniquement pour les lignes actuelles, à savoir

CREATE INDEX idx_current_ids 
    ON DataNode((CASE WHEN expiration_date IS NULL THEN id ELSE null END)); 

qui serait utilisé dans une requête comme

SELECT * 
    FROM DataNode 
WHERE (CASE WHEN expiration_date IS NULL THEN id ELSE null END) = <<some id>> 

De toute évidence, vous d voulez probablement créer une vue qui a cette condition plutôt que de la réécrire chaque fois que vous avez besoin de la ligne en cours, par exemple

CREATE VIEW CurrentDataNode 
AS 
SELECT (CASE WHEN expiration_date IS NULL THEN id ELSE null END) id, 
     type, 
     name, 
     status 
    FROM DataNode; 

SELECT * 
    FROM CurrentDataNode 
WHERE id = <<some value>> 
+0

+1: L'idée d'index basée sur la fonction est excellente! –

4

J'utilise généralement des déclencheurs pour écrire dans la table 'Révisions'. Oui, les modifications de schéma vous forcent à mettre à jour la table miroir et la fonction de déclenchement/archivage.

Je pense que vous regretterez de garder toute votre histoire ainsi que la révision actuelle dans un seul tableau, donc je pense que vous avez la bonne idée. Si vous souhaitez essayer de proposer une solution générique qui ne nécessite pas de table miroir pour chacune de vos tables transactionnelles, vous pouvez envisager d'avoir une seule table de révisions dans laquelle convertir les enregistrements en XML et les stocker dans un clob ... pas très utile si vous devez y accéder souvent ou rapidement, mais bon si vous voulez vraiment tout archiver.

2

Vous avez quelques options. Quelles sont les exigences métier qui vous obligent à suivre les modifications de données?

  • si vous avez besoin de garder les changements pendant une certaine période de temps « court », vous pouvez lire les données à partir UNDO à l'aide de la requête flashback .. select * from table d'horodatage (BLA);

  • Si vous avez besoin de conserver cette information à long terme, jetez un coup d'œil à la fonctionnalité appelée Oracle Total Recall. Il fait la même chose que Flashback Query, mais conserve les changements indéfiniment.

  • Si vous avez besoin de quelque chose de plus simple, ne demandez pas à l'application d'insérer la "vieille" version des lignes. Utilisez un déclencheur qui remplit les données.

  • si le système est extrêmement occupé, vous pouvez découpler les deux tables en ayant une table intermédiaire que vous utilisez comme une « file d'attente »

2

Cela va dépendre de l'application. Si vous êtes sur 11g, vous pouvez regarder le nouveau Flashback Data Archive. Je commence juste à le regarder pour garder l'histoire sur toutes nos données financières et autres critiques.