Come posso memorizzare informazioni con struttura variabile?

5

Ho problemi a trovare un nome per questo problema, ma mi sento come se fosse stato risolto prima. Penso che la mia ingenuità mi impedisca di digitare le parole giuste in Google per ottenere i risultati di cui ho bisogno. Quindi mi scuso in anticipo se questa domanda è stata posta prima.

In ogni caso ...

Sto progettando un'applicazione web multi-tenant in cui la struttura dei dati dipende dal locatario. Un inquilino in questo caso è un'azienda che vuole utilizzare i nostri servizi e un utente è un individuo che lavora per una di quelle attività. Il sistema è tutto in un unico posto, dato che in questo c'è un sito Web a cui tutti gli utenti si collegano, a seconda dell'indirizzo e-mail che digitano, l'affittuario a cui sono assegnati viene deciso automaticamente al momento della registrazione (non sono sicuro se questo è il modo giusto per andare su questo).

Ogni inquilino vuole memorizzare informazioni sulle persone che lavorano per loro sul nostro sistema. Queste persone non sono necessariamente utenti e, cosa più importante, queste informazioni sulle persone sono utilizzate in altre parti del sito web che potrebbero essere più generali.

Ecco il problema: ogni inquilino potrebbe voler memorizzare informazioni diverse sulla propria gente. Ad esempio, il Tenant A vuole memorizzare Nome, Email, Telefono e Indirizzo, ma il Tenant B vuole Nome negozio, Email, un'immagine della persona e il loro cibo preferito (non so).

Utilizziamo SQL Server per archiviare i nostri dati. Il mio istinto è quello di creare un tavolo diverso per ogni inquilino, ma prevedo che le cose diventeranno sempre più sicure con l'aumento del numero di inquilini. Se avessimo 5 inquilini, certi tavoli individuali avrebbero funzionato ... ma cosa accadrebbe se avessimo 500 inquilini? Avremmo bisogno di avere 500 tabelle solo per tutte le persone sulle quali archiviamo le informazioni? Ma peggiora. Le diverse informazioni non riguardano solo le persone di ciascun inquilino; gli inquilini potrebbero desiderarci di memorizzare informazioni diverse per altri servizi che offriamo loro.

È possibile generalizzare in qualche modo questa struttura di dati variabile? C'è qualcuno là fuori che ha già trattato qualcosa del genere?

    
posta tnlarson 14.12.2017 - 18:21
fonte

5 risposte

2

Dovresti separare i dati standard su tutti i titolari e i dati che variano da titolare a titolare.

È possibile memorizzare i dati variabili in XML o JSON. Sia come singolo campo in una tabella più grande, o più campi, dipenderà dalla natura dei dati. SQL Server ha la capacità di eseguire query nelle strutture JSON e probabilmente (ma non ne sono sicuro al 100%) è possibile farlo anche per XML.

Gli schemi possono essere definiti per XML, quindi puoi ancora convalidare i dati per ciascun titolare per lo schema personalizzato del tenant, se lo desideri. Credo che ci siano modi per definire schemi anche per JSON.

Se non vuoi seguire quella rotta, c'è il buon vecchio modello Entity-Attribute-Value che potrebbe gestire anche questo ( link )

Ovviamente, dovresti anche assicurarti che il tuo sistema permetta agli utenti di manipolare i loro attributi personalizzati (aggiungerne di nuovi, modificare quelli esistenti, rimuoverli, ecc ...) - se tutto viene scaricato in JSON / XML o in un Modello EAV.

    
risposta data 14.12.2017 - 18:35
fonte
2

In realtà ho lavorato su un progetto che è stato migrato come funzionalità in un software molto più grande. All'improvviso ci sono state molte più aziende che volevano accedere alla nostra applicazione e ogni azienda ci ha fornito diverse informazioni sugli utenti, il che risulta in un disordine nel database.

La nostra soluzione era aggiungere una tabella utente di base. La tabella conteneva tutte le informazioni che erano uguali per tutte le società: nomi, password, email, telefono e lingua. Alla fine queste erano solo le informazioni necessarie al nostro servizio per funzionare correttamente. Inoltre, abbiamo aggiunto tabelle per ogni azienda. Abbiamo avuto Company-A-User e Company-B-User e così via. Queste tabelle contenevano le informazioni aggiuntive e diverse e una chiave esterna per l'utente di base per fare riferimento alle informazioni necessarie. Nella nostra applicazione potevamo fare quasi tutto con i dati dell'utente di base e solo nei servizi specifici dell'azienda era necessario accedere alle altre tabelle.

Il mio consiglio: controlla la quantità di informazioni effettivamente necessarie per i tuoi servizi e inseriscile in una tabella di base. Se hai bisogno delle informazioni aggiuntive che un'azienda fornisce, aggiungi una tabella utente con una chiave esterna alla tabella di base. Se non condividi alcuna informazione, devi comunque eseguire singole tabelle.

    
risposta data 14.12.2017 - 21:11
fonte
2

Il problema non è nuovo e per questo non esiste una soluzione "taglia unica". Se vuoi mantenere il tuo sistema gestibile, devi analizzare i diversi requisiti per ogni singolo attributo e prendere una decisione caso per caso come progettarlo:

  • o come attributo standard disponibile per ogni tenant (e quindi meglio modellato come colonna standard nel database)

  • o un attributo disponibile per molti inquilini (quindi potrebbe essere modellato come una colonna standard anche nel database, ma mostrato solo nell'interfaccia utente per quei titolari che lo richiedono).

  • o un attributo personalizzato che viene modellato meglio usando un approccio EAV, come suggerito da @FrustratedWithFormsDesigner, o un approccio "XML o JSON" (questo è tipicamente il caso in cui l'inquilino vuole aggiungere liberamente nuovi attributi da solo , forse su una base "per record")

  • o, se l'attributo si adatta meglio a una tabella "figlio", come suggerito da @pfuetz (forse una tabella figlio specifica del tenant, ma consiglio di avere tabelle figlio di questo tipo associate a una funzione con nome dell'applicazione e quindi decidere quale titolare accede a questa funzione)

Si noti che le colonne standard sono spesso molto più facili da gestire rispetto agli approcci EAV: sarà più semplice implementare la logica aziendale per loro, le query SQL standard saranno più semplici, la progettazione dell'interfaccia utente può essere resa più specifica per la colonna, le migrazioni del database spesso sono più facili, sono molto più auto-documentanti e così via. Quindi raccomando di usare l'EAV raramente, con cautela, solo dove ne hai veramente bisogno.

Ci si imbatterà in problemi di manutenzione quando inizierai a duplicare le tabelle per ciascun tenant e modificerai un po 'ogni copia. Fallo 10 volte e avrai 10 volte lo sforzo di manutenzione per ogni attributo copiato. Quindi raccomanderei strongmente contro quello.

    
risposta data 14.12.2017 - 21:36
fonte
0

Offri agli inquilini la possibilità di "modellare" la struttura dei dati ... in un modo o nell'altro.

Ti consiglio di prendere alcune richieste di esempio per i dati e i flussi di lavoro di molti titolari e scoprire la struttura generica comune a tutti. Ci sarebbero alcuni problemi comuni come:

  1. Gestione utenti
  2. Controllo dell'accesso
  3. Autenticazione
  4. Alcune funzionalità comuni come la gerarchia utente

Quindi, potresti iniziare con le tabelle di base per le cose comuni. Quindi consentire agli inquilini di aggiungere campi a queste entità in modo dinamico (formattazione, convalida e tutto) in tabelle di estensioni EAV separate, una per ogni tabella di base. In sostanza, è simile a quello che alcuni noti Sistemi di gestione dei contenuti chiamano "Campi personalizzati".

    
risposta data 15.12.2017 - 08:39
fonte
-2

Alcune idee:

Tabelle individuali

Non penso che l'utilizzo di una tabella SQL per ogni singolo tenant (o struttura di oggetti) sia necessariamente negativo.

Ho lavorato personalmente con database Oracle contenenti circa 1000 tabelle (con milioni di righe per tabella). Avevano bisogno di alcune impostazioni dei parametri per superare alcune limitazioni di risorse, ma ha funzionato abbastanza bene.

Il vantaggio è che tutte le operazioni di database rimangono semplici. I tavoli rimangono compatti. Ed è facile implementare l'isolamento del cliente concedendo privilegi sulle tabelle.

A seconda del livello di accesso al database che si sta utilizzando, l'implementazione potrebbe risultare goffa (specialmente i relatori Object-Relational), ma si scrive "Il mio istinto è di creare una tabella diversa per ogni tenant ...", quindi penso hai analizzato questo aspetto.

Tabella Unificante grande

Un'altra opzione è creare una tabella mostro con tutte le colonne che conosci in questo momento, e non appena un nuovo cliente ha bisogno di un'altra colonna, modifica la tabella aggiungendo quella colonna (non sai quanto sia efficiente quell'operazione su MS SQL Server ).

Hai ancora operazioni di database dirette, ma una grande tabella in crescita, che rallenta un cliente a causa dei dati di massa di altri clienti. E l'isolamento dei clienti non è così semplice.

Quindi, opterei per l'approccio alla tabella individuale

    
risposta data 14.12.2017 - 19:46
fonte

Leggi altre domande sui tag