-
Notifications
You must be signed in to change notification settings - Fork 4
Snowflake SQL 정확도 평가 방법
이 문서는 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 : 특정 비즈니스 정의, 지표에 맞춰 조정되어야 하는 점이 기존 벤치마크에서는 과소평가되어 있습니다.
예를 들어,활성 게임 유저
를 정의하는 방식은 조직마다 다릅니다.
복잡한 질문들을 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'
또한 사용자가 쿼리할 때 특정값(리터럴)을 정확히 작성해야 할 때가 있습니다.
Snowflake에서는 Cortex Search라는 검색 기능을 만들어 의미 기반으로 정확한
리터럴 값을 매칭할 수 있게 합니다.
Text-to-SQL에는 정답이 무조건적으로 한 가지만 있는 것이 아니라 하나의 질문에 여러 정답이 있을 수 있습니다.
그렇기에, 생성된 쿼리가 단순히 정답 SQL과 얼마나 일치하는지 비교하는 방법은
유효하지 않을 수 있습니다.
때문에 Snowflake에서는 아래 방법을 통해 문제를 해결합니다.
단계 | 설명 |
---|---|
① 다양한 쿼리 생성 | 여러 모델(GPT-4o, 다른 LLM들 등)로 같은 질문을 돌려서 다양한 SQL 후보를 모음 |
② 인간 골드 선정 | 그 중에서 사람이 직접 제대로 된 SQL만 골라 "정답 쿼리 세트(gold set)"로 등록 |
③ 유연한 평가 | 생성된 SQL이 "gold set 중 하나"랑만 맞으면 OK, 그리고 완벽한 매칭 대신 열 이름 매칭(Precision/Recall) 기준으로 평가 |
💬 Lang2SQL 프로젝트에 참고할 점
- 다양한 refined 된 쿼리, 혹은 SQL 쿼리를 생성하고,
- 사람 피드벡을 받는 방식으로 구현할 수 있을 것 같습니다.
- 생성된 이전 쿼리를 참고할 수 있다면, 성공적으로 평가된 쿼리들과
열 기반으로 정답 SQL과 얼마나 일치하는 지 확인할 수 있을 것 같습니다.
또한, Computation cost, latancy등을 같이 비교할 수도 있을 것 같습니다.