체인의정석

스마트컨트렉트, 백엔드 , DB사이의 작업 처리에 대하여 (MySQL 다중 테이블 쿼리 + 백엔드 처리) 본문

개발/database

스마트컨트렉트, 백엔드 , DB사이의 작업 처리에 대하여 (MySQL 다중 테이블 쿼리 + 백엔드 처리)

체인의정석 2023. 2. 13. 18:33
728x90
반응형

컨트렉트와 개발할 때는 총 3가지의 단계가 존재한다.

 

1. DB의 SQL

2. 백엔드의 데이터 처리

3. 스마트컨트렉트의 데이터 처리

 

무언가 작업을 하거나 계산할 때 1,2,3의 처리를 우리는 모두 다 해주어야 한다.

상황에 따라 다르지만 컨트렉트에서의 처리는 최대한 줄여주고 그 다음으로 백엔드의 처리를 최대한 줄여주고 최대한의 작업을 SQL에서 작업해야 빠른 처리가 가능하다.

 

1 -> 2의 호출회수를 줄이고

2 -> 3의 호출 회수를 줄이는 것이 우선순위이다.

 

데이터베이스에서 자료를 가져오면서 복잡한 쿼리를 작성하여 정리해 두고자한다.

 

STEP 1.) 여러 테이블에서 조회를 같이 해와서 최대로 큰 블록을 가져오는 경우의 쿼리는 다음과 같이 작성한다.

 

먼저 FROM 안에 SELECT를 넣을 때는 AS A와 같이 이름을 지어주지 않으면 에러가 나게 된다.

또한 UNION ALL을 사용하면 중복 제거 없이 UNION을 사용하면 중복 제거를 한 상태로 합집합을 구할 수 있다.

group by의 경우 앞의 select에 sum , max, min 등과 같이 계산할 값만 남겨두고 하게 될 경우 해당 연산을 수행하여 선택값을 줄여주게 된다.

이렇게 모아서 선택되어 한번 필터링 된 데이터를 가져와서 그 안에서 조건을 한번 더 실행 시킬 수 있다.

다음과 같이 기본 포맷을 두고 활용하면 된다.

또한 트랜잭션의 이벤트 데이터의 경우 json_extract를 사용할 수 있는데 이는 명시만 잘 해주면 일반 변수처럼 사용하면 다 작동한다.

SELECT A.data, max(A.block_number) as max_block
FROM(
	SELECT json_extract(event_data,'$.data') as data1 FROM DBNAME.TABLENAME where 조건 group by data1
	UNION ALL
	SELECT json_extract(event_data,'$.data') as data1 FROM DBNAME.TABLENAME where 조건 group by data1
) AS A
GROUP BY A.data
ORDER BY A.data

STEP 2.) 특정 값에 대한 이벤트가 찍힌 경우에는 상황 1번의 조건에서 제외 해야 한다.

SELECT A.data, max(A.block_number) as max_block
FROM(
	SELECT json_extract(event_data,'$.data') as data1 FROM DBNAME.TABLENAME where 조건 group by data1 having 조건2
	UNION ALL
	SELECT json_extract(event_data,'$.data') as data1 FROM DBNAME.TABLENAME where 조건 group by data1 having 조건2
) AS A
GROUP BY A.data
ORDER BY A.data

최초의 필터링 이후 group by를 할 때 having을 넣어주면 추가적인 조건2를 필터링 할 수 있다.

그룹을 먼저 해서 중복값을 제거하며 계산한 결과 값에서 원하는 값만 또 뽑아내는 것이다.

 

STEP 3.) 조회하고자 하는 테이블이 서비스 상황에 따라 유동적을 변화할 수 있기 때문에 다음과 같이 반복문을 통해서 추후 수정이 필요 없도록 설계한다.

    let inlineQuery = ''
    for(i in 테이블이름배열) {
        const baseQuery = `SELECT 문`
        if(i < 테이블이름배열) inlineQuery  = inlineQuery.concat(baseQuery, ' UNION ALL ' )
        else if(i == 테이블이름배열) inlineQuery  = inlineQuery.concat(baseQuery)
    }

    let queryRepayer = 
    `SELECT A.열이름 as 별명, max(A.열이름2) as 별명2  FROM(${inlineQuery}) AS A GROUP BY A.열이름 ORDER BY A.열이름`

또는 다음과 같이 사용할 수도 있다.

    let sql_union = "";
    for(let i = 0; i < tableNames.length; i++) {
        sql_union += 
        `
        SELECT 
            '${tableNames[i]}' as table_name,
            (sum(token0_value)/POW(10,18) + sum(token1_value)/POW(10,18)) as volume
        FROM dbName.${tableNames[i]}
        WHERE block_number > ${current_blocknumber-86400} and block_number < ${current_blocknumber}`;
    
        // Add UNION ALL between SELECT queries, but not after the last one
        if(i < tableNames.length - 1) {
            sql_union += " UNION ALL ";
        }
    }

 

STEP 4.) 위의 두 값을 각각 해서 SQL로 통신을 2번하고 각 받아온 배열 값을 백엔드에서 비교 연산하여 새로운 값을 도출해 낸다.

이 경우 요즘 핫한 chat GPT의 도움을 받았다.

 

https://openai.com/blog/chatgpt/

 

ChatGPT: Optimizing Language Models for Dialogue

We’ve trained a model called ChatGPT which interacts in a conversational way. The dialogue format makes it possible for ChatGPT to answer followup questions, admit its mistakes, challenge incorrect premises, and reject inappropriate requests. ChatGPT is

openai.com

    let mergedArr = [];

    for (let i = 0; i < 결과배열1.length; i++) {
        let bObj = 결과배열1[i];
        let found = false;
        for (let j = 0; j < 결과배열2.length; j++) {
            let rObj = 결과배열2[j];
            if (bObj.address == rObj.address && bObj.max_block < rObj.max_block) {
                found = true;
                break;
            }
        }
        if (!found) {
            mergedArr.push(bObj.address);
        }
    }
    return (mergedArr);

chat GPT를 써서 하면 내가 원하는 코드와 약 80% 유사한 코드가 나온다. 따라서 코드를 이해하고 수정과 확인 작업만 거치면 된다.

위의 경우 특정 조건이 맞아서 포함을 안시키는 경우 found=true로 두고 넘어가고 만약 안찾아지는 경우 예외상황이 아니기에 그대로 push를 해버리는 값이다.

 

STEP 5.) 그외의  처리는 컨트렉트에서

그 외의 처리는 컨트렉트에서 다루었다. 도메인 자체가 디파이라서 데이터가 중요하기에 백엔드에서 최대한 작업을 줄여준 형태로 컨트렉트로 보내서 처리하는 것이 좋다.

 

물론 컨트렉트에서는 멀티콜을 사용해서 최대한 tx와 call 수를 줄여야 한다.

 

* 만약 SQL을 더 잘 다룬다면 서버의 부담이 줄어들 것이고 서버를 잘다루면 컨트렉트의 부담이 줄어들 것이다.

대규모 처리 시스템은 이런식으로 구현하지 않는다면 결국 제대로 된 서비스가 돌아가기 어렵게 된다.

728x90
반응형
Comments