Domanda

Descrizione del problema: Nella mia applicazione devo presentare il contenuto dei pacchetti di dati in un determinato formato.Un esempio:

Un esempioQualsiasi dato binario compresso, ad esempio:Intestazione a 4 byte, tipo a 4 byte (codici di tipo con significati predefiniti), quindi indirizzo di origine, indirizzo di destinazione e così via.

In precedenza, ho realizzato implementazioni fatte in casa che memorizzavano i dati in un file binario (la lunghezza fissa del record consentiva una ricerca rapida), ma con il tempo mi sono reso conto che sto inventando una sorta di database.Ad esempio, sto implementando il mio efficiente formato di archiviazione binario per file di dati di grandi dimensioni.Sto anche implementando la mia indicizzazione per eseguire rapidamente ricerche su alcuni campi.Penso che un vero DB (anche il semplice SQLite) possa rendere queste cose trasparenti e semplici.

Domanda 1: i DB sono utili per archiviare tali dati e come dovrebbe essere fatto?Nota che non ci sono mappature 1-a-molti, molti-a-molti qui e altre cose avanzate, è solo una semplice sequenza di pacchetti con una certa struttura interna che voglio mostrare all'utente e con cui lasciarlo interagire (ad es.ricerca per un determinato campo).

Domanda 2: Supponiamo ora che l'utente stesso possa specificare il formato dei suoi pacchetti, ad es.in un file di configurazione:la lunghezza di ciascun campo, il suo tipo, il significato dei suoi valori (in caso di enumerazione) e così via.Come posso estendere un'implementazione supportata da DB per questo?L'utente dovrebbe definire gli schemi DB?Il file di configurazione dovrebbe essere tradotto automaticamente in questi schemi?ORM?

Domanda 3: Ancora più avanzato...Supponiamo ora che i pacchetti di dati possano variare in lunghezza e contenuto.Cioè, per i pacchetti di tipo n. 2, ci sono alcuni campi, per il tipo n. 3, alcuni altri campi e così via.Ma mi piacerebbe comunque che la mia app lo gestisse, visualizzando tutto in modo gradevole e consentendo anche agli utenti di specificare i formati nei file di configurazione.Com'è fatto?

Grazie in anticipo.

È stato utile?

Soluzione

Domanda 1:I DB sono utili per conservazione di tali dati e in che modo essere fatto?

Certamente un database è utile per questa applicazione.Potresti implementare il tuo archivio dati per scopi speciali e forse sarebbe più efficiente per la tua applicazione specifica, perché puoi progettarlo per quella specializzazione.Un database relazionale è più generico, ma utilizzando un database è possibile evitare settimane o mesi di sviluppo.

Oggi ho risposto a un'altra domanda sull'argomento su come gestire i tipi estensibili, in cui ogni nuovo sottotipo ha il proprio insieme distinto di attributi.

"tabella dei prodotti, molti tipi di prodotto, ogni prodotto ha molti parametri."

Per la tua applicazione, sceglierei il Eredità della tabella concreta progetto.

Domanda 2:Si supponga ora che l'utente può specificare il formato del suo pacchetti, ad es.in un file di configurazione:la lunghezza di ciascun campo, il suo tipo, cosa significano i suoi valori (in caso di enumerazione) e così via.Come faccio a estendere un'implementazione supportata da DB per questo?

Presumo che il numero di tipi di pacchetti sia relativamente basso e quindi molti pacchetti vengano inseriti praticamente con la stessa struttura.Quindi dovresti utilizzare la capacità del database di gestire i metadati.Definirei una tabella aggiuntiva per ogni nuovo tipo di pacchetto.

Memorizzerei anche i pacchetti "esplosi" in modo che ogni campo del pacchetto venga archiviato in una colonna del database separata.In questo modo puoi indicizzare ciascuna colonna individualmente, per supportare una ricerca efficiente.

Puoi anche definire dei vincoli in modo che alcuni campi siano obbligatori (NOT NULL) o i loro valori vincolati dalle tabelle di ricerca.Ancora una volta, sfruttando le capacità del database di utilizzare i metadati per imporre una struttura coerente dove è desiderabile.

SQL supporta già un linguaggio dichiarativo standard per specificare i campi con tipi di dati, vincoli, ecc.Perché sviluppare un linguaggio diverso da tradurre poi in SQL?

Domanda 3:Ancora più avanzato...Ora Supponiamo che i pacchetti di dati possano essere varia per lunghezza e contenuto.

I campi facoltativi in ​​un determinato tipo di pacchetto dovrebbero consentirlo NULL nella colonna corrispondente.

Altri suggerimenti

Una regola semplice è questa: se avete intenzione di interrogare i dati, allora dovrebbe essere un campo discreta all'interno di una tabella all'interno del DB. In caso contrario, è possibile memorizzare il BLOB e da fare con esso.

Detto questo, se si desidera derivare "meta dati" da un BLOB, e indice che, allora si può fare facilmente pure.

Se i tipi di dati sono congruenti con quello che il database in grado di supportare (o possono essere convertiti con precisione), non ci può essere qualche valore sta esplodendo il BLOB per sue parti componenti che mappano bene in alle colonne DB.

Il problema con la definizione di "tavoli al volo" (che potrebbe essere fatto facilmente) non è tanto la definizione della tabella, ma il potenziale cambiamento del tavolo. Tabelle che vengono cambiati (cioè una colonna aggiunto o eliminato, etc.) tendono ad essere inutilizzabile per la durata della modifica. Non è un problema per le 100 righe. Un vero e proprio problema per milioni di righe.

Se le definizioni di dati sono abbastanza statica, quindi la creazione di una struttura di mappatura che consente agli utenti descrivono il BLOB, e quindi si utilizza tale definizione per creare sia una tabella conforme e convertono il BLOB in modo appropriato durante l'importazione.

Per quanto riguarda i "diversi file di diversi tipi", si può ancora roba che i dati in una singola tabella. Alcune righe sono colonne "inutilizzati" rispetto alle altre, ciascuna riga è identificata per tipo. Se hai un sacco di definizioni fila, e un sacco di varianza, si ottiene un sacco di spazio sprecato facendo questo. Poi si può decidere di andare ad avere una tabella per ogni tipo di riga, e un tavolo master che contiene i tipi di riga e riferimenti a veri righe nelle tabelle attuali. Si avrebbe solo bisogno di questa tabella master se avete a cuore le relazioni tra i pacchetti di dati originali gli uni agli altri (quindi si possono memorizzare in modo ricezione, diciamo, ecc.).

In realtà, tutto si riduce a quanto i dati che avete, quanto ci si aspetta, quanto lavoro si vuole fare vs quanto hai già fatto, ecc.

Un'altra opzione che si può prendere in considerazione è Berkeley DB o uno dei suoi cloni. BDB è piuttosto basso livello, non c'è SQL. E 'praticamente un davvero piccolo, tabella hash veramente veloce di file-backed. E 'stato in giro per sempre, ed è utilizzato in un sacco di posti dove la velocità e la semplicità è fondamentale. Avresti bisogno di aggiungere alcune funzionalità in cima a fare quello che stai cercando di realizzare, però.

Nonostante tu abbia affermato che non esistono relazioni 1-molti, esistono :)

Consiglierei di creare due tabelle per l'archiviazione dei pacchetti.Uno per memorizzare informazioni di "intestazione" o "scalari", che sono comuni al pacchetto e, sebbene possano definire QUALI dati sono presenti, non sono i dati effettivi memorizzati nel pacchetto.

La tua seconda tabella memorizzerebbe i dati per ciascun pacchetto, con ciascuna combinazione campo-valore che rappresenta una riga in questa tabella.Ad esempio, le due tabelle seguenti:

create table packet
(
    packet_id int identity(1, 1) primary key,
    destination varchar(50),
    sender varchar(50),
    packet_type_id int not null
)

create table packet_field
(
    packet_field_id int identity(1, 1) primary key,
    packet_id int not null references packet (packet_id),
    field_id int not null,
    data varbinary(500)
)

Ovviamente queste due tabelle fanno ipotesi sul tipo e sulla dimensione dei dati da archiviare e non sono esaustive su ciò che dovranno archiviare.Tuttavia, questa struttura fondamentale consentirà formati di pacchetto definiti dinamicamente ed è uno schema facilmente indicizzabile (ad esempio, aggiungendo un indice su packet_id+field_id In packet_field sarebbe un gioco da ragazzi).

Tutto ciò di cui la tua applicazione è quindi responsabile è decomprimere il pacchetto e memorizzarlo nel tuo DB in questo schema, quindi reimballarlo (se necessario).

Naturalmente da questo punto in poi avrai bisogno di tabelle che memorizzino il formato effettivo del pacchetto.Qualcosa di simile a...

create table packet_type
(
    packet_type_id int identity(1, 1) primary key,
    name varchar(200) not null
)

create table packet_type_field
(
    field_id int identity(1, 1) primary key,
    packet_type_id int not null references packet_type (packet_type_id)
    field_offset int not null,
    name varchar(200) not null
)

Ancora una volta, ovviamente semplificato ma mostra l'idea di base.Avresti un singolo record nel tuo file packet_type tabella per ciascun formato di pacchetto e una riga nel file packet_type_field per ogni campo in un dato pacchetto.Questo dovrebbe darti la maggior parte delle informazioni necessarie per essere in grado di elaborare una porzione arbitraria di dati binari nello schema di archiviazione dei pacchetti sopra menzionato.

Tre metodi vengono in mente.

sFlow e IPFlow possono trasmettere una serie limitata di contenuto del pacchetto. Questo può essere registrato direttamente in diversi database diversi.

Un altro metodo più mirato sarebbe una scrittura una regola molto semplice sbuffo come indirizzo di origine o di destinazione. Poi hanno cattura sbuffo il payload dei pacchetti. In questo modo si potrebbe ottenere solo i dati effettivi si richiede. Per esempio si potrebbe prendere solo i campi di dati all'interno del pacchetto. per esempio. la password ecc.

ngrep può anche afferrare dati selettivi destra dal filo.

Naturalmente ognuno di questi potrebbe richiedere un rubinetto o di un monitor sessione su una porta, se non si sta facendo la cattura sul server / workstation stessa.

Anche se io non sono un grande fan di questa implementazione, abbiamo qualche software che fa essenzialmente questo per alcune liste di chiamata. In sostanza, ecco cosa fanno:

  1. Una tabella con le definizioni delle colonne - chiamarlo tblColumnDefs. Questa tabella contiene colonne come "Nome", "Tipo", "Lunghezza" e "Descrizione"
  2. Una tabella master esempio (tblPacketNames). In sostanza, solo "PacketTypeID", "PacketName", e "Descrizione" per ogni tipo di pacchetto che si sta definendo
  3. Una tabella di definizione di istanza (per voi, questo sarebbe tblPacketColumns). Questa tabella raccoglie le colonne predefinite insieme per formare la struttura di dati che si sta memorizzare. Ad esempio, potrebbe contenere "PacketTypeID", "ColumnNumber", "ColumnID". Nel database normalizzazione-parlare, questa è una tabella molti-a-molti, dal momento che le mappe delle colonne per i pacchetti che li utilizzano.
  4. In un secondo database (a causa delle dinamiche implicazioni SQL / iniezione di questo passo), le tabelle vengono create in modo dinamico per contenere i dati effettivi. Ad esempio, se hai definito (in step 2/3) di un tipo di pacchetto chiamato "PING", si potrebbe avere una tabella chiamata "PING" nel database per contenere i dati. Usereste tblPacketColumns, legato alla tblColumnDefs, per capire che cosa tipi di campo per creare e quanto grande dovrebbe essere. Si finisce con un insieme di tabelle che corrispondono alle definizioni del tipo di pacchetto dal punto 3, utilizzando le colonne dal punto 1.

NOTA: Non particolare come le implicazioni SQL-iniezione di passaggio 4. Creazione di tabelle in modo dinamico può portare ad alcune conseguenze se la sicurezza non è progettato correttamente e il contributo di tutti i campi inseriti dall'utente nella propria applicazione non è purificato correttamente, soprattutto se questa applicazione ha un'interfaccia che a disposizione dei chiamanti non attendibili (ad esempio, Internet).

Con questo, è possibile creare indici tuttavia che si vuole quando si creano le tabelle (forse si dispone di una colonna in fase 1 in cui si contrassegna alcune colonne come "indicizzabile", e gli indici vengono creati su di loro quando si creano le tabelle .

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top