Det første spørgsmål bør være:hvad ville du gøre med disse data? Hvis du ikke har klare forretningskrav, skal du ikke gøre det.
Jeg gjorde noget lignende, og efter 3 års drift er der omkring 20% af "gyldige data" og resten er "tidligere versioner". Og det er 10 millioner + 40 millioner poster. I de sidste tre år havde vi 2 (to) anmodninger om at undersøge historikken for ændringer, og begge gange var anmodninger dumme - vi registrerer tidsstempel for rekordændring, og vi blev bedt om at kontrollere, om personer arbejdede overarbejde (efter kl. 17.00).
Nu sidder vi fast med en overdimensioneret database, der indeholder 80 % af data, som ingen har brug for.
EDIT:
Da du bad om mulige løsninger, vil jeg beskrive, hvad vi gjorde. Det er en smule anderledes end den løsning, du overvejer.
- Alle tabeller har surrogat primærnøgle.
- Alle primære nøgler er genereret fra en enkelt sekvens. Dette fungerer fint, fordi Oracle kan generere og cache numre, så ingen ydeevneproblemer her. Vi bruger ORM, og vi ønskede, at hvert objekt i hukommelsen (og tilsvarende post i databasen) skulle have en unik identifikator
- Vi bruger ORM og kortlægningsinformation mellem databasetabel og klasse er i form af attributter.
Vi registrerer alle ændringer i en enkelt arkivtabel med følgende kolonner:
- id (surrogat primær nøgle)
- tidsstempel
- oprindelig tabel
- id for den oprindelige post
- bruger-id
- transaktionstype (indsæt, opdater, slet)
- registrer data som varchar2-felt
- dette er faktiske data i form af feltnavn/værdi-par.
Tingene fungerer på denne måde:
- ORM har indsæt/opdater og slet kommandoer.
- vi har oprettet én basisklasse for alle vores forretningsobjekter, der tilsidesætter indsæt/opdater og slet kommandoer
- indsæt/opdater/slet kommandoer opretter streng i form af feltnavn/værdipar ved brug af refleksion. Kode søger efter kortoplysninger og læser feltnavn, tilhørende værdi og felttype. Så laver vi noget, der ligner JSON (vi tilføjede nogle ændringer). Når en streng, der repræsenterer objektets aktuelle tilstand, oprettes, indsættes den i arkivtabel.
- når nyt eller opdateret objekt gemmes i databasetabel, gemmes det i hans måltabel, og samtidig indsætter vi en post med aktuel værdi i arkivtabel.
- når objekt slettes, sletter vi det fra hans måltabel, og samtidig indsætter vi en post i arkivtabel, der har transaktionstype ="DELETE"
Fordel:
- vi har ikke arkivtabeller for hver tabel i databasen. Vi behøver heller ikke bekymre os om at opdatere arkivtabel, når skemaet ændres.
- komplet arkiv er adskilt fra "aktuelle data", så arkiv påtvinger ikke nogen performance hit på databasen. Vi sætter det på separat tablespace på separat disk, og det fungerer fint.
- vi har oprettet 2 formularer til visning af arkiv:
- generel fremviser, der kan liste arkivtabel i henhold til filter på arkivtabel. Filterdatabrugeren kan indtaste på formularen (tidsrum, bruger, ...). Vi viser hver post i form feltnavn/værdi, og hver ændring er farvekodet. Brugere kan se alle versioner for hver post, og de kan se, hvem og hvornår der er foretaget ændringer.
- fakturafremviser - denne var kompleks, men vi oprettede en formular, der viser faktura meget lig den originale fakturaindtastningsformular, men med nogle ekstra knapper, der kan vise forskellige generationer. Det tog en betydelig indsats at skabe denne form. Form blev brugt få gange og derefter glemt, fordi det ikke var nødvendigt i den nuværende arbejdsgang.
- kode til oprettelse af arkivposter er placeret i en enkelt C#-klasse. Der er ikke behov for triggere på hver tabel i databasen.
- ydelsen er meget god. I spidsbelastningsperioder bruges systemet af omkring 700-800 brugere. Dette er ASP.Net-applikationen. Både ASP.Net og Oracle kører på én dual XEON med 8 Gb RAM.
Ulemper:
- enkelttabels arkivformat er sværere at læse end løsning, hvor der er én arkivtabel for hver af datatabellerne.
- søgning på ikke-id-felt i arkivtabel er svært - vi kan kun bruge
LIKE
operator på streng.
Så igen, tjek kravene til arkivering . Det er ikke en triviel opgave, men gevinster og brug kan være minimale.