글을 읽기 전에

이 글은 AgensGraph를 조금 사용해본 사용자를 위한 글이다.

  • Cypher query language 를 알아야 한다.
  • SQL 문에 대한 이해가 아주 조금 필요하다.

말은 거창하게 문제해결이라 타이틀을 걸었지만, 이 해결법은 임시방편용인 해결책이다. 쿼리의 속도 저하가 발생한다.

Chapter 1. RETURN TYPE ‘JSONB’

AgensGraph는 JSON Data의 properties를 JSONB type으로 관리한다. JSONB(JSON Binary) 타입의 이점은 다음과 같은데,

  • B-TREE Indexing
  • 저장공간 활용도 증진 등이 있을 것이다.

Database의 가용성을 높히기 위해 택한 것은 사실이나, 이 부분이 현재 AgensGraph를 사용함에 있어 너무 불편한 점이 많다.

  1. AgensGraph는 RETURN type이 전부 JSONB를 택하고 있다.
    • 이는 Hybrid Query라는 명목상의 기능을 사용할 때 많은 문제가 발생하고 있다. (심지어 Application 영역에서 처리할 때도 문제가 있다.)
    • 현재 github source를 컴파일해서 설치하면 1.4 버전으로 되어있다. release node에는 2.0이 있는데 이 부분은 동일하고, 1.2 버전 이하일 땐 PostgreSQL 타입을 따라가다 보니 이런 문제가 발생하지 않았다.
  2. 쿼리안에서 불필요한 명시적 캐스팅 필요

query를 짜다보면 text 타입만 처리하지 않는다. int, float, dobule, name, timestamp 등 아주 많은 데이터 타입이 존재하는데,

조건문을 사용할 때 이는 사용하는 사람에게 너무 불편함을 초래하고 있다.

AgensGraph 개발자 분들이 고생해서 언젠가는 고쳐질 것이라 생각하지만, 막상 사용하다보면 답답함이 느껴지기 마련이다.

Chapter 2. trouble

  • 다음은 하나의 예시 쿼리이다. Alt text

위에서 볼 부분만 빨간색 표시를 해뒀는데 1) 그래프 데이터 생성 2) SQL 데이터 생성 3) hybrid query 조회 4) 오류 발생

오류 내용을 확인해보면

ERROR:  operator does not exist: text = jsonb
LINE 3: WHERE t1.name = (MATCH (a:person) WHERE a.name = 'jhs' RETUR...
                      ^
HINT:  No operator matches the given name and argument type(s). You might need to add explicit type casts.

즉, where 조건에서 비교하고자 하는 대상의 타입이 맞지 않아 오류가 발생한다는 내용이다. 일반적인 SQL 문법을 알고 있는 사람이 이런 query를 보면 이해가 가지 않을 것이다. (명시적 캐스팅도 좋긴하지만, auto casting이란 단어가 괜히 있는 것이 아니다. 나같이 귀찮은 거랑 쿼리가 지저분해지는 것을 싫어하는 사람은 다음과 같은 해결책을 싫어한다.)

SELECT t1.name
FROM public.t_name t1
WHERE to_jsonb(t1.name) = (MATCH (a:person) WHERE a.name = 'jhs' RETURN a.name)
;
 name
------
 jhs
(1 row)

Alt text

이렇게만 보면 귀찮아도 명시적 캐스팅으로 가능할 것 같지 않은가? 그런데 여기선 또 데이터 처리에 있어 불편한 상황이 초래된다.

1번 그림에서도 확인할 수 있지만 Cypher query 조회 결과가 이렇다.

test=# MATCH (a)-[r]->(b)
RETURN a.name,b.name;
 name  |  name
-------+--------
 "jhs" | "khan"
(1 row)

Application(이하 A.P) 영역에서 AgensGraph(이하 A.G)안의 데이터를 불러와 처리를 할 때, JSONB 타입의 데이터는 텍스트에 “” 가 붙게 된다. 텍스트가 붙는 이유는 JSON 데이터가 텍스트 데이터를 처리할 때 쌍따옴표가 붙기 때문이다.

이 쌍따옴표가 그대로 텍스트에 포함되면서 나는 모든 A.P 영역에서 이 쌍따옴표를 없애는 작업을 해야한다. 정말 만약에 내가 AgensGraph1.3 이후 버전을 사용했다면 이런 작업을 처리하는 공통모듈을 만들었을 것이다. 그렇지만? AgensGraph 1.2에선 이런 문제가 발생하지 않았다.

즉! AgensGraph 1.2 환경에서 개발하던 사람이 DB 업그레이드를 위해 2.0으로 포팅하는 과정에서
무수히 많은 기존 A.P 소스가 오류를 발생시킬 수 있다는 것이다.
예전에 1.2랑 1.4~2.0이랑 많이 다르냐고 물어보신 분이 있었는데, 나는 포팅하다가 정말 욕이 나왔다.

결국 나는 선택을 해야한다. 1) 기능을 지원해줄 때까지 기다릴 것인지…….. 2) AP영역에서 이를 처리하는 공통모듈을 만들 것인지.. 3) 쿼리를 조금만 손보고 처리할 수 있는 A.G 내장함수를 만들 것인지

Chapter 3. temp solution

오늘은, AgensGraph 내장함수를 만들어 처리하는 방법을 소개하도록 하겠다. 방법은 간단하다.

1) plpythonu extension

create lanugage plpythonu;

2) creating plpython function

create or replace function to_string(value jsonb)
returns text as $$
return str(value.replace('\"',''))
$$ language plpythonu;

먼저, AgensGraph안에서 plpython을 사용하기 위한 language를 생성한다. (plpython에 대한 내용도 다음시간에 한 번 작성해보도록 하겠다.. 이 것도 문제가 있다.)

그리고, to_string 이라는 function을 커스터마이징 한다. argument는 jsonb 타입의 argument를 받는다. 리턴할 때 쌍따옴표를 제거해서 리턴하게 만든다.

MATCH 문을 사용해서 그래프 패턴을 조회하고 RETURN 절에 to_string function을 사용하여 리턴하게 되면 아까와 같은 오류가 발생하지 않는다.

Alt text

to_jsonb랑 to_string이랑 이러면 사용하는 의도가 비슷하지 않냐는 사람이 있을텐데 예시에서 굳이 to_jsonb를 사용한 이유는 RDB 테이블을 처리하는 과정에서의 오류를 보여주기 위함이였다.

A.P 개발하기도 바빠죽겠는데 MATCH … RETURN 문만 가지고 나는 데이터를 조회하고 싶고, 저런 번거로운 작업을 하기 싫기 때문이다.

to_string은 텍스트를 한번 더 가공하는 작업을 하므로 그냥 조회할 때보다 당연히 성능이 떨어진다.

하지만 오류가 안나는게 제일 첫 번째 목적이고, 둘 째 이슈가 속도가 되지 않을까?