Progettazione di database SQL Server per dati "archiviati ma disponibili"


12

Abbiamo questo ampio database (> 1 TB) che intendiamo "ridurre". Il database ruota attorno a un'entità principale, chiamiamola "Visita". Per la discussione, diciamo che è un database per una pratica medica.

Esistono in totale 30 "tipi" di visita, come procedura, annuale, follow-up, immunizzazione ecc., Ciascuno dei quali è una tabella sussidiaria per "Visita", ad esempio "visit_immuno".

Il database ha accumulato circa 12 anni di dati dal 2000. Qualcuno ha proposto di mantenere circa 3 anni di dati nella versione "live" e di fare in modo che il resto sia attivo in un database "old_data". La data viene memorizzata SOLO nella tabella "Visita" poiché è normalizzata. La tabella Visit contiene anche una ROWVERSIONcolonna e una colonna BIGINTpseudo-identità (raggruppata). A tutti gli effetti, supponiamo che la chiave di clustering sia popolata da una SEQUENZA (SQL Server 2012 Enterprise) - la chiameremo cid.

Non visit.dateè sempre nello stesso ordine della chiave di clustering, ad esempio quando un medico effettua visite prolungate e ritorna con la sua "valigetta" di dati, viene unito alla tabella principale. Ci sono anche alcuni aggiornamenti alla tabella "visit" che causano la ROWVERSIONmancata sincronizzazione della colonna con entrambe le colonne cide date- per dirla semplicemente, ROWVERSIONcidrenderebbe né adatte le chiavi di partizione per questo motivo.

La regola aziendale per la rimozione dei dati dal "live" è che visit.datedeve essere maggiore di 36 mesi evisit_payment deve esistere un record figlio . Inoltre, il database "old_data" non contiene nessuna delle tabelle di base tranne visit%.

Quindi finiamo con:

Live DB (uso quotidiano) - Tutte le tabelle DB di dati vecchi - dati più vecchi per le visit%tabelle

La proposta richiede un DB combinato che sia una shell contenente sinonimi di TUTTE le tabelle di base nelle Live DB(tranne visit%) più viste che UNION ALL tra le visit%tabelle nei due database.

Supponendo che gli stessi indici vengano creati nel Old-DataDB, le query funzioneranno bene nelle viste UNION-ALL ? Che tipo di modelli di query potrebbe scattare il piano di esecuzione per l'Unione-ALL Visualizzazioni ?


3
Qual è la motivazione per a) archiviare i vecchi dati eb) tenerli accessibili? Spese generali di manutenzione? Problemi di prestazioni? I dati archiviati devono essere facilmente accessibili all'applicazione? Con o senza modifiche all'applicazione?
Mark Storey-Smith,

(a) Mantenere piccolo il db principale. Viene replicato in altri 3 envs: dev, pre-test, test. Esistono anche mirror e backup replicati, tutti supportati da costosi archivi. (b) Poiché i sistemi a valle attualmente hanno accesso a tutti i dati, questo mantiene lo status quo. (c) Un'istanza dell'app potrebbe essere eseguita sul DB "combinato" con tutte le viste, ma sospetto che potrebbe non funzionare affatto.
孔夫子

Giusto per chiarire, i dati archiviati sono ancora in lettura-scrittura, giusto? O è di sola lettura?
Jon Seigel,

I vecchi dati passerebbero a pagine di sola lettura e riempite al 100%. L'istanza dell'app che si collega alle viste combinate potrebbe generare errori se qualcuno prova qualcosa di stupido su vecchi dati - non ci interessa.
孔夫子

Penso che un filegroup di sola lettura per i dati storici e il backup / ripristino parziale coprirebbe questo, senza l'aggiunta del muck del database della shell e dei sinonimi. Dico che non mi sono immischiato nella meccanica da qualche tempo e ho bisogno di rinfrescare la mia memoria. Non ho idea di come si adatterebbe con la replica, ma mi chiedo perché stai replicando un database live in ambienti downstream.
Mark Storey-Smith,

Risposte:


4

Per comodità, supponiamo che sia chiamato il database live e che sia chiamato LiveDbil database achiveArchiveDb

  • Aggiungere una vista UNION ALL LiveDbindicando le tabelle nel ArchiveDbdatabase tramite un sinonimo (Non è necessario eseguire un db combinato con sinonimi)
  • "Partiziona" attiva visit.datee denormalizza anche questa colonna visit_paymentsse non è già presente (ciò migliora le prestazioni dei join condivisi)
  • Archivia solo le due tabelle di grandi dimensioni, se possibile (riduce la possibilità di far scattare l'ottimizzatore). Mantenere la vista UNION ALL e le altre tabelle in LiveDbmodo che tutti i join alle tabelle più piccole vengano mantenuti locali
  • Aggiungi un vincolo CHECK sulle tabelle in entrambi LiveDbe ArchiveDb che descrive l'intervallo di visit.datecontenuti nella tabella. Questo aiuta l'ottimizzatore a eliminare la tabella di archivio sia dalle ricerche che dalle scansioni che contengono la colonna visit.data. Dovrai aggiornare periodicamente questo vincolo.
  • Nella vista UNION ALL, aggiungi un criterio WHERE su cui filtrare visit.data. Questo è in aggiunta al suggerimento che hai già fornito nel vincolo di controllo. Ciò massimizza la possibilità che i filtri vengano spinti verso il basso
  • Se si dispone di EE, partizionare la tabella nel database di archivio (ma NON nel database live). Se vuoi essere davvero fantasioso, usa il backup / ripristino a livello di filegroup dei database di archivio per risparmiare sui tempi di backup.
  • Prendi AchiveDbin considerazione la modalità di recupero SEMPLICE se non lo è già. Non è probabile che tu abbia bisogno di backup del log delle transazioni diArchiveDb
  • Utilizzare INSERT ... WITH (TABLOCK) SELECT ... WITH (ROWLOCK) per forzare la registrazione minima sulla destinazione quando si spostano i dati tra LiveDbeArchiveDb

Tutto quanto sopra non garantisce che l'ottimizzatore eliminerà le tabelle di archivio da ricerche e scansioni, ma lo rende più probabile.

Quando l'eliminazione non avviene. Questi sono gli effetti che potresti vedere (questo elenco potrebbe essere incompleto). Per le ricerche, otterrai una ricerca aggiuntiva su ogni query (questo porta su IOPS). Per le scansioni, i risultati potrebbero essere disastrosi per le prestazioni in quanto si potrebbe finire per scansionare sia l'archivio sia le tabelle live. Ecco i modi tipici in cui puoi attivare l'ottimizzatore:

  • Se unisci le visit%tabelle e non includi i visit.datacriteri di join (ecco perché vuoi denormalizzare). Per questo motivo, potresti voler modificare alcune delle tue domande
  • Se ottieni un hash join tra visit.datae un'altra tabella (ad esempio una dimensione data), potresti non ottenere la giusta eliminazione delle tabelle
  • Se si tenta di aggregare i dati sulle tabelle archiviate
  • Se si filtra qualcosa, MA il visit.data, ad esempio, cercare direttamente sul tasto della vista.

Per l'ultimo scenario, puoi proteggerti dagli effetti peggiori aggiungendo un altro vincolo di controllo sul cid- se questo è possibile. Hai detto che la sequenza cidnon è "pulita" rispetto alle date e alla progressione delle righe nella tabella. Tuttavia, potresti mantenere una tabella che contiene le informazioni: "Non esiste un cidnumero superiore a questo numero da questo visit.data" o simile? Ciò potrebbe quindi determinare un ulteriore vincolo.

Un'altra cosa a cui prestare attenzione è che le query parallele possono generare MOLTE più discussioni una volta eseguita la query sulla vista partizionata (poiché entrambe le "sotto-tabelle" saranno esposte alle stesse ottimizzazioni parallele). Per questo motivo, potresti voler limitare MAXDOP sul server o le query che sono parallele.

A proposito, se conosci bene le query, potresti non aver nemmeno bisogno degli stessi indici nei due database (questo presuppone che tu sia sicuro al 100% che otterrai la giusta eliminazione delle tabelle). Puoi anche prendere in considerazione l'utilizzo di archivi di colonne per ArchiveDb.


-1

Il modo in cui abbiamo fatto è scrivere i vecchi dati in batch in un database appena creato ed eliminare i vecchi dati dal database live. In questo modo entrambi i db sono accessibili. È inoltre possibile eseguire il backup del database appena creato e ripristinarlo altrove per rimuovere il footprint di grandi dimensioni dai server di produzione. Spero che sia una soluzione accettabile per le tue esigenze.


L'OP deve andare oltre questo per mantenere la compatibilità delle applicazioni. Hai letto la domanda?
Jon Seigel,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.