特にアドレスに対してクエリを実行する必要があり、大きなテーブル/コレクションがある場合は、IP アドレスを数字として保存してください。
理由は次のとおりです。
保管所
- 符号なし整数として格納されている場合、IPv4 アドレスは 4 バイトです。
- ドット付き 8 進数形式の文字列として書き出すと、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 とストレージのオーバーヘッドを伴います)。