Mais conteúdo relacionado Semelhante a Osc shimane-2016-do-postgres-dream-of-graph-database (20) Mais de Toshi Harada (20) Osc shimane-2016-do-postgres-dream-of-graph-database22. 22
Decoding Function
例えば以下のような DML を発行する
BEGIN;
DROP TABLE IF EXISTS node;
CREATE TABLE node
(id int primary key, name text, age int, gender text, location text);
COMMIT;
INSERT INTO node VALUES
(1, 'Akagi',17,'Famale','Tokyo'),
(2, 'Yamato',28,'Male','Tokyo'),
(3, 'Musashi',27,'Male','Yokohama'),
(4, 'Nagato',22,'Male','Kawasaki');
BEGIN;
UPDATE node SET age = age + 1 WHERE id IN (1,2);
DELETE FROM node WHERE id IN (3,4);
SELECT * FROM node;
COMMIT;
23. 23
Decoding Function
論理スロットから SQL 関数経由で更新ログを取得できる
logideco=# SELECT data FROM pg_logical_slot_get_changes('regression_slot', NULL,
NULL);
BEGIN 1959
COMMIT 1959
BEGIN 1960
table public.node: INSERT: id[integer]:1 name[text]:'Akagi' age[integer]:17
gender[text]:'Famale' location[text]:'Tokyo'
table public.node: INSERT: id[integer]:2 name[text]:'Yamato' age[integer]:28
gender[text]:'Male' location[text]:'Tokyo'
table public.node: INSERT: id[integer]:3 name[text]:'Musashi' age[integer]:27
gender[text]:'Male' location[text]:'Yokohama'
table public.node: INSERT: id[integer]:4 name[text]:'Nagato' age[integer]:22
gender[text]:'Male' location[text]:'Kawasaki'
COMMIT 1960
BEGIN 1961
table public.node: UPDATE: id[integer]:1 name[text]:'Akagi' age[integer]:18
gender[text]:'Famale' location[text]:'Tokyo'
table public.node: UPDATE: id[integer]:2 name[text]:'Yamato' age[integer]:29
gender[text]:'Male' location[text]:'Tokyo'
table public.node: DELETE: id[integer]:3
table public.node: DELETE: id[integer]:4
COMMIT 1961
test_decoding は
DDL は未対応です。
27. 27
Decoding Function
探したら、やっぱりありましたw
「 PostgreSQL の Logical Decoding 機能についての紹介」
http://qiita.com/bwtakacy/items/d8461518a1770524e0d6
まとめを書いたのは
@bwtakacy さん
pg_rman や pg_bulkload の
メンテナやってる人です。
Deconding Function Plug-in wal2json
https://github.com/eulerto/wal2json
名前のとおり WAL を JSON 形式にデコードしてくれる。
せっかくなので、今回はこれを使ってみる。
28. 28
Decoding Function
json2wal の使用例
例えば以下のような DML を発行する
neo4j=# BEGIN;
BEGIN
neo4j=# INSERT INTO node_person VALUES
('2005','Shinano','Famale','Kawasaki','22');
INSERT 0 1
neo4j=# INSERT INTO rel_person_person VALUES
('10028','2005','love','1001');
INSERT 0 1
neo4j=# UPDATE node_person SET location = 'Yokohama' WHERE uid = '2005';
UPDATE 1
neo4j=# DELETE FROM rel_person_person WHERE rid = '10028';
DELETE 1
neo4j=# DELETE FROM node_person WHERE uid = '2005';
DELETE 1
neo4j=# COMMIT;
COMMIT
29. 29
Decoding Function
json2wal の使用例
レプリケーションスロットから、取得したデコード結果
トランザクション全体で 1 つの JSON 文書になっている
neo4j=# SELECT data FROM pg_logical_slot_get_changes('neo4j', NULL, NULL);
{"xid":1976,"change":[
{"kind":"insert","schema":"public","table":"node_person","columnnames":
["uid","name","gender","location","age"],"columntypes":
["text","text","text","text","text"],"columnvalues":
["2005","Shinano","Famale","Kawasaki","22"]}
,{"kind":"insert","schema":"public","table":"rel_person_person","columnnames":
["rid","f_uid","type","t_uid"],"columntypes":
["text","text","text","text"],"columnvalues":["10028","2005","love","1001"]}
,{"kind":"update","schema":"public","table":"node_person","columnnames":
["uid","name","gender","location","age"],"columntypes":
["text","text","text","text","text"],"columnvalues":
["2005","Shinano","Famale","Yokohama","22"],"oldkeys":{"keynames":["uid"],"keytypes":
["text"],"keyvalues":["2005"]}}
,{"kind":"delete","schema":"public","table":"rel_person_person","oldkeys":{"keynames":
["rid"],"keytypes":["text"],"keyvalues":["10028"]}}
,{"kind":"delete","schema":"public","table":"node_person","oldkeys":{"keynames":
["uid"],"keytypes":["text"],"keyvalues":["2005"]}}
]}
赤字が 1 つの DML によるログ情報
33. 33
Logideco4neo4j
レプリケーションスロットから
デコードされた WAL を
読み込む SQL 関数を発行する
http://www.postgresql.jp/document/9.5/html/functions-admin.html#functions-replication
関数名 説明
pg_create_logical_replication_slot(slot
_name name, plugin name)
論理レプリケーションスロットを生成
pg_logical_slot_get_changes(slot_nam
e name, upto_lsn pg_lsn,
upto_nchanges int, VARIADIC options
text[])
論理レプリケーションスロットから変更内
容を読み取る。
35. 35
Logideco4neo4j
ノード挿入の Cypher Query への変換例
INSERT INTO public.person
(nid, name, gender, location, age)
VALUES ('10001',' ぬこ ','Male','Yokohama','48')
{"kind":"insert","schema":"public","table":"person",
"columnnames":["nid","name","gender","location","age"],
"columntypes":["text","text","text","text","text"],
"columnvalues":["10001"," ぬこ ","Male","Yokohama","48"]}
CREATE (n:person { nid:"10001",name:" ぬこ ",gender:"Male",
location:"Yokohama",age:"48" })
{"query":"CREATE (n:person { nid:"10001",name:" ぬこ ",
gender:"Male",location:"Yokohama",age:"48" }) "}
SQL
論理ログ
Cypher
REST API
更新も削除も同様に REST API に変換
36. 36
Logideco4neo4j
関連挿入の Cypher Query への変換例
INSERT INTO relationship VALUES
('100001', 'employ', 'company', '1001', 'person', '10001');
{"kind":"insert","schema":"public","table":"relationship",
"columnnames":["rid","type","f_label","f_uid","t_label","t_uid"],
"columntypes":["text","text","text","text","text","text"],
"columnvalues":["100001","employ","company","1001","person","10001"]}
MATCH (f:company {nid:"1001"}),(t:person {nid:"10001"})
MERGE (f)-[e:employ {rid:"100001"}]->(t)
query={"query":"MATCH (f:company {nid:"1001"}),
(t:person {nid:"10001"})
MERGE (f)-[e:employ {rid:"100001"}]->(t)"}
SQL
論理ログ
Cypher
REST API
更新も削除も同様に REST API に変換
44. 44
Neo4j Server
Logideco4neo4j
PostgreSQL
Cypher Query
WAL
(wal_level=logical) Logical
Replication
Slot
Execute Cypher Query on REST
Convert Cypher Query
olumn1 column2 column3
・・・ ・・・ ・・・
・・・・ ・・・・ ・・・
Get Replication Slot Data
Decoding Function
Convert JSON
Neo4j Foriegn Data Wrapper
Defined Cypher Query
Execute Cypher Query on REST
Generate PostgreSQL Record
PostgreSQL
Record
JSON
Result
Provide Cypher Result View
SQL
Cypher
Query
スロット定義
47. 47
neo4j_fdw
外部データラッパを登録
外部サーバと外部テーブルを定義
CREATE EXTENSION neo4j_fdw;
CREATE SERVER foo
FOREIGN DATA WRAPPER neo4j_fdw
OPTIONS (url 'http://localhost:7474/db/data/cypher');
CREATE FOREIGN TABLE persons (
uid text, name text, gender text, age text, company text
)
SERVER foo
OPTIONS (query '{"query":"MATCH (c:company)-[e:employ]->(p:person)
RETURN p.nid, p.name, p.gender, p.age, c.name"}');
あとは persons テーブルに SELECT 文を発行すれば OK!
58. 58
汎用的に SQL DML から
Neo4j の Cypher Query へ
変換する仕組みを考えないと
いけないのが面倒…
面倒なので放置中…
(だからロジデコ使った)