2013-03-23 12 views
9

Obecnie, aby zapisać adres IP, konwertuję go na numer i przechowuję w kolekcji. Zasadniczo robię to dla celów logowania. Oznacza to, że zależy mi na przechowywaniu informacji tak szybko, jak to możliwe i przy jak najmniejszej ilości miejsca.Zapisz adres IP w mongoDB

Będę rzadko używany do wysyłania zapytań.

Moje pomysły, które

  • Zapisywanie jako ciągi jest pewne nieefektywne.
  • Przechowywanie jako 4 cyfry będzie wolniejsze i zajmie więcej miejsca.

Mimo wszystko uważam, że jest to odpowiednia metoda, ale czy jest lepsza dla mojego celu?

+2

4 numery int nie będą działać dla adresów IPv6. 4 cyfry * nie * zajmują więcej miejsca niż ciąg. Szczerze mówiąc, musisz zdecydować, czy konwersja z łańcucha źródłowego, czy strat przestrzeni jest ważniejsza i zdecydować na podstawie tego. – Joe

+1

Czy chcesz zapytać o wynikową strukturę? MongoDB może nie być najlepszym wyborem do logowania, jeśli konkuruje z innymi operacjami zapisu bazy danych.Wypróbuj opcje i zobacz, jak działają. Spójrz na "statystyki" kolekcji (http://docs.mongodb.org/manual/reference/collection-statistics/), aby zobaczyć, jak duże są przeciętne dokumenty. Możesz także chcieć zrobić trochę w buforowaniu pamięci, zamiast pisać wiele drobnych pojedynczych dokumentów. – WiredPrairie

+0

Powinieneś przekonwertować na ciąg i zapisać go. – Abhishek

Odpowiedz

10

Zdecydowanie zapisać adresy IP w postaci liczb, jeśli nie masz nic przeciwko dodatkowej trochę pracy, że potrzebny, zwłaszcza gdy trzeba zrobić zapytania o adresy i masz dużych tabel/kolekcje.

Oto dlaczego:

bagażu

  • adres IPv4 jest 4 bajty, jeśli jest przechowywany jako liczba całkowita bez znaku.
  • Adres IPv4 waha się od 10 bajtów do 18 bajtów, gdy jest zapisany jako ciąg znaków w formie kropkowanej. (Przyjmijmy, że średnia wynosi 14 bajtów.)

To 7-15 bajtów dla znaków, plus 2-3 bajty, jeśli używasz zmiennej długości łańcucha znaków, która zmienia się w zależności od bazy danych " ponownie używać. Jeśli dostępna jest stała reprezentacja ciągów znaków, należy użyć 15-znakowego pola o stałej szerokości.

Miejsce na dysku jest tanie, więc nie ma to większego znaczenia w większości przypadków. Jednak pamięć nie jest tak tania, a jeśli masz dużą tabelę/kolekcję i chcesz wykonywać szybkie zapytania, potrzebujesz indeksu. Kara za przechowywanie kodu o wartości 2 x 2 drastycznie zmniejsza ilość rekordów, które można indeksować, zachowując jednocześnie indeks rezydentny w pamięci.

  • Adres IPv6 ma 16 bajtów, jeśli jest zapisany jako liczba całkowita bez znaku. (Prawdopodobnie jako wiele 4-lub 8-bajtowych liczb całkowitych, w zależności od platformy.)
  • Adres IPv6 zawiera się w przedziale od 6 bajtów do 42 bajtów, gdy jest zakodowany jako ciąg w skróconej notacji szesnastkowej.

Na najniższym końcu adres zwrotny pętli (:: 1) to 3 bajty plus ciąg znaków o zmiennej długości. Na wyższym końcu, adres taki jak 2002:4559:1FE2:1FE2:4559:1FE2:4559:1FE2 używa 39 bajtów plus narzut zmiennej długości łańcucha.

W przeciwieństwie do IPv4, nie można bezpiecznie założyć, że średnia długość łańcucha IPv6 będzie wynosić 6 i 42, ponieważ liczba adresów ze znaczną liczbą kolejnych zer jest bardzo małą częścią całkowitej przestrzeni adresowej IPv6.Tylko niektóre specjalne adresy, takie jak adresy pętli zwrotnej i autokonfiguracji, mogą być w ten sposób kompresowane.

To kara za przechowywanie w wysokości> 2x w przypadku kodowania ciągów znaków w porównaniu z kodowaniem całkowitym.

Network Math

Czy uważasz, że adresy IP routery przechowywać jako strun? Oczywiście, że nie.

Jeśli potrzebujesz matematyki sieciowej na adresach IP, reprezentacja ciągów znaków jest kłopotliwa. Na przykład. jeśli chcesz napisać zapytanie, które wyszuka wszystkie adresy w określonej podsieci ("zwróć wszystkie rekordy z adresem IP w 10.7.200.104/27", możesz to łatwo zrobić, zamaskowując adres liczby całkowitej za pomocą maski całkowitej podsieci. Mongo nie obsługuje tego konkretnego zapytania, ale większość RDBMS robi.) Jeśli przechowujesz adresy w postaci łańcuchów, twoje zapytanie będzie musiało przekonwertować każdy wiersz na liczbę całkowitą, a następnie zamaskować je, co jest wolniejsze o kilka rzędów wielkości (maskowanie bitowe). adres IPv4 może być wykonany w kilku cyklach procesora przy użyciu 2 rejestrów Konwersja ciągu na liczbę całkowitą wymaga zapętlenia ciągu znaków.)

Podobnie, zapytania zakresu ("zwracają wszystkie rekordy wszystkie rekordy pomiędzy 192.168.1.50 a 192.168 .50.100 ") z adresami całkowitymi będzie mógł korzystać z indeksów, podczas gdy zapytania zakresu na adresach ciągowych nie będą miały wartości

Bottom Line

zajmuje trochę więcej pracy, ale nie za dużo (istnieje milion Aton() i ntoa() funkcjonuje tam), ale jeśli coś buduje poważne i stałe i chcąc w przyszłości zabezpieczyć go przed przyszłymi wymaganiami i możliwością dużego zbioru danych, należy przechowywać adresy IP jako liczby całkowite, a nie ciągi.

Jeśli robisz coś szybkiego i brudnego i nie masz nic przeciwko możliwości przebudowy w przyszłości, użyj ciągów.

Dla celów OP, jeśli optymalizujesz prędkość i przestrzeń i nie myślisz, że chcesz często je przesyłać, to po co w ogóle korzystać z bazy danych? Wystarczy wydrukować adresy IP do pliku. Byłoby to szybsze i wydajniejsze przechowywanie niż przechowywanie w bazie danych (z powiązanym API i obciążeniem pamięci masowej).

0

IPv4 ma cztery bajty, więc można go zapisać w 32-bitowej liczbie całkowitej (BSON, typ 16).

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

+1

Myślę, że nie przeczytałeś mojego pytania. Wiem, że mogę przechowywać je w ten sposób i już napisałem to w pytaniu. Szukam bardziej wyszukanej odpowiedzi, a następnie jednego liniowca, który można zapisać jako liczbę całkowitą. –

+0

Zrobiłem to. Pytanie brzmi: "Zrobiłem to w najlepszy sposób, ale co jeszcze mogłoby być lepsze?". Więc w zasadzie moja odpowiedź brzmi "tak, myślę, że to najlepszy sposób". I nie trzeba pisać książki dla tak prostej odpowiedzi. –

-1

Najprostszym sposobem dla IPv4 jest konwersja na int za pomocą interesujących matematycznych podanych here.

używam następującą funkcję (js) do konwersji przed dopasowanie z 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

nie ma absolutnie żadnego sensu, aby to zrobić, ponieważ większość języków ma natywną funkcję, która robi coś bardzo podobnego. Także pytanie nie dotyczyło konwersji adresu IP na liczbę całkowitą. –

1

skuteczny sposób, aby zapisać adres IP jako int. Jeśli chcesz oznaczyć IP filtrem cidr, tutaj:

> 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'}) 

Utwórz indeks tagów.

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

Filtrowanie IP z zakresem cidr. ip2int('10.94.25.32') == 173938976.

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