Alternativa a EAV per campi dinamici in un data warehouse di schemi a stella


13

Devo supportare campi e valori dinamici in un grande datawarehouse per l'archiviazione del registro delle richieste API, il mio caso utente è che devo archiviare tutte le stringhe di query delle richieste API e in grado di eseguire query su di esse in futuro (quindi non è solo archiviazione, quindi non posso usare BLOB per loro)

per esempio http://example.com/?action=test&foo=abc&bar=def...

Devo archiviare tutti i field => valuemapping, vale a dire (action => test), (foo => abc), (bar => def), e poiché il campo è così dinamico, l'unica soluzione che ho trovato è usare Entity-Attribute-Value, tuttavia, la gente continua a dire che è un progetto molto cattivo.

Quindi, considera il mio caso d'uso sopra, quale sarebbe un'alternativa adatta all'EAV?

Il mio schema attuale usando KAV

  1. Tabella requests
    (id, timestamp, uri)
    es(1, 149382220, '/')

  2. Tabella params
    (request_id, key, value)
    es(1, 'action', 'test'), (1, 'foo', 'abc'), (1, 'bar', 'def')

Eventuali suggerimenti?

Aggiornamento: gestiamo il magazzino su AWS RedShift


2
Cosa c'è di sbagliato nel provare quello che stai suggerendo su un database di sviluppo? Inoltre, stai parlando di SQL Server? Il tag sql è piuttosto ampio.
Max Vernon,

Aggiornato la mia domanda
Howard

1
Quale DBMS stai usando? Alcuni hanno capacità di indicizzazione del testo piuttosto buone, quindi non escluderei l'uso di un campo "testo lungo" per archiviare le richieste. Detto questo, non avrei problemi a utilizzare il modello che proponi. Sebbene EAV in senso stretto, viene utilizzato solo per questo scopo molto specifico. Ancora una volta, detto questo, che tipo di domande devi essere in grado di fare? Prova a scrivere queste query su questo modello per vedere se funziona per te.
Colin 't Hart,

1
Quale RDBMS stai usando? SQLnon è abbastanza specifico. Ti è stato chiesto due volte. Io sono il terzo
Erwin Brandstetter,

2
Dal momento che RedShift si basa su PostgreSQL, vorrei provare a utilizzare il hstoreo jsontipi di dati (o jsonbse / quando "aggiornamento" per 9.4).
Colin 't Hart,

Risposte:


11

Mi vengono in mente tre soluzioni: EAV, XML e Sparse Columns. Quest'ultimo è specifico del fornitore e potrebbe non esserti utile.

Qualunque metodo tu scelga, potresti prendere in considerazione l'idea di memorizzare i dati della richiesta originale in un formato non elaborato, in una tabella o in un file flat. Semplifica il tentativo di provare nuovi modi di archiviare i dati, ti consente di ricaricare i dati se scopri un errore nel modo in cui analizzi le tue richieste e offre opportunità per analizzare le richieste API utilizzando l'elaborazione batch o "big data" strumenti se ritieni che il tuo data warehouse non sia in grado di gestire i dati in modo efficiente.

Considerazioni EAV

EAV / KVS, come descritto sopra, è probabilmente l'implementazione più semplice.

Sfortunatamente sarà anche molto costoso - per ottenere qualsiasi tipo di query efficiente sulle chiavi di uso comune dovrai avere indici sulla colonna chiave, che potrebbero essere molto frammentati. La richiesta di chiavi particolari sarebbe estremamente costosa.

Potresti essere in grado di ridurre il costo dell'indicizzazione o delle scansioni dell'indice supportando il tuo negozio EAV con visualizzazioni materializzate (molti fornitori supportano questo) per eseguire query su chiavi o valori che ti interessano.

XML

La maggior parte dei sistemi di database aziendali offre una gestione XML molto matura, tra cui convalida, indicizzazione e query sofisticate.

Caricare la richiesta API nel database come XML fornirebbe una tupla per richiesta, che logicamente potrebbe essere un po 'più appetibile per te che avere un numero sconosciuto di righe in una tabella EAV.

Se questo sia efficiente dipenderebbe molto dal tuo fornitore RDBMS e dalla tua implementazione.

Il più grande svantaggio è che questo è probabilmente l'unico modo per gestire i dati più complicato della manipolazione di stringhe della richiesta originale!

Colonne sparse / tabelle tradizionali

È possibile che tu possa caricare i tuoi dati in una struttura di tabella tradizionale, con una colonna per chiave.

La funzionalità Colonne sparse di SQL Server è un'ottima alternativa a un archivio EAV. Una tabella con colonne sparse si comporta in modo analogo a una tabella normale, tranne per il fatto che può avere fino a 30.000 colonne e i valori NULL nelle colonne sparse non occupano spazio nella tabella.

La loro combinazione con indici filtrati (un'altra caratteristica specifica di SQL Server) può fornire un'alternativa estremamente efficiente a un archivio EAV se si esegue frequentemente query per un paio di colonne e / o valori specifici.

L'utilizzo di una tabella tradizionale con altri fornitori può essere praticabile: IBM supporta oltre 700 colonne per tabella e Oracle circa 1000 e funzionalità come la compressione o il trattamento Oracle dei null finali potrebbero significare che è possibile archiviare i dati API in modo abbastanza efficiente.

L'ovvio svantaggio di questo approccio è che quando si aggiungono nuove chiavi all'API, è necessario modificare di conseguenza lo schema.


2
In PostgreSQL non consiglierei XML ma né hstoreo json. Nei prossimi 9.4 jsonbsarebbe la mia raccomandazione.
Colin 't Hart,

Mi piace molto questa risposta con i contro e la spiegazione di ciascuno. Molto informativo: apprezzo molto le informazioni sulle colonne sparse. Vorrei un esempio di EAV che utilizza l'approccio delle colonne sparse.
StixO

9

L'EAV non è un cattivo progetto, di per sé, è semplicemente un progetto che richiede una buona dose di riflessione e può essere risolto con problemi di prestazioni quando la quantità di dati aumenta. Potrebbe essere che per il tuo sistema, funzionerebbe bene.

Quando ho progettato un sistema per l'archiviazione di stringhe di query, non avevo idea in anticipo di quali campi sarei interessato. Ho creato una tabella per archiviare la stringa di query in formato binario serializzato e ho creato un sistema che mi ha permesso di dividere la query stringa nei suoi componenti una volta che ho conosciuto i pezzi che mi interessavano. Da lì ho creato un set di tabelle; uno ciascuno per gli insiemi di dati comunemente contenuti nella stringa di query.

Ad esempio, alla fine avevo una tabella per i dati del referrer, una per i dati della richiesta di destinazione e una per gli elementi relativi all'utente come la query di ricerca che avevano inserito.

Ho trovato la possibilità di archiviare l'intera stringa di query in una singola tabella come BLOB, fornendo al contempo la possibilità di dividere tale BLOB in futuro, soddisfacendo molto bene le mie esigenze.


1
Sia nella domanda che nella risposta BLOBviene usato il termine che significa oggetto binario lungo. Preferirei usare un CLOB(Character Long OBject) o qualcosa del genere textin PostgreSQL, dal momento che stiamo parlando di carattere e non di dati binari.
Colin 't Hart,

2
Ho usato un campo binario da quando ho effettivamente serializzato l'intero oggetto sessione e memorizzato tutto nel database.
Max Vernon,
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.