特にアドレスに対してクエリを実行する必要があり、テーブルやコレクションが大きい場合は、余分な作業を気にしない場合は、IPアドレスを数値として確実に保存してください。
理由は次のとおりです:
ストレージ
- 符号なし整数として格納されている場合、IPv4アドレスは4バイトです。
- IPv4アドレスは、点線のオクト形式の文字列として書き出される場合、10バイトから18バイトの間で変化します。 (平均が14バイトであると仮定しましょう。)
これは、文字の場合は7〜15バイトであり、可変長の文字列型を使用している場合は2〜3バイトです。これは、使用しているデータベースによって異なります。固定長の文字列表現を使用できる場合は、15文字の固定幅フィールドを使用する必要があります。
ディスクストレージは安価であるため、ほとんどのユースケースではそれは要因ではありません。ただし、メモリはそれほど安価ではありません。大きなテーブル/コレクションがあり、高速クエリを実行する場合は、インデックスが必要です。文字列エンコーディングの2〜3倍のストレージペナルティにより、インデックスをメモリに常駐させたまま、インデックスを作成できるレコードの量が大幅に削減されます。
- 符号なし整数として格納されている場合、IPv6アドレスは16バイトです。 (プラットフォームに応じて、複数の4バイトまたは8バイトの整数のようになります。)
- IPv6アドレスは、16進表記の省略形で文字列としてエンコードされた場合、6バイトから42バイトの範囲になります。
ローエンドでは、ループバックアドレス(::1)は3バイトに可変長の文字列オーバーヘッドを加えたものです。ハイエンドでは、2002:4559:1FE2:1FE2:4559:1FE2:4559:1FE2
のようなアドレス 39バイトと可変長文字列オーバーヘッドを使用します。
IPv4とは異なり、IPv6の平均文字列長が6と42の平均であると想定するのは安全ではありません。これは、連続するゼロの数が多いアドレスの数が、IPv6アドレス空間全体のごく一部であるためです。ループバックアドレスやautoconfアドレスなど、一部の特別なアドレスのみがこの方法で圧縮できる可能性があります。
繰り返しになりますが、これは文字列エンコーディングと整数エンコーディングの2倍を超えるストレージペナルティです。
ネットワーク数学
ルーターはIPアドレスを文字列として保存すると思いますか?もちろんそうではありません。
IPアドレスでネットワーク計算を行う必要がある場合、文字列表現は面倒です。例えば。特定のサブネット上のすべてのアドレスを検索するクエリを作成する場合(「10.7.200.104/27のIPアドレスを持つすべてのレコードを返す」、整数のアドレスを整数のサブネットマスクでマスクすることで簡単に実行できます。) Mongoはこの特定のクエリをサポートしていませんが、ほとんどのRDBMSはサポートしています。)アドレスを文字列として格納する場合、クエリは各行を整数に変換してからマスクする必要があります。これは数桁遅くなります(ビットワイズマスキング)。 IPv4アドレスの場合、2つのレジスタを使用して数CPUサイクルで実行できます。文字列を整数に変換するには、文字列をループする必要があります。)
同様に、整数アドレスを使用した範囲クエリ(「すべてのレコードを192.168.1.50から192.168.50.100までのすべてのレコードを返す」)はインデックスを使用できますが、文字列アドレスに対する範囲クエリは使用できません。
結論
少し手間がかかりますが、それほど多くはありません(100万個のaton()およびntoa()関数があります)が、真面目で堅実なものを構築していて、将来の要件に対して将来にわたって利用できるようにしたい場合は、大規模なデータセットの可能性がある場合は、IPアドレスを文字列ではなく整数として保存する必要があります。
迅速で汚いことをしていて、将来の改造の可能性を気にしない場合は、文字列を使用してください。
OPの目的で、速度とスペースを最適化していて、頻繁にクエリを実行したくない場合は、なぜデータベースを使用するのでしょうか。 IPアドレスをファイルに出力するだけです。これは、データベースに保存するよりも高速でストレージ効率が高くなります(関連するAPIとストレージのオーバーヘッドがあります)。