アプリケーション開発ポータルサイト
ServerNote.NET
カテゴリー【RedisPostgreSQLDebian
redis_fdwでRedisのハッシュ型DBをPostgreSQL11のテーブルとして使う
POSTED BY
2023-06-20

Redis上の各種データをPostgreSQLのテーブルとしてアクセス可能になります。Redisは番号で分けてDBを複数持つことができて、切り替えは

redis-cli

select 1 # 好きなDB番号に切り替え

などとして、空間を分けることができます。これを利用して、PostgreSQLでは別テーブルとして扱えます。

1、redis_fdwのインストール

redisのC言語ライブラリがインストールされていない場合、入れます。

git clone https://github.com/redis/hiredis.git
cd hiredis/
make
sudo make install

PGXSを使うのでpostgresql-server開発ツールをインストールします。

apt search postgresql-server-dev
Sorting... Done
Full Text Search... Done
postgresql-server-dev-11/stable,stable 11.7-0+deb10u1 amd64
  development files for PostgreSQL 11 server-side programming

postgresql-server-dev-all/stable,stable 200+deb10u3 all
  extension build tool for multiple PostgreSQL versions

sudo apt install postgresql-server-dev-11

redis_fdwが対応しているPostgreSQLのバージョンを確認します。

https://github.com/pg-redis-fdw/redis_fdw/branches/stale

自分のPostgreSQLのバージョンが11系列なら、REL_11_STABLEを選択すればいいことがわかります。

psql --version
psql (PostgreSQL) 11.7 (Debian 11.7-0+deb10u1)

redis_fdwのダウンロード、コンパイル、インストール

git clone https://github.com/pg-redis-fdw/redis_fdw.git
cd redis_fdw
該当PostgreSQLバージョンにスイッチ
git checkout -b REL_11_STABLE origin/REL_11_STABLE
Branch 'REL_11_STABLE' set up to track remote branch 'REL_11_STABLE' from 'origin'.
Switched to a new branch 'REL_11_STABLE'

make USE_PGXS=1
sudo make USE_PGXS=1 install

2、PostgreSQLでの使用開始宣言とRedisでのモニター開始

スーパーユーザーでpsqlします。

CREATE EXTENSION redis_fdw;
CREATE SERVER redis_server FOREIGN DATA WRAPPER redis_fdw OPTIONS (address '127.0.0.1', port '6379');
CREATE EXTENSION hstore;
CREATE USER MAPPING FOR PUBLIC SERVER redis_server;
\dx
                            List of installed extensions
   Name    | Version |   Schema   |                   Description
-----------+---------+------------+--------------------------------------------------
 hstore    | 1.5     | public     | data type for storing sets of (key, value) pairs
 plpgsql   | 1.0     | pg_catalog | PL/pgSQL procedural language
 redis_fdw | 1.0     | public     | Foreign data wrapper for querying a Redis server
(3 rows)

Redisでは、どのようなコマンドに変換されるか見るため、MONITORを立ち上げておきましょう。

redis-cli monitor

3、HASH型テーブルを扱う(singleton_keyを使わない場合)

RedisのHASH型を扱うテーブルをPostgreSQLで宣言し、Redisで登録して、PostgreSQLで抽出してみます。

PostgreSQL

CREATE FOREIGN TABLE redisdb10 (key text, value text) SERVER redis_server OPTIONS (tabletype 'hash', database '10');

Redis

select 10

hset key1 field1 value1
hset key1 field2 value2
hset key2 field2 value2

PostgreSQL

時間計測を入れておく

\timing

SELECT * FROM redisdb10;
 key  |                 value
------+---------------------------------------
 key2 | {"field2","value2"}
 key1 | {"field1","value1","field2","value2"}
(2 rows)

Time: 1.353 ms

無事取得できましたが、こんなので1.3ミリ秒もかかっていたら使い物にならない…!

Redisモニタ(どんなコマンドが発行されているか)

"SELECT" "10"
"DBSIZE"
"SELECT" "10"
"SCAN" "0" "COUNT" "1000"
"HGETALL" "key2"
"HGETALL" "key1"

うーむ、くどい…

4、HASH型テーブルを扱う(singleton_keyを使う場合)

singleton_keyを指定してテーブル作成をすると、KEY名がそれに固定される用途になるため、出力が大きく異なってきます。

PostgreSQL

CREATE FOREIGN TABLE redisdb11 (key text, value text) SERVER redis_server OPTIONS (tabletype 'hash', singleton_key 'PG', database '11');

Redis

キーは"PG"固定になります。

select 11

hset PG field1 value1
hset PG field2 value2
hset PG field3 value3

PostgreSQL

\timing

SELECT * FROM redisdb11;
  key   | value
--------+--------
 field1 | value1
 field2 | value2
 field3 | value3
(3 rows)

Time: 1.114 ms

本来keyが入る箇所にfieldが入ってくるので、valueはfield-valueの配列にならずそのまま複数行として返ります。

Redisモニタ

"SELECT" "11"
"HLEN" "PG"
"SELECT" "11"
"HGETALL" "PG"

キーが固定なので多少早くなったような、しかしこれHASHの意味全然ないですよね…。

5、STRING型テーブルを扱う

最もスタンダードなKEY-VALUEタイプです。PostgreSQLからのINSERTも簡単にできるので、SELECT結果をINSERTで大量にRedisに流し込む用途には最適といえます。

PostgreSQL

CREATE FOREIGN TABLE redisdb12 (key text, value text) SERVER redis_server OPTIONS (database '12');

tabletypeをstringなどと指定すると何故かエラーになるので注意

Redis

select 12

set key1 value1
set key2 value2
set key3 value3

PostgreSQL

\timing

SELECT * FROM redisdb12;
 key  | value
------+--------
 key2 | value2
 key3 | value3
 key1 | value1
(3 rows)

Time: 1.524 ms

Stringなら爆速!と期待したものの、Hashより遅い。。

Redisモニタ

"SELECT" "12"
"DBSIZE"
"SELECT" "12"
"SCAN" "0" "COUNT" "1000"
"GET" "key2"
"GET" "key3"
"GET" "key1"

うーむ、くどい…

PostgreSQL

INSERT,UPDATE, SELECTの結果を受けての大量INSERTも可能。

INSERT INTO redisdb12 (key, value) VALUES ('key4','value4');
INSERT 0 1
Time: 0.872 ms
SELECT * FROM redisdb12;
 key  | value
------+--------
 key4 | value4
 key2 | value2
 key3 | value3
 key1 | value1
(4 rows)

Time: 1.403 ms

6、テーブルの削除

PostgreSQL

DROP FOREIGN TABLE redisdb12;

Redis側のデータが消える訳ではないので注意。

※本記事は当サイト管理人の個人的な備忘録です。本記事の参照又は付随ソースコード利用後にいかなる損害が発生しても当サイト及び管理人は一切責任を負いません。
※本記事内容の無断転載を禁じます。
【WEBMASTER/管理人】
自営業プログラマーです。お仕事ください!
ご連絡は以下アドレスまでお願いします★

【キーワード検索】