Skip to content

Snowflake SQL 정확도 평가 방법

seyoung4503 edited this page Apr 28, 2025 · 1 revision

이 문서는 Snowflake에서 개시한 문서를 정리한 내용입니다.
Snowflake에서 Text-to-SQL 과제를 실제 비즈니스 인텔리전스(BI) 환경에서 어떻게 해결했는지에 대해 설명하고 있습니다.

자세한 정보는 아래 주소에서 확인하실 수 있습니다.
https://www.snowflake.com/en/engineering-blog/cortex-analyst-text-to-sql-accuracy-bi/

기존 벤치마크의 한계

최종 비즈니스 사용자의 관점에서 시스템의 정확성에 대한 확신을 더하기 위해 SQL 벤치마크를 사용할 수 있습니다.
그러나, 기존 벤치마크의 경우 아래 4가지 측면에서 BI 환경과 다릅니다.

  • Question Complexity : 기존 벤치마크에 사용되는 질문이 실제 산업 환경의 복잡도나, 특성에 맞지 않습니다.
    또한 실제 BI 환경에서 묻는 질문 유형을 제대로 포착하지 않습니다.

  • Schema Complexity : 기존 벤치마크의 데이터베이스가 실제 BI 환경의 복잡하고 불분명한 스키마를 반영하지 못합니다.
    특히 시계열 테이블에 대해 과소평가되어 있습니다.

  • SQL Complexity : 기존 벤치마크는 현실 세계의 BI 작업에 필수적인 복잡한 쿼리
    (window 함수, Common Table Expressions : 공통 테이블 식, 복잡한 집계 연산)을 다루지 못합니다.

  • SQL Matching Business Context : 특정 비즈니스 정의, 지표에 맞춰 조정되어야 하는 점이 기존 벤치마크에서는 과소평가되어 있습니다.
    예를 들어, 활성 게임 유저를 정의하는 방식은 조직마다 다릅니다.

Snowflake에서 접근한 방법

복잡한 질문들을 SQL로 생성하고, 정확한 성능을 측정하기 위해 Snowflake에서는 아래 방법으로 접근합니다.

질문 난이도 구분

우선, 질문 난이도를 필터링, 집계, 추세 순서로 나누고 있습니다.

  • Level 1 : 필터링
  • Level 2 : 집계
  • Level 3 : 추세

💬 Lang2SQL 프로젝트에 참고할 점
저희도 Lang2SQL 프로젝트를 구현할 때 난이도 별로 질문을 나누고, Agentic 하게 접근할 수 있을 것 같습니다.



스키마(테이블 형태) 현실적 형태 반영

  • 좋지 않은 예시)

    날짜 메트릭 이름 메트릭 값
    2024/01/01 매출 1,000,000
    2024/01/01 비용 500,000
    2024/01/01 수익 500,000

    해당 테이블은 분석할 때 지표별로 일일이 필터링/피봇 해야 하기에 SQL이 복잡해질 우려가 있습니다.


  • 좋은 예시 : 현실적 형태 반영)

    날짜 매출 비용 수익
    2024/01/01 1,000,000 500,000 500,000
    2024/01/02 1,200,000 600,000 600,000

    해당 테이블은 날짜별로 매출, 비용, 수익을 한눈에 볼 수 있는 구조입니다.
    해당 테이블로 SQL을 작성한다면 좋지 않은 예시보다 훨씬 간단하면서 직관적으로 구조를 짤 수 있습니다.



시계열 데이터 고려

시계열 데이터를 분석할 때, 이전 값과 비교를 하는 경향이 있습니다.
이때 보통 LEAD(), LAG() 같은 윈도우 함수를 사용하는데,
두 함수는 모두 시간 축의 순서에 의존하므로 데이터가 연속적이지 않은 경우 올바른 기간을 비교하지 못할 수 있습니다.

  • 좋지 않은 예시)

    날짜 매출
    2024-01-01 100
    2024-01-02 120
    2024-01-04 130
    2024-01-05 150

    전날 대비 매출이 얼마나 올랐나?라는 질문에서 1월 4일의 전날과 비교를 한다면
    틀린 비교를 하게 됩니다.

    즉, LAG는 단순히 데이터 순서를 사용하기 때문에 날짜가 끊기면 잘못된 비교를 할 수 있습니다.

그래서 Snowflake에서는 Self-Join 방법을 고수하고 있습니다.
Self-Join은 같은 테이블을 자기 자신과 조인해 기준 날짜로부터 쿼리에 대한 행을 직접 찾아 연결하는 방법입니다.


  • 좋은 예시 : Self-Join 사용)

    SELECT
        curr.date AS current_date,
        curr.sales AS current_sales,
        prev.sales AS previous_sales,
        curr.sales - prev.sales AS sales_diff
    FROM
        sales_data AS curr
    LEFT JOIN
        sales_data AS prev
    ON
        curr.date = prev.date + INTERVAL '1 day'

    curr은 현재 날짜, prev는 하루 전 행을 찾아 직접 연결합니다.



정의된 지표/필터를 신뢰성 있게 적용하기

회사마다 정의된 용어가 다를 수 있습니다.
예를 들어, 북미라는 용어는 회사에 따라 미국 하나만을 의미할 수 있고,
북아메리카(미국, 캐나다, 멕시코)를 모두 의미할 수 있습니다.

그래서 회사마다 정의된 지표로 변환해서 SQL을 작성합니다.

ex) "2024년 북미 지역 총 매출은 얼마야?"

SELECT sum(revenue)
FROM daily_revenue_by_region
WHERE region in ("United States", "Canada", "Mexico")
AND year(dt) = '2024'


Literal retrieval

또한 사용자가 쿼리할 때 특정값(리터럴)을 정확히 작성해야 할 때가 있습니다.
Snowflake에서는 Cortex Search라는 검색 기능을 만들어 의미 기반으로 정확한
리터럴 값을 매칭할 수 있게 합니다.



평가 방법론

하나의 질문에 여러 정답이 있을 수 있음

Text-to-SQL에는 정답이 무조건적으로 한 가지만 있는 것이 아니라 하나의 질문에 여러 정답이 있을 수 있습니다.
그렇기에, 생성된 쿼리가 단순히 정답 SQL과 얼마나 일치하는지 비교하는 방법은
유효하지 않을 수 있습니다.

때문에 Snowflake에서는 아래 방법을 통해 문제를 해결합니다.

단계 설명
① 다양한 쿼리 생성 여러 모델(GPT-4o, 다른 LLM들 등)로 같은 질문을 돌려서 다양한 SQL 후보를 모음
② 인간 골드 선정 그 중에서 사람이 직접 제대로 된 SQL만 골라 "정답 쿼리 세트(gold set)"로 등록
③ 유연한 평가 생성된 SQL이 "gold set 중 하나"랑만 맞으면 OK, 그리고 완벽한 매칭 대신 열 이름 매칭(Precision/Recall) 기준으로 평가

💬 Lang2SQL 프로젝트에 참고할 점

  1. 다양한 refined 된 쿼리, 혹은 SQL 쿼리를 생성하고,
  2. 사람 피드벡을 받는 방식으로 구현할 수 있을 것 같습니다.
  3. 생성된 이전 쿼리를 참고할 수 있다면, 성공적으로 평가된 쿼리들과
    열 기반으로 정답 SQL과 얼마나 일치하는 지 확인할 수 있을 것 같습니다.
    또한, Computation cost, latancy등을 같이 비교할 수도 있을 것 같습니다.