Day27 前半のゴール
「“PostgreSQLはただのRDB”から“機能を足せるプラットフォーム”だと気づく」
今日のテーマは「拡張機能(extension)」、そして代表例としての PostGIS(地理情報)です。
ここまで学んできたのは、いわば「素のPostgreSQL」。
Day27 では、「PostgreSQLは“機能を後から足せるプラットフォーム”でもある」という視点を手に入れてもらいます。
前半のゴールはこうです。
拡張機能(extension)とは何かを、自分の言葉で説明できる。CREATE EXTENSION で「DBに機能をインストールする」イメージを持てる。
PostGIS が「地理情報を扱うための拡張」であることと、そのざっくりした使いどころをイメージできる。
まずは、「拡張機能ってそもそも何?」からいきます。
拡張機能とは何か
「PostgreSQLに“新しい脳みそ”を後付けする仕組み」
拡張機能(extension)は、一言でいうと「PostgreSQLに後から追加できる機能パック」です。
アプリでいう「プラグイン」や「モジュール」に近いイメージです。
拡張機能が追加できるものは、かなり幅広いです。
新しいデータ型(例:地理情報、JSONの強化版、暗号化用の型など)
新しい関数・演算子(例:距離計算、統計関数、暗号化・復号関数など)
新しいインデックス方式(例:地理情報向けのインデックス)
新しい集約関数やユーティリティ
これらを「PostgreSQL本体を改造することなく」「DBごとにオン・オフできる」ようにするのが、拡張機能の仕組みです。
重要なのは、「PostgreSQLは“拡張前提で設計されたRDB”」だということです。
つまり、「標準機能+必要な拡張を組み合わせて、自分たちの用途に最適化できるプラットフォーム」として考えると、見え方が変わります。
CREATE EXTENSION のイメージ
「OSにパッケージを入れてから、“このDBで使う”と宣言する」
拡張機能を使う流れは、ざっくり二段階です。
サーバ側(OS側)に拡張モジュールをインストールする。
特定のデータベースの中で CREATE EXTENSION を実行して、「このDBで使う」と宣言する。
OS側へのインストールは、環境によって違います(apt / yum / brew など)。
ここでは、「サーバ管理者がやる作業」として一旦箱に入れておきます。
開発者としてよく触るのは、二段階目の CREATE EXTENSION です。
例えば、標準でよく使われる拡張 uuid-ossp を有効化する場合は、こう書きます。
CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
SQLこれで、「このデータベースの中で uuid-ossp が使えるようになる」わけです。
新しい関数(uuid_generate_v4() など)が増え、UUIDを簡単に生成できるようになります。
ここでのポイントは、「拡張は“DBごとに有効化する”」ということです。
同じPostgreSQLサーバ上でも、「このDBではPostGISを使う」「あのDBでは使わない」といった切り分けができます。
PostGISとは何か
「PostgreSQLを“地理情報データベース”に変える拡張」
PostGIS は、PostgreSQLの拡張機能の中でも超有名な存在です。
一言でいうと、「PostgreSQLを地理情報(GIS)対応にする拡張」です。
PostGISを入れると、ざっくりこんなことができるようになります。
位置情報を表す専用のデータ型(POINT, LINESTRING, POLYGON など)が使える。
「この2点の距離は?」「この点はこのエリアの中か?」といった空間クエリが書ける。
地図アプリや位置情報サービスで必要な処理を、DB側で効率よく実行できる。
つまり、「緯度経度をただの数値として持つ」のではなく、
「空間として意味のあるデータ」として扱えるようになるわけです。
イメージとしては、「PostgreSQLに“地図の脳みそ”を付ける」のがPostGISです。
例題:店舗の位置情報をPostGISで持つイメージ
「POINT型で“緯度経度”を1つの値として扱う」
具体的なイメージを持つために、「店舗の位置情報」を扱う例を考えます。
PostGISを使わない場合、店舗テーブルはこんな感じになりがちです。
CREATE TABLE shops (
id bigserial PRIMARY KEY,
name text NOT NULL,
lat double precision NOT NULL,
lon double precision NOT NULL
);
SQL緯度(lat)と経度(lon)を別々のカラムで持っています。
これでも動きますが、「距離計算」「範囲検索」などをやろうとすると、
毎回「地球は球体で〜」みたいな計算式を自分で書く必要が出てきます。
PostGISを使うと、こう書けます。
CREATE TABLE shops (
id bigserial PRIMARY KEY,
name text NOT NULL,
location geometry(Point, 4326) NOT NULL
);
SQLここで出てきた geometry(Point, 4326) が、PostGISのデータ型です。
geometry
→ 「空間オブジェクト」を表す基本型。
Point
→ 点(位置)を表すサブタイプ。
4326
→ 世界測地系(WGS84)、つまり一般的な緯度経度の座標系を表す番号。
これにより、「location カラム1つで“位置情報”を表す」ことができます。
INSERTするときは、PostGISの関数を使います。
INSERT INTO shops (name, location)
VALUES (
'テストカフェ',
ST_SetSRID(ST_MakePoint(139.7000, 35.6895), 4326)
);
SQLST_MakePoint(経度, 緯度) で点を作り、ST_SetSRID(..., 4326) で「これはWGS84の座標だよ」と教えています。
ここでの重要ポイントは、「PostGISを使うと、緯度経度を“ただの数値”ではなく“空間オブジェクト”として扱える」ということです。
例題:ある地点から半径1km以内の店舗を探す
「“距離で検索する”をSQLで書ける気持ちよさ」
PostGISの真価は、「空間クエリ」が書けるところにあります。
例えば、「この地点から半径1km以内の店舗を探したい」という要件を考えます。
地点(ユーザーの現在地など)を、経度・緯度で持っているとします。
-- 東京駅あたりを仮の現在地とする
SELECT *
FROM shops
WHERE ST_DWithin(
location::geography,
ST_SetSRID(ST_MakePoint(139.7671, 35.6812), 4326)::geography,
1000
);
SQLここで使っている ST_DWithin は、「2つの位置が、指定した距離以内かどうか」を判定する関数です。
location::geography
→ geometry を geography にキャストして、「地球の丸さを考慮した距離計算」をするための型変換。
ST_SetSRID(ST_MakePoint(…), 4326)::geography
→ 比較対象の点(現在地)を geography 型に変換。
1000
→ 距離(メートル)。ここでは1km。
このクエリは、「東京駅から1km以内にある店舗」を全部返してくれます。
もしPostGISなしで同じことをやろうとすると、
自分で距離計算の式を書き、インデックスも工夫しないといけません。
PostGISは、そのあたりを「地理情報の専門家が作ったロジック」と「専用インデックス」で肩代わりしてくれます。
ここでの学びは、「拡張機能を入れると、“その分野の専門知識”をDBにインストールできる」ということです。
拡張機能を使うときの“責任の範囲”
「便利さの裏に、“依存する”という選択がある」
拡張機能は強力ですが、「入れた瞬間から、その拡張に依存する」ことになります。
これは、セキュリティ・運用・将来の移行の観点で、ちゃんと意識しておくべきポイントです。
運用面
バージョンアップ時に、「PostgreSQL本体+拡張」の互換性を確認する必要がある。
バックアップ・リストア時にも、「拡張が入っている前提」で環境を用意する必要がある。
セキュリティ面
拡張はC言語などで書かれていることが多く、「DBの中で動くネイティブコード」です。
信頼できる拡張だけを使う、不要な拡張は入れない、という判断が大事です。
移行面
将来、別のRDBMSに移行したくなったとき、
PostGISや特定拡張に強く依存していると、「移行コスト」が跳ね上がる。
だからこそ、「拡張を使うかどうか」は、
「その機能がどれだけ価値を生むか」と「その拡張にどれだけ縛られてもいいか」のバランスで決める必要があります。
PostGISレベルのメジャー拡張は、「依存してもいい」と判断されることが多いですが、
それでも「入れた瞬間から“PostgreSQL+PostGIS前提の世界”になる」という自覚は持っておきたいところです。
Day27 前半のまとめ
拡張機能(extension)は、PostgreSQLに「新しいデータ型・関数・インデックス方式などの“機能パック”を後付けする仕組み」であり、サーバ側にモジュールを入れたうえで、各データベースごとに CREATE EXTENSION を実行することで「このDBでこの拡張を使う」と宣言する。
PostGISはその代表例として、geometry/geography 型や空間関数(ST_MakePoint, ST_DWithin など)を提供し、「店舗の位置を geometry(Point, 4326) で持ち、ある地点から半径1km以内の店舗をSQLで検索する」といった“地理情報の専門知識”をDB側にインストールして使えるようにしてくれる一方、拡張に依存するということは「運用・セキュリティ・将来の移行もその拡張前提になる」という意味でもある――ここまでの構造とイメージが掴めていれば、Day27 前半としてはとても良いスタートラインです。
