redis_fdw は、リレーショナルデータベース PostgreSQL からキーバリューストア Redis にアクセスする拡張モジュールです。redis_fdw を使うことで、高速なデータの読み書きができる Redis と、SQL で複雑なデータの操作ができる PostgreSQL 間で円滑なデータの連携ができます。
この記事では、redis_fdw の概要、インストール、基本的な使い方、テーブルオプションについて説明します。なお、Redis 自体の説明については Redis の紹介 をお読みください。
redis_fdw とは
redis_fdw の名前につく fdw は外部データラッパ (Foreign Data Wrapper) を表し、PostgreSQL から Oracle や CSV ファイルなど、PostgreSQL 外のデータに外部テーブルとしてアクセスする機能です。redis_fdw はこの機能を使って Redis 上のデータにアクセスします。

redis_fdw は、もともと PostgreSQL 開発者の一人 Dave Page 氏が実験的に開発し、その後、Andrew Dunstan 氏が開発を引き継ぎ、本番利用向けに改修しました。
ソースコードは GitHub リポジトリ上で公開され、PostgreSQL ライセンスに従って配布されています。PostgreSQL の対応バージョンは 9.1 以降で、2022 年 8 月時点で最新の PostgreSQL 14 にも対応しています。
なお、PGDG リポジトリ[1] で同じ名前のパッケージが配布されていますが、ここで取り上げる redis_fdw とは異なるもので、便宜上、リポジトリ名をとって rw_redis_fdw と呼びます。
rw_redis_fdw も Redis 用外部データラッパで、名前につく rw は読み書き (Read-Write) を表し、以前は書き込みに対応していなかった redis_fdw に対して名づけられたものと考えられますが、現在は redis_fdw も書き込みに対応しています。
rw_redis_fdw は redis_fdw に比べて機能は多いですが、ここでは、より広く使われている redis_fdw を取り上げます。
redis_fdw のインストール
redis_fdw をインストールします。
ここでは、Rocky Linux 8 上に PostgreSQL、Redis をセットアップした上、redis_fdw をソースコードからビルドし、インストールします。
- PGDG リポジトリをインストールします。
$ sudo dnf -qy install https://download.postgresql.org/pub/repos/yum/reporpms/EL-$(rpm -E %rhel-%_arch)/pgdg-redhat-repo-latest.noarch.rpm Installed: pgdg-redhat-repo-42.0-24.noarch
PostgreSQL は PGDG リポジトリからインストールします。
これ以降、
dnfコマンドの実行時に署名つきパッケージの検証に必要な PGP キーの取り込みを表すメッセージが出力される場合があります。 - PostgreSQL モジュールを無効にします。
$ sudo dnf -qy module disable postgresql
OS 標準のリポジトリからも PostgreSQL をインストールできますが、バージョンが古いので、PGDG リポジトリのほうを使うように、PostgreSQL モジュールを無効にしています。
- PostgreSQL をインストールします。
$ sudo dnf -qy install postgresql14-server Installed: lz4-1.8.3-3.el8_4.x86_64 postgresql14-14.4-1PGDG.rhel8.x86_64 postgresql14-libs-14.4-1PGDG.rhel8.x86_64 postgresql14-server-14.4-1PGDG.rhel8.x86_64
ここでは、PostgreSQL 14 をインストールしています。
パッケージ名
postgresql14-serverをはじめ、これ以降、コマンドラインに含まれる14は PostgreSQL のバージョンを表します。お使いになるバージョンに合わせ、適宜、読み替えてください。 - データベースクラスタを作成します。
$ PGSETUP_INITDB_OPTIONS="-E UTF8 --no-locale" sudo -E /usr/pgsql-14/bin/postgresql-14-setup initdb Initializing database ... OK
データベースクラスタはデータベースを格納する領域です。作成には通常
initdbコマンドを使いますが、ここでは、パッケージに付属のスクリプトを使います。環境変数
PGSETUP_INITDB_OPTIONSにはinitdbコマンドに渡すオプションを指定します。ここでは、デフォルトのエンコーディングを UTF8、ロケールをなしに指定しています。 - PostgreSQL のサービスを起動します。
$ sudo systemctl start postgresql-14
- Redis をインストールします。
$ sudo dnf -qy install redis Installed: redis-5.0.3-5.module+el8.5.0+657+2674830e.x86_64
- Redis のサービスを起動します。
$ sudo systemctl start redis
- EPEL リポジトリ[2] をインストールします。
$ sudo dnf -qy install epel-release Installed: epel-release-8-13.el8.noarch
redis_fdw の動作に必要な Redis 用 C 言語ライブラリ Hiredis は EPEL リポジトリからインストールします。
- redis_fdw のビルドに必要なパッケージをインストールします。
$ sudo dnf -qy install make redhat-rpm-config postgresql14-devel hiredis-devel Upgraded: libgcc-8.5.0-10.1.el8_6.x86_64 libgomp-8.5.0-10.1.el8_6.x86_64 libstdc++-8.5.0-10.1.el8_6.x86_64 Installed: annobin-10.29-3.el8.x86_64 binutils-2.30-113.el8.x86_64 clang-13.0.1-1.module+el8.6.0+825+7e27476a.x86_64 clang-devel-13.0.1-1.module+el8.6.0+825+7e27476a.x86_64 clang-libs-13.0.1-1.module+el8.6.0+825+7e27476a.x86_64 clang-resource-filesystem-13.0.1-2.module+el8.6.0+987+d36ea6a1.x86_64 clang-tools-extra-13.0.1-1.module+el8.6.0+825+7e27476a.x86_64 cmake-filesystem-3.20.2-4.el8.x86_64 compiler-rt-13.0.1-1.module+el8.6.0+825+7e27476a.x86_64 cpp-8.5.0-10.1.el8_6.x86_64 dwz-0.12-10.el8.x86_64 efi-srpm-macros-3-3.el8.noarch emacs-filesystem-1:26.1-7.el8.noarch gcc-8.5.0-10.1.el8_6.x86_64 gcc-c++-8.5.0-10.1.el8_6.x86_64 ghc-srpm-macros-1.4.2-7.el8.noarch glibc-devel-2.28-189.5.el8_6.x86_64 glibc-headers-2.28-189.5.el8_6.x86_64 go-srpm-macros-2-17.el8.noarch hiredis-0.13.3-13.el8.x86_64 hiredis-devel-0.13.3-13.el8.x86_64 isl-0.16.1-6.el8.x86_64 kernel-headers-4.18.0-372.13.1.el8_6.x86_64 libicu-devel-60.3-2.el8_1.x86_64 libmpc-1.1.0-9.1.el8.x86_64 libomp-13.0.1-1.module+el8.6.0+825+7e27476a.x86_64 libomp-devel-13.0.1-1.module+el8.6.0+825+7e27476a.x86_64 libstdc++-devel-8.5.0-10.1.el8_6.x86_64 libxcrypt-devel-4.1.1-6.el8.x86_64 llvm-13.0.1-1.module+el8.6.0+825+7e27476a.x86_64 llvm-devel-13.0.1-1.module+el8.6.0+825+7e27476a.x86_64 llvm-libs-13.0.1-1.module+el8.6.0+825+7e27476a.x86_64 llvm-static-13.0.1-1.module+el8.6.0+825+7e27476a.x86_64 llvm-test-13.0.1-1.module+el8.6.0+825+7e27476a.x86_64 make-1:4.2.1-11.el8.x86_64 ocaml-srpm-macros-5-4.el8.noarch openblas-srpm-macros-2-2.el8.noarch perl-srpm-macros-1-25.el8.noarch postgresql14-devel-14.4-1PGDG.rhel8.x86_64 python-rpm-macros-3-41.el8.noarch python-srpm-macros-3-41.el8.noarch python3-rpm-macros-3-41.el8.noarch qt5-srpm-macros-5.15.2-1.el8.0.1.noarch redhat-rpm-config-129-1.el8.noarch rust-srpm-macros-5-2.el8.noarch unzip-6.0-46.el8.x86_64 zip-3.0-23.el8.x86_64
- redis_fdw のソースコードをダウンロードします。
$ curl -LOs https://github.com/pg-redis-fdw/redis_fdw/archive/refs/heads/REL_14_STABLE.tar.gz
redis_fdw のソースコードは PostgreSQL のバージョンごとにブランチが分かれていて、ダウンロード時はブランチ名を指定する必要があります。ここでは、PostgreSQL 14 に対応したブランチ
REL_14_STABLEを指定しています。 - redis_fdw のソースコードを展開します。
$ tar -xzf REL_14_STABLE.tar.gz
- redis_fdw をビルドします。
$ make -C redis_fdw-REL_14_STABLE USE_PGXS=1 PG_CONFIG=/usr/pgsql-14/bin/pg_config make: ディレクトリ '/home/vagrant/redis_fdw-REL_14_STABLE' に入ります gcc -Wall -Wmissing-prototypes -Wpointer-arith -Wdeclaration-after-statement -Werror=vla -Wendif-labels -Wmissing-format-attribute -Wimplicit-fallthrough=3 -Wcast-function-type -Wformat-security -fno-strict-aliasing -fwrapv -fexcess-precision=standard -Wno-format-truncation -Wno-stringop-truncation -O2 -g -pipe -Wall -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -Wp,-D_GLIBCXX_ASSERTIONS -fexceptions -fstack-protector-strong -grecord-gcc-switches -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1 -m64 -mtune=generic -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection -fPIC -I. -I./ -I/usr/pgsql-14/include/server -I/usr/pgsql-14/include/internal -D_GNU_SOURCE -I/usr/include/libxml2 -I/usr/include -c -o redis_fdw.o redis_fdw.c gcc -Wall -Wmissing-prototypes -Wpointer-arith -Wdeclaration-after-statement -Werror=vla -Wendif-labels -Wmissing-format-attribute -Wimplicit-fallthrough=3 -Wcast-function-type -Wformat-security -fno-strict-aliasing -fwrapv -fexcess-precision=standard -Wno-format-truncation -Wno-stringop-truncation -O2 -g -pipe -Wall -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -Wp,-D_GLIBCXX_ASSERTIONS -fexceptions -fstack-protector-strong -grecord-gcc-switches -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1 -m64 -mtune=generic -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection -fPIC -shared -o redis_fdw.so redis_fdw.o -L/usr/pgsql-14/lib -Wl,--as-needed -L/usr/lib64 -L/usr/lib64 -Wl,--as-needed -Wl,-rpath,'/usr/pgsql-14/lib',--enable-new-dtags -lhiredis /usr/bin/clang -Wno-ignored-attributes -fno-strict-aliasing -fwrapv -Wno-unused-command-line-argument -Wno-compound-token-split-by-macro -O2 -I. -I./ -I/usr/pgsql-14/include/server -I/usr/pgsql-14/include/internal -D_GNU_SOURCE -I/usr/include/libxml2 -I/usr/include -flto=thin -emit-llvm -c -o redis_fdw.bc redis_fdw.c make: ディレクトリ '/home/vagrant/redis_fdw-REL_14_STABLE' から出ます
引数の変数
USE_PGXSには PostgreSQL 用拡張モジュールの構築基盤 PGXS を使うことを表す1、PG_CONFIGにはpg_configコマンドのパスを指定します。 - redis_fdw をインストールします。
$ sudo make -C redis_fdw-REL_14_STABLE install USE_PGXS=1 PG_CONFIG=/usr/pgsql-14/bin/pg_config make: ディレクトリ '/home/vagrant/redis_fdw-REL_14_STABLE' に入ります /usr/bin/mkdir -p '/usr/pgsql-14/lib' /usr/bin/mkdir -p '/usr/pgsql-14/share/extension' /usr/bin/mkdir -p '/usr/pgsql-14/share/extension' /usr/bin/install -c -m 755 redis_fdw.so '/usr/pgsql-14/lib/redis_fdw.so' /usr/bin/install -c -m 644 .//redis_fdw.control '/usr/pgsql-14/share/extension/' /usr/bin/install -c -m 644 .//redis_fdw--1.0.sql '/usr/pgsql-14/share/extension/' /usr/bin/mkdir -p '/usr/pgsql-14/lib/bitcode/redis_fdw' /usr/bin/mkdir -p '/usr/pgsql-14/lib/bitcode'/redis_fdw/ /usr/bin/install -c -m 644 redis_fdw.bc '/usr/pgsql-14/lib/bitcode'/redis_fdw/./ cd '/usr/pgsql-14/lib/bitcode' && /usr/bin/llvm-lto -thinlto -thinlto-action=thinlink -o redis_fdw.index.bc redis_fdw/redis_fdw.bc make: ディレクトリ '/home/vagrant/redis_fdw-REL_14_STABLE' から出ます
ソースコードと、それを展開したディレクトリはインストール後、削除しても構いません。
redis_fdw の基本的な使い方
redis_fdw を使って PostgreSQL から Redis 上のデータを操作してみます。
- PostgreSQL のスーパーユーザに切り替わります。
$ sudo su - postgres
- データベースを作成します。
$ createdb redis_db
ここでは、
redis_dbという名前のデータベースを作成しています。 - データベースに接続します。
$ psql redis_db psql (14.4) "help"でヘルプを表示します。 =#
ここでは、作成した
redis_dbデータベースに接続しています。終了するには\qまたはCtrl+Dを入力します。 - データベースに redis_fdw をインストールします。
=# CREATE EXTENSION redis_fdw; CREATE EXTENSION
redis_fdw はプログラムとしてはインストール済みですが、実際に使うにはデータベースごとにインストールする必要があります。
ここでは、接続中の
redis_dbデータベースにインストールしています。 - 外部サーバを作成します。
=# CREATE SERVER redis_server FOREIGN DATA WRAPPER redis_fdw OPTIONS (address '127.0.0.1', port '6379'); CREATE SERVER外部サーバとは、外部データラッパを使って外部データにアクセスするのに必要な接続情報を定義したオブジェクトです。作成時には、外部サーバ名、外部データラッパ名、オプションを指定します。
redis_fdw では、以下のオプションが指定できます。
オプション デフォルト値 説明 address127.0.0.1Redis サーバの IP アドレスまたはホスト名 port6379Redis サーバのポート番号 ここでは、
redis_serverという名前で redis_fdw の外部サーバを作成しています。オプションは例示のため、指定していますが、デフォルトでよければ、指定する必要はありません。 - 外部サーバのユーザマッピングを作成します。
=# CREATE USER MAPPING FOR PUBLIC SERVER redis_server OPTIONS (password 'secret'); CREATE USER MAPPING外部サーバのユーザマッピングとは、外部サーバとユーザの対応づけを定義したオブジェクトです。作成時には、ユーザ名、外部サーバ名、オプションを指定します。
redis_fdw では、以下のオプションが指定できます。
オプション デフォルト値 説明 password(なし) Redis サーバ接続時の認証に使うパスワード ここでは、すべてのユーザを表す
PUBLICと外部サーバredis_serverを対応づけるユーザマッピングを作成しています。passwordオプションはパスワードが未設定であれば、指定する必要はありません。 - 外部テーブルを作成します。
=# CREATE FOREIGN TABLE string_table (key text, val text) SERVER redis_server OPTIONS (database '0'); CREATE FOREIGN TABLE外部テーブルとは、外部データラッパを使って外部データにテーブルとしてアクセスできるように定義した特別なテーブルです。作成時には、テーブル定義、外部サーバ名、オプションを指定します。
redis_fdw では、以下のオプションが指定できます。
オプション デフォルト値 説明 database0Redis のデータベース番号。 0からデフォルトでは15まで指定可能tabletype(なし) Redis のデータ型。 list、hash、set、zsetが指定可能。未指定はstringtablekeyprefix(なし) 指定した接頭辞をもつキーに対象データを絞り込む tablekeyset(なし) 指定したキーをもつ集合に含まれるキーに対象データを絞り込む singleton_key(なし) 指定したキーの単一データを展開して対象データにする tabletypeオプションを指定しないと、文字列を表すstring型になりますが、値としてstringは指定できません。teblekeyprefix、tablekeyset、singleton_keyはいずれも対象データを指定するオプションで、1 つのみ指定でき、指定しないと、すべてのデータが対象になります。詳しくは redis_fdw のテーブルオプション で説明します。
ここでは、
tabletypeオプションは指定せず、テーブル定義はtext型のkeyとval列を定義しています。Redis のキーとstring型の値は PostgreSQL ではそれぞれtext型に対応します。列名は任意です。databaseオプションはデフォルトでよければ、指定する必要はありません。 - 外部テーブルのデータを操作します。データの操作を受けて Redis サーバがどう動作するかを確認するため、Redis サーバで実行されたコマンドを出力するようにしておきます。終了するには
Ctrl+Cを入力します。$ redis-cli monitor OK
PostgreSQL 側でデータを 3 件登録します。
=# INSERT INTO string_table VALUES ('key1', 'val1'), ('key2', 'val2'), ('key3', 'val3'); INSERT 0 3Redis 側で実行されたコマンドが出力されます。
1658092725.885750 [0 127.0.0.1:46042] "AUTH" "secret" 1658092725.886005 [0 127.0.0.1:46042] "SELECT" "0" 1658092725.886333 [0 127.0.0.1:46042] "EXISTS" "key1" 1658092725.886766 [0 127.0.0.1:46042] "SET" "key1" "val1" 1658092725.887016 [0 127.0.0.1:46042] "EXISTS" "key2" 1658092725.887387 [0 127.0.0.1:46042] "SET" "key2" "val2" 1658092725.887620 [0 127.0.0.1:46042] "EXISTS" "key3" 1658092725.887764 [0 127.0.0.1:46042] "SET" "key3" "val3"
PostgreSQL 側でデータを 1 件更新します。
=# UPDATE string_table SET val = 'val4' WHERE key = 'key1'; UPDATE 1
Redis 側で実行されたコマンドが出力されます。
1658092937.940434 [0 127.0.0.1:46044] "AUTH" "secret" 1658092937.940542 [0 127.0.0.1:46044] "SELECT" "0" 1658092937.940660 [0 127.0.0.1:46044] "DBSIZE" 1658092937.941136 [0 127.0.0.1:46046] "AUTH" "secret" 1658092937.941352 [0 127.0.0.1:46046] "SELECT" "0" 1658092937.941445 [0 127.0.0.1:46046] "EXISTS" "key1" 1658092937.941835 [0 127.0.0.1:46048] "AUTH" "secret" 1658092937.941976 [0 127.0.0.1:46048] "SELECT" "0" 1658092937.942118 [0 127.0.0.1:46046] "GET" "key1" 1658092937.942385 [0 127.0.0.1:46048] "SET" "key1" "val4"
PostgreSQL 側でデータを 1 件削除します。
=# DELETE FROM string_table WHERE key = 'key2'; DELETE 1
Redis 側で実行されたコマンドが出力されます。
1658092947.811658 [0 127.0.0.1:46050] "AUTH" "secret" 1658092947.811792 [0 127.0.0.1:46050] "SELECT" "0" 1658092947.811875 [0 127.0.0.1:46050] "DBSIZE" 1658092947.812375 [0 127.0.0.1:46052] "AUTH" "secret" 1658092947.812605 [0 127.0.0.1:46052] "SELECT" "0" 1658092947.812729 [0 127.0.0.1:46052] "EXISTS" "key2" 1658092947.813055 [0 127.0.0.1:46054] "AUTH" "secret" 1658092947.813197 [0 127.0.0.1:46054] "SELECT" "0" 1658092947.813342 [0 127.0.0.1:46052] "GET" "key2" 1658092947.813438 [0 127.0.0.1:46054] "DEL" "key2"
PostgreSQL 側でデータを 1 件取得します。
=# SELECT val FROM string_table WHERE key = 'key3'; val ------ val3 (1 行)
Redis 側で実行されたコマンドが出力されます。
1658092954.987736 [0 127.0.0.1:46056] "AUTH" "secret" 1658092954.987827 [0 127.0.0.1:46056] "SELECT" "0" 1658092954.987876 [0 127.0.0.1:46056] "DBSIZE" 1658092954.988113 [0 127.0.0.1:46058] "AUTH" "secret" 1658092954.988283 [0 127.0.0.1:46058] "SELECT" "0" 1658092954.988375 [0 127.0.0.1:46058] "EXISTS" "key3" 1658092954.988482 [0 127.0.0.1:46058] "GET" "key3"
redis_fdw のテーブルオプション
redis_fdw を使って外部テーブルの定義時に指定できるオプションについて説明します。
tabletype オプション
tabletype は Redis のデータ型を指定するオプションです。オプションに指定できるデータ型について説明します。
list 型
list は登録順に並べた文字列の集合を表すデータ型で、PostgreSQL では値を並べた text 型の配列に対応します。
=# CREATE FOREIGN TABLE list_table (key text, val text[])
SERVER redis_server
OPTIONS (database '1', tabletype 'list');
CREATE FOREIGN TABLE
=# INSERT INTO list_table
VALUES ('key1', '{val1,val2,val3,val1}');
INSERT 0 1
=# SELECT * FROM list_table WHERE key = 'key1';
key | val
------+-----------------------
key1 | {val1,val2,val3,val1}
(1 行)
=# SELECT key, unnest(val) FROM list_table WHERE key = 'key1';
key | unnest
------+--------
key1 | val1
key1 | val2
key1 | val3
key1 | val1
(4 行)
値 val1、val2、val3、val1 を登録し、データを取得すると、値が登録順に並び、重複する値 val1 が残っています。取得したデータは unnest 関数で行の集合に展開できます。
hash 型
hash はフィールドと値の文字列の組み合わせからなる集合を表すデータ型で、PostgreSQL ではフィールドと値を交互に並べた text 型の配列に対応します。
=# CREATE FOREIGN TABLE hash_table (key text, val text[])
SERVER redis_server
OPTIONS (database '2', tabletype 'hash');
CREATE FOREIGN TABLE
=# INSERT INTO hash_table
VALUES ('key1', '{fld1,val1,fld2,val2,fld3,val3,fld1,val4}');
INSERT 0 1
=# SELECT * FROM hash_table WHERE key = 'key1';
key | val
------+---------------------------------
key1 | {fld1,val4,fld2,val2,fld3,val3}
(1 行)
=# SELECT key, json_object(val) FROM hash_table WHERE key = 'key1';
key | json_object
------+-----------------------------------------------------
key1 | {"fld1" : "val4", "fld2" : "val2", "fld3" : "val3"}
(1 行)
=# SELECT key, (json_each_text(json_object(val))).*
FROM hash_table WHERE key = 'key1';
key | key | value
------+------+-------
key1 | fld1 | val4
key1 | fld2 | val2
key1 | fld3 | val3
(3 行)
フィールドと値の組み合わせ fld1 と val1、fld2 と val2、fld3 と val3、fld1 と val4 を登録し、データを取得すると、フィールド fld1 が重複する値 val1、val4 はあとから登録した値 val4 で上書きされています。取得したデータは json_object 関数で JSON オブジェクトに変換し、さらに json_each_text 関数でフィールドと値からなる行の集合に展開できます。
set 型
set は順序づけがなく、重複がない文字列の集合を表すデータ型で、PostgreSQL では値を並べた text 型の配列に対応します。
=# CREATE FOREIGN TABLE set_table (key text, val text[])
SERVER redis_server
OPTIONS (database '3', tabletype 'set');
CREATE FOREIGN TABLE
=# INSERT INTO set_table
VALUES ('key1', '{val1,val2,val3,val1}');
INSERT 0 1
=# SELECT * FROM set_table WHERE key = 'key1';
key | val
------+------------------
key1 | {val1,val3,val2}
(1 行)
値 val1、val2、val3、val1 を登録し、データを取得すると、重複する値 val1 が取り除かれ、1 つになっています。
zset 型
zset はスコアで順序づけした、重複がない文字列の集合を表すデータ型で、PostgreSQL では値を並べた text 型の配列に対応します。
zset 型の使い方は基本的に set 型と同じです。スコアは登録順に 0、1、2、… が割り当てられます。スコアを PostgreSQL で扱うには、singleton_key オプション を指定する必要があります。
tablekeyprefix オプション
tablekeyprefix は指定した接頭辞をもつキーに対象データを絞り込むオプションで、1 つのデータベース内に異なる種類のデータをもたせ、別テーブルとしてアクセスするのに役立ちます。

=# CREATE FOREIGN TABLE keyprefix_table (key text, val text)
SERVER redis_server
OPTIONS (database '4', tablekeyprefix 'keyprefix_table:');
CREATE FOREIGN TABLE
=# INSERT INTO keyprefix_table VALUES ('keyprefix_table:key1', 'val1');
INSERT 0 1
=# INSERT INTO keyprefix_table VALUES ('keyprefix_table:key2', 'val2');
INSERT 0 1
=# INSERT INTO keyprefix_table VALUES ('key3', 'val3');
ERROR: key 'key3' does not match table key prefix 'keyprefix_table:'
=# SELECT * FROM keyprefix_table;
key | val
----------------------+------
keyprefix_table:key2 | val2
keyprefix_table:key1 | val1
(2 行)
=# \! redis-cli -n 4 SET key3 val3
OK
=# \! redis-cli -n 4 KEYS \*
1) "keyprefix_table:key2"
2) "key3"
3) "keyprefix_table:key1"
=# SELECT * FROM keyprefix_table;
key | val
----------------------+------
keyprefix_table:key2 | val2
keyprefix_table:key1 | val1
(2 行)
tablekeyprefix オプションを指定すると、指定した接頭辞 keyprefix_table: をもつキー keyprefix_table:key1、keyprefix_table:key2 のデータしか登録できず、接頭辞をもたないキー key3 の登録はエラーになります。\! は PostgreSQL 外のコマンドを実行するコマンドで、Redis 上のデータを直接操作し、接頭辞をもたないキー key3 を登録し、データを取得すると、接頭辞をもたないキー key3 は結果に現れません。
大量のキーをもつデータベースでは、tablekeyprefix オプションではキーの検索に時間がかかるため、tablekeyset オプションでキーを集合に含まれるものに限ったほうがよいでしょう。
tablekeyset オプション
tablekeyset は指定したキーをもつ集合に含まれるキーに対象データを絞り込むオプションで、tablekeyprefix オプションと同じく、1 つのデータベース内で異なる種類のデータを扱うのに使います。

=# CREATE FOREIGN TABLE keyset_table (key text, val text)
SERVER redis_server
OPTIONS (database '5', tablekeyset 'keyset_table_keys');
CREATE FOREIGN TABLE
=# INSERT INTO keyset_table
VALUES ('key1', 'val1'), ('key2', 'val2'), ('key3', 'val3');
INSERT 0 3
=# SELECT * FROM keyset_table;
key | val
------+------
key3 | val3
key2 | val2
key1 | val1
(3 行)
=# \! redis-cli -n 5 SREM keyset_table_keys key2
(integer) 1
=# \! redis-cli -n 5 SMEMBERS keyset_table_keys
1) "key3"
2) "key1"
=# SELECT * FROM keyset_table;
key | val
------+------
key3 | val3
key1 | val1
(2 行)
tablekeyset オプションを指定すると、指定したキー keyset_table_keys をもつ集合に登録したキー key1、key2、key3 が自動的に登録され、取得されるデータは集合に含まれるキーに限られます。Redis 上のデータを直接操作し、キー key2 を削除し、データを取得すると、削除したキー key2 は結果に現れなくなります。
singleton_key オプション
singleton_key は指定したキーの単一データを展開して対象データにするオプションで、tableytpe オプション指定なしの string 型は 1 行 1 列、指定ありの list または set 型は行の集合、hash 型はフィールドと値からなる行の集合、zset 型は値とスコアからなる行の集合に展開されます。

=# CREATE FOREIGN TABLE singleton_table (val text, sc numeric)
SERVER redis_server
OPTIONS (database '6', tabletype 'zset', singleton_key 'singleton_table');
CREATE FOREIGN TABLE
=# INSERT INTO singleton_table
VALUES ('val1', 10), ('val2', 20), ('val3', 30);
INSERT 0 3
=# SELECT * FROM singleton_table;
val | sc
------+----
val1 | 10
val2 | 20
val3 | 30
(3 行)
=# UPDATE singleton_table SET sc = 40 WHERE val = 'val1';
UPDATE 1
=# SELECT * FROM singleton_table;
val | sc
------+----
val2 | 20
val3 | 30
val1 | 40
(3 行)
singleton_key オプションと併せて tabletype オプションに zset 型を指定すると、PostgreSQL でスコアを扱えるようになります。スコアは PostgreSQL では numeric 型に対応します。ORDER BY 句で並び順を指定しなければ、データはスコアの昇順に取得されます。値 val1 のスコアを 10 から 40 に更新すると、並び順が更新したスコア順に変わり、値 val1 は最後に来るようになります。
おわりに
この記事では、Redis 用外部データラッパ redis_fdw の概要、インストール、基本的な使い方、テーブルオプションについて説明しました。redis_fdw を使うことで、高速なデータの読み書きができる Redis と、SQL で複雑なデータの操作ができる PostgreSQL の特長を互いに活かし、さらに利用の幅が広がることでしょう。
SRA OSS では、PostgreSQL や Redis、redis_fdw のサポートをはじめとして、オープンソースに関する様々なサービスを提供しています。SRA OSS のサービスに興味がありましたら、お気軽に こちら からお問い合わせください。
- PostgreSQL Global Development Group (PGDG) が運営する PostgreSQL 関連パッケージの Yum リポジトリ
- Fedora Project が運営するエンタープライズ Linux 向け追加パッケージ (Extra Packages for Enterprise Linux; EPEL) の Yum リポジトリ