【実務・中級編】 ネットワークアドレス型 – PostgreSQL

「IPアドレスをどう保存するか?」

これ、新人の頃に一度は悩むポイントだよね。`varchar(15)` で適当に突っ込んで、いざ「特定のサブネットに含まれるIPを検索したい」なんて要件が来ると、途端に `LIKE` 検索で死ぬほど重いクエリを叩くことになる……。

PostgreSQLを触っているなら、そんな苦労はしなくていい。今回は、PostgreSQLが標準で持っている「ネットワークアドレス型」の魔法について、現場の視点で語らせてもらうよ。

—

なぜ `varchar` を捨てて「ネットワークアドレス型」を使うべきか

PostgreSQLには、`inet`、`cidr`、`macaddr` という、ネットワーク専用の型が用意されている。これらを使う理由は、単なる「型チェック」だけじゃない。

1. バリデーションが自動で走る: 間違った形式の文字列を入れようとすると、DB側で即座に弾いてくれる。
2. ストレージ効率: 文字列として保存するより遥かに省スペースで、検索も速い。
3. 演算子が最強: 「このIPはこのサブネットに含まれるか?」という計算が、専用の演算子一発で終わる。

これが、僕らが `inet` 型を愛する理由だ。

—

現場でよく使う3つの型

1. `inet` 型:IPアドレスとサブネット

一番出番が多いやつだ。「192.168.1.1」のような単体IPも、「192.168.1.0/24」のようなサブネットも両方扱える。迷ったらこれを選べば間違いない。

2. `cidr` 型:ネットワークの定義

`inet` と似ているけど、こちらは「ネットワークアドレスそのもの」を厳密に扱う。例えば `192.168.1.5/24` を入れようとすると、「それはサブネットじゃないよ(ホスト部が混ざってるよ)」と怒ってくれる。IP範囲を厳密に管理したいならこっちだ。

3. `macaddr` 型:MACアドレス

その名の通り。IEEE 802 MACアドレスを保存するためのもの。これもバリデーションが効くから、変な形式のデータが入る心配がない。

—

実践!こんなクエリが書けるようになる

例えば、特定のサブネット(例: `192.168.1.0/24`)に属するIPアドレスを検索したいとき。`LIKE` なんて使わずに、こう書く。

— 演算子 << は「左側が右側のサブネットに含まれるか」を判定する SELECT FROM access_logs WHERE ip_address << '192.168.1.0/24'; これ、内部的にはビット演算で行われるから爆速なんだ。インデックスももちろん貼れる。`GIST` インデックスを貼っておけば、数百万件のログから瞬時に範囲検索ができるよ。 CREATE INDEX idx_access_logs_ip ON access_logs USING GIST (ip_address inet_ops);

便利すぎる組み込み関数たち

他にも、現場で地味に重宝する関数が揃っている。

  • `host(ip)`: `inet` 型からサブネットマスクを外して、純粋なIPアドレス文字列を取り出す。
  • `masklen(ip)`: サブネットマスク長(24とか)を返す。
  • `broadcast(ip)`: そのネットワークのブロードキャストアドレスを計算する。

— 例: ネットワークの範囲を知りたいとき
SELECT
host(ip_address) AS host,
broadcast(ip_address) AS broadcast
FROM subnets;

—

先輩からのアドバイス:ハマりどころ

最後に一つだけ注意点。`inet` 型を使うときは、「何を検索対象にしたいか」を設計段階で決めておくこと。

たとえば、「特定のIPが含まれるかどうか」を頻繁に検索するなら `inet` 型+`GIST` インデックスが定石だけど、単純に「IPアドレスの完全一致」しか検索しないなら、通常の `B-tree` インデックスでも十分機能する。

あと、アプリケーション側でバリデーションをかけるのは当然として、DB側でもしっかり型を指定することで、「誰かが誤って変なデータを流し込んだ」という事故を未然に防げる。これが堅牢なシステムを作る第一歩だよ。

PostgreSQLは、こういった「現場の痒いところに手が届く機能」が本当に豊富だ。適材適所で型を選んで、無駄なコードを書く時間を減らしていこうぜ。

何か分からないことがあったら、いつでもコードを見せに来てよ。また次回の記事で!

コメント

タイトルとURLをコピーしました