2013-03-23 12 views
9

Attualmente per salvare un indirizzo IP lo converto in numero e lo memorizzo nella raccolta. Fondamentalmente sto facendo questo per scopi di registrazione. Ciò significa che mi preoccupo di memorizzare le informazioni il più velocemente possibile e con il minor spazio possibile.salva l'indirizzo IP in mongoDB

Lo userò raramente per l'interrogazione.

mie idee che

  • Memorizzazione come stringhe è certa inefficiente.
  • La memorizzazione come 4 cifre sarà più lenta e richiederà più spazio.

Tuttavia, penso che questo sia un metodo adeguato, ma ce n'è uno migliore per il mio scopo?

+2

4 ints non funziona per gli indirizzi IPv6. 4 cifre * non * occupano più spazio di una stringa. Onestamente, devi decidere se convertire la stringa di origine o la perdita di spazio è più importante e decidere in base a ciò. – Joe

+1

Hai bisogno di interrogare la struttura risultante? MongoDB potrebbe non essere la scelta migliore per la registrazione se è in competizione con altre operazioni di scrittura del database.Prova le opzioni e guarda come si comportano. Guarda le 'stats' per la raccolta (http://docs.mongodb.org/manual/reference/collection-statistics/) per vedere quanto sono grandi i documenti medi. Si potrebbe anche voler fare un po 'di memoria buffer piuttosto che scrivere molti piccoli documenti individuali. – WiredPrairie

+0

Dovresti convertire in stringa e memorizzarlo. – Abhishek

risposta

10

sicuramente risparmiare indirizzi IP come numeri, se non ti dispiace l'extra po 'di lavoro che ci vuole, soprattutto se avete bisogno di fare domande sulle indirizzi e si dispone di grandi tavoli/collezioni.

Ecco perché:

bagagli

  • Un indirizzo IPv4 è di 4 byte se conservato come numero intero senza segno.
  • Un indirizzo IPv4 varia tra 10 byte e 18 byte quando viene scritto come una stringa in forma puntata. (Supponiamo che la media è di 14 byte.)

Questo è 7-15 byte per i caratteri, oltre a 2-3 byte se si sta utilizzando un tipo di stringa di lunghezza variabile, che varia in base al database' usando. Se si dispone di una rappresentazione di stringa di lunghezza fissa disponibile, è necessario utilizzare un campo a larghezza fissa di 15 caratteri.

L'archiviazione su disco è economica, quindi non è un fattore nella maggior parte dei casi d'uso. La memoria, tuttavia, non è così economica, e se si dispone di una tabella/raccolta di grandi dimensioni e si desidera eseguire query veloci, è necessario un indice. La penalità di memorizzazione 2-3 volte della codifica delle stringhe riduce drasticamente la quantità di record che è possibile indicizzare mantenendo comunque l'indice residente in memoria.

  • Un indirizzo IPv6 è di 16 byte se memorizzato come numero intero senza segno. (Probabilmente come multipli di 4 o 8 byte interi, a seconda della piattaforma.)
  • Un indirizzo IPv6 varia da 6 byte a 42 byte quando è codificato come stringa in notazione esadecimale abbreviata.

Sul lato inferiore, un indirizzo di loopback (:: 1) è 3 byte più la stringa di lunghezza variabile in testa. Nella fascia alta, un indirizzo come 2002:4559:1FE2:1FE2:4559:1FE2:4559:1FE2 utilizza 39 byte più l'overhead della stringa di lunghezza variabile.

Diversamente da IPv4, non è sicuro assumere che la lunghezza media della stringa IPv6 sarà media di 6 e 42, poiché il numero di indirizzi con un numero significativo di zeri consecutivi è una frazione molto piccola dello spazio di indirizzi IPv6 complessivo.Solo alcuni indirizzi speciali, come gli indirizzi di loopback e autoconf, possono essere comprimibili in questo modo.

nuovo, questa è una penalità di memorizzazione> 2x per la stringa di codifica rispetto codifica intera.

rete Math

Pensi che gli indirizzi IP dei router negozio come stringhe? Certo che non lo fanno.

Se avete bisogno di fare matematica di rete agli indirizzi IP, la rappresentazione di stringa è una seccatura. Per esempio. se si desidera scrivere una query che cerca tutti gli indirizzi su una sottorete specifica ("restituisce tutti i record con un indirizzo IP in 10.7.200.104/27", è possibile farlo facilmente mascherando un indirizzo intero con una maschera di sottorete intera. Mongo non supporta questa particolare query, ma la maggior parte degli RDBMS.) Se memorizzi gli indirizzi come stringhe, la tua query dovrà convertire ogni riga in un numero intero, quindi mascherarla, che è più lenta di diversi ordini di grandezza. per un indirizzo IPv4 può essere fatto in pochi cicli di CPU utilizzando 2 registri. Convertire una stringa in un numero intero richiede il looping sulla stringa.)

Analogamente, query di intervallo ("restituisce tutti i record tutti i record tra 192.168.1.50 e 192.168 .50.100") con gli indirizzi interi saranno in grado di utilizzare gli indici, mentre le query gamma su indirizzi di stringa non lo faranno.

0.123.

The Bottom Line

Ci vuole un po 'più di lavoro, ma non molto (ci sono un milione di Aton() e ntoa() funzioni là fuori), ma se si sta costruendo qualcosa di serio e solido e vuoi renderlo a prova di futuro contro i requisiti futuri e la possibilità di un set di dati di grandi dimensioni, dovresti memorizzare gli indirizzi IP come numeri interi, non come stringhe.

Se stai facendo qualcosa di veloce e sporco e non vi dispiace la possibilità di rimodellamento, in futuro, quindi usare le stringhe.

fini del PO, se si sta ottimizzando per la velocità e lo spazio e non si pensa che si desidera interrogare spesso, allora perché utilizza un database a tutti? Basta stampare gli indirizzi IP in un file. Sarebbe più veloce e più efficiente in termini di storage rispetto all'archiviazione in un database (con API associata e overhead di archiviazione).

0

Un IPv4 è quattro byte, quindi è possibile memorizzarlo in un numero intero a 32 bit (tipo BSON 16).

Vedi http://docs.mongodb.org/manual/reference/bson-types

+1

Penso che tu non abbia letto la mia domanda. So che posso memorizzarli in questo modo e l'ho già scritto nella domanda. Sto cercando una risposta più elaborata quindi solo un one-liner è possibile memorizzarli come interi. –

+0

L'ho letto. La tua domanda suona come "l'ho fatto nel modo migliore, ma cos'altro sarebbe meglio?". Quindi in sostanza la mia risposta dice "Sì, penso che sia il modo migliore". E non c'è bisogno di scrivere un libro per una risposta così semplice. –

-1

più semplice modo per IPv4 è quello di convertire in int utilizzando l'interessante matematica fornito here.

Io uso la seguente funzione (js) per convertire prima della corrispondenza con db

ipv4Number: function (ip) { 
    iparray = ip.split("."); 
    ipnumber = parseInt(iparray[3]) + 
     parseInt(iparray[2]) * 256 + 
     parseInt(iparray[1]) * Math.pow(256, 2) + 
     parseInt(iparray[0]) * Math.pow(256, 3); 
    if (parseInt(ipnumber) > 0)return ipnumber; 
    return 0; 
} 
+2

non ha assolutamente senso farlo, perché la maggior parte delle lingue ha la funzione nativa che sta facendo qualcosa di veramente simile. Inoltre la domanda non era su come convertire l'IP in intero. –

1

Un modo efficace per salvare un indirizzo IP come int. Se si desidera taggare un ip con filtro cidr, una demo qui:

> db.getCollection('iptag').insert({tags: ['office'], hostmin: 2886991873, hostmax: 2887057406, cidr: '172.20.0.0/16'}) 
> db.getCollection('iptag').insert({tags: ['server'], hostmin: 173867009, hostmax: 173932542, cidr: '10.93.0.0/16'}) 
> db.getCollection('iptag').insert({tags: ['server'], hostmin: 173932545, hostmax: 173998078, cidr: '10.94.0.0/16'}) 

Creare tag indice.

> db.getCollection('iptag').ensureIndex(tags: 1) 

Filtro ip con gamma cidr. ip2int('10.94.25.32') == 173938976.

> db.getCollection('iptag').find({hostmin: {$lte: 173938976}, hostmax: {$gte: 173938976}})