導入
システム開発において、IPアドレスやMACアドレスを扱う際、それらを単なる「文字列(VARCHAR)」として保存していませんか?文字列で保存すると、バリデーションが煩雑になるだけでなく、ネットワーク範囲の検索(例:特定のサブネットに含まれるかどうかの判定)が困難になります。PostgreSQLが提供する「ネットワークアドレス型」を活用することで、データ整合性の確保と高度な検索処理を劇的に効率化できます。
基礎知識
PostgreSQLには、ネットワーク関連データを専門に扱う3つの主要な型が存在します。
inet型: ホストアドレスとネットワークの両方を保持できます。IPアドレスそのものを保存する場合に最適です。
cidr型: ネットワークアドレス専用です。ホストビットが含まれているとエラーになるため、サブネットの定義に厳格さを求める場合に適しています。
macaddr型: 6バイトのMACアドレスを格納します。コロンやハイフンなど、多様な表記を自動で正規化して保存してくれます。
これらを使う最大のメリットは、データ型のバリデーションがDB側で自動的に行われる点です。不正なIP形式をINSERTしようとすると、即座にエラーが返るため、アプリケーション側のコードを簡略化できます。
実装/解決策
ネットワークアドレス型の真骨頂は、演算子によるフィルタリングです。例えば、「特定のサブネットに含まれる全IPを検索する」といった処理が、非常に高速かつ直感的に記述できます。
以下に、テーブル定義と実用的なクエリのサンプルを示します。
サンプルプログラム
— 1. ネットワーク情報を管理するテーブルの作成
CREATE TABLE network_devices (
device_id SERIAL PRIMARY KEY,
device_name VARCHAR(50),
ip_address INET, — IPアドレスとサブネットを保持
mac_address MACADDR — MACアドレスを保持
);
— 2. データの挿入
— PostgreSQLが自動的に有効なIP/MAC形式かチェックします
INSERT INTO network_devices (device_name, ip_address, mac_address)
VALUES (‘Server-A’, ‘192.168.1.10/24′, ’08:00:2b:01:02:03’);
— 3. 実用的な検索:特定のサブネット(192.168.1.0/24)に含まれるホストを抽出
— <<= 演算子は「含まれる(is contained by)」を意味します
SELECT device_name, ip_address
FROM network_devices
WHERE ip_address <<= '192.168.1.0/24';
-- 4. 便利な関数:ネットワークアドレス部分のみを抽出
-- ホストビットを0にしてネットワークアドレスを取得します
SELECT device_name, set_masklen(ip_address, 24) AS network_addr
FROM network_devices;
応用・注意点
現場で運用する際の注意点をいくつか共有します。
1. 検索パフォーマンス: 大規模なネットワークリストを扱う場合、通常のインデックス(B-tree)も有効ですが、GiSTインデックスを併用することで、ネットワークの包含関係に関する検索を高速化できます。
2. バリデーション: アプリ側で正規表現を使ってチェックするよりも、DB側の型制約を信頼する方が安全です。ただし、クライアントに返すエラーメッセージをカスタマイズしたい場合は、アプリ側でプレチェックを入れるのがベストプラクティスです。
3. 型変換: 文字列から型変換が必要な場合は、::inet や ::cidr といったキャスト演算子を積極的に活用してください。
ネットワークアドレス型は、単なる「保存場所」ではなく、ネットワーク管理のロジックをDB側にオフロードできる強力なツールです。ぜひ明日からの設計に取り入れてみてください。

コメント