DuckDB in Action · Manning, 2024 · 제1장 정독
1 AN INTRODUCTION TO DUCKDB
원서 1–11쪽

빅데이터의 시대에 단일 노드 데이터베이스가 되돌아온 사연

지난 십 년간 데이터 업계가 배운 상식은 하나였다. 데이터가 커지면 기계를 늘려라. 그런데 이 책은 첫 문장부터 그 상식을 거스른다고 선언한다. 한 대의 컴퓨터, 프로세스 안에 들어앉은 작은 분석 엔진 하나로 수백 기가바이트를 처리한다는 것이다. 제1장은 그 주장의 배경과 근거, 그리고 이 오리가 앉을 자리와 앉지 말아야 할 자리를 차례로 짚는다.

저자
Mark Needham · Michael Hunger · Michael Simons
1장이 다루는 것
DuckDB의 등장 배경, 기능, 데이터 파이프라인에서의 위치
절 구성
1.1 – 1.7 (하위 절 1.7.1 – 1.7.4) 및 요약
도판
5점 · 〈도판 1.1〉 – 〈도판 1.5〉
CSV · JSON Parquet · Arrow MySQL · SQLite Postgres DataFrame · S3 DATA SOURCES DuckDB IN-PROCESS · VECTORIZED SELECT year, avg(a.value) FROM read_csv(...) AS a JOIN sales AS b ON a.region = b.region GROUP BY ALL pandas · Polars 프레임 CSV · Parquet · Excel 차트 · 대시보드 · API OUTPUT
← 좌우로 밀어 보기 →
〈도판 1.1〉생태계 속의 DuckDB. 원천을 옮기지 않고 제자리에서 읽어 들이고, 결과는 다시 프레임·파일·차트·API로 흘려보낸다.

저자들은 이 책의 성격을 미리 못 박는다. 참고서가 아니다. 문서를 찢어 옮긴 사전이 아니라, 자기들이 DuckDB를 쓰면서 느낀 즐거움을 그대로 옮기려는 실습서다. 그래서 서술은 짧고 빠르며, 예제 코드가 지천으로 깔린다. 책을 덮을 무렵이면 여러 형식의 표 형태 데이터를 DuckDB로 분석할 수 있고, 데이터 변환·정제·변형에 쓸 연장 하나를 새로 얻게 되고, 성능이 나오지 않는 자리에서 pandas 데이터프레임을 대신할 수단을 갖게 되고, Streamlit과 DuckDB로 간단한 데이터 분석 애플리케이션을 지어 올릴 수 있게 된다는 것이 저자들의 약속이다.

제1장은 그 약속의 밑그림이다. 왜 빅데이터의 시대에 굳이 단일 노드 인메모리 데이터베이스가 나타났는가, 그것으로 무엇을 할 수 있는가, 그리고 내 데이터 파이프라인의 어느 지점에 그것을 앉힐 것인가. 세 가지 물음에 답하는 것으로 장 전체가 짜여 있다.

우리는 지난 십 년간 빅데이터 시스템에 대해 배운 거의 모든 것에 역행하는 듯한 기술을 다룬다. 제1장 도입부의 취지
1.1

DuckDB란 무엇인가What is DuckDB?

DuckDB는 현대적인 임베디드 분석 데이터베이스다. 내 기계 위에서 돌면서, 서로 다른 원천에 흩어져 있는 기가바이트 단위의 데이터를 효율적으로 처리하고 질의한다. 여기서 임베디드라는 말의 뜻이 중요하다. 임베디드 데이터베이스는 애플리케이션이나 노트북 같은 다른 프로세스 안에서 함께 돈다. 네트워크를 통해 접속하는 대상이 아니다. 서버를 세우고 포트를 열고 접속 문자열을 관리하는 일련의 의례가 애초에 없다.

태생을 보면 이 물건의 성격이 더 잘 읽힌다. DuckDB는 2018년 마르크 라스벨트(Mark Raasveldt)와 하네스 뮐라이젠(Hannes Mühleisen)이 만들었다. 두 사람은 당시 네덜란드 국립 수학·컴퓨터과학 연구소인 CWI(Centrum Wiskunde & Informatica)의 데이터베이스 시스템 연구자였다. 즉 이것은 실리콘밸리 스타트업의 제품 기획서에서 나온 것이 아니라, 데이터베이스 연구실의 문제의식에서 자라난 물건이다.

세 개의 조직, 하나의 프로젝트

창업자들과 CWI는 DuckDB를 더 밀고 나가기 위해 DuckDB Labs를 분사시켰다. 이 회사의 엔지니어링 조직은 DuckDB를 더 빠르게, 더 쓰기 편하게, 더 잘 통합되게 만드는 일에 집중한다.

한편 비영리 DuckDB Foundation이 프로젝트를 관장한다. 지적재산권을 지키고, MIT 라이선스 아래 오픈소스 프로젝트의 지속성을 보장하는 것이 재단의 일이다. 재단의 운영과 DuckDB의 개발은 상용 회원사들의 지원으로 이루어지며, 협회 회원은 개발 로드맵에 의견을 낼 수 있다. 오픈소스의 수명을 걱정하는 조직이라면 이 지배구조를 한 번 들여다볼 만하다.

DuckDB가 로컬 처리에 집중하는 사이, 또 하나의 스타트업 MotherDuck은 DuckDB를 분산·셀프서비스 분석 시스템으로 확장하려 한다. 클라우드와 엣지에서 데이터를 처리하고, DuckDB에 협업과 공유 기능을 얹고, 온갖 클라우드 스토리지의 데이터를 다룰 수 있게 하는 것이 목표다.

생태계는 꽤 넓다. 많은 사람과 조직이 통합 도구와 범용 애플리케이션을 만들어 붙이고 있다. 다행히 공동체의 인심이 후하고 친절해서, DiscordGitHub에서 사람들을 만날 수 있다. 문서는 웬만한 질문에 답할 만큼 충실하고 상세하다.

무엇을 읽을 수 있는가

DuckDB는 로컬 파일이든 원격 파일이든—클라우드 버킷이나 URL에 있는 것이든—CSV, JSON, Parquet, Apache Arrow 같은 여러 형식으로 읽고 조인한다. MySQL, SQLite, Postgres 같은 데이터베이스도 상대한다. 파이썬 스크립트나 주피터 노트북 안의 pandas·Polars 데이터프레임에 직접 질의를 던지는 것까지 가능하다. 〈도판 1.1〉이 그 쓰임새를 개념적으로 보여준다.

pandas나 Polars 같은 데이터프레임 라이브러리와 DuckDB의 차이는 여기서 갈린다. DuckDB는 진짜 분석 데이터베이스다. 더 효율적인 데이터 처리 기제를 구현해 대량의 데이터를 초 단위로 처리한다. 자체 SQL 방언 덕에 복잡한 질의도 더 간결하게 표현되고, 그 표현력이 여러 연산을 하나의 질의 안에 몰아넣게 해준다. 여러 번 실행할 일을 한 번으로 줄이는 것, 그것이 곧 비용의 절감이다.

효율적인 처리와 메모리 관리의 근거는 코어 데이터베이스 엔진의 구조에 있다. 질의가 어떤 경로를 지나는지는 〈도판 1.2〉가 보여준다.

파서 PARSER 플래너 PLANNER 옵티마이저 OPTIMIZER 물리 플래너 SQL 구문 트리 미최적화 논리 계획 최적화된 논리 계획 물리 계획 STATEMENT → PHYSICAL PLAN
← 좌우로 밀어 보기 →
〈도판 1.2〉DuckDB의 질의 처리 파이프라인 개관. 여느 데이터베이스와 다르지 않은 정공법이다.

도판이 말해주는 바는 뜻밖에도 평범하다. DuckDB는 다른 데이터베이스와 똑같은 방식으로 질의를 처리한다. SQL 파서, 질의 실행 플래너, 질의 런타임이 차례로 놓인다. 비범한 것은 그다음이다. 질의 엔진이 벡터화(vectorized)되어 있다. 데이터를 한 행씩 훑는 대신 청크 단위로 묶어 병렬 처리하고, 그래서 현대적인 멀티코어 CPU 구조의 이점을 온전히 받아먹는다. 여기에 새 기능을 얹는 확장(extension) 체계와 사용자 정의 함수가 있고, CLI와 API부터 다른 시스템—데이터 처리 라이브러리 같은 것—에 대한 저수준 통합까지 다양한 사용자 인터페이스가 준비되어 있다.

1.2

왜 관심을 가져야 하는가Why should you care about DuckDB?

저자들의 답은 감정적이다. DuckDB는 데이터 분석을 다시 빠르고 즐거운 일로 만든다. 고작 수백 기가바이트를 처리하겠다고 커다란 Apache Spark 클러스터를 세우거나 클라우드 데이터 웨어하우스를 돌릴 필요가 없다. 여러 원천의 데이터에 직접 접근해서, 데이터가 놓인 자리에서 처리한다. 데이터를 선 위로 실어 옮기지 않는다는 이 한 가지가 작업을 더 빠르고 단순하고 값싸게 만든다. 시간만 아끼는 것이 아니다. 돈이 아껴지고, 무엇보다 짜증이 줄어든다.

S3 로그 한 뭉치의 청구서

저자들이 든 실례가 이 대목의 백미다. 최근 S3에 놓인 AWS 접근 로그 파일을 처리할 일이 있었다. 통상의 방법대로라면 압축된 JSON 파일을 상대로 AWS Athena의 SQL 질의를 돌린다. 그런데 이게 비싸진다. 비용의 큰 몫이 분석 서비스가 스캔한 데이터의 양에 따라 붙기 때문이다. 지금은 대신 EC2 VM에 DuckDB를 올려두고 데이터 곁에서 파일을 질의한다. 처리한 데이터 용량이 아니라 VM 값만 내면 되므로 비용은 몇 분의 일로 떨어진다. 아키텍처의 우아함이 아니라 청구서가 이 기술의 명분이 되는 셈이다.

표준을 넘어선 SQL 방언

DuckDB로는 수많은 실험을 돌려 아이디어와 가설을 빠르게, 그것도 로컬에서 검증할 수 있다. 도구는 SQL 하나뿐이다. ANSI SQL 표준을 지원하는 데서 멈추지 않고, DuckDB의 방언은 다음과 같은 혁신으로 표준을 확장한다.

  • SELECT * EXCLUDE() / SELECT * REPLACE()SELECT * 질의를 단순하게 만든다. 컬럼 하나를 빼거나 갈아 끼우려고 전체 목록을 다시 적을 필요가 없다.
  • ORDER BY ALL / GROUP BY ALL — 모든 컬럼을 기준으로 정렬하고 묶는다. GROUP BY ALL 한 줄이 필드 이름을 일일이 타이핑하는 노동을 없앤다.
  • PIVOT / UNPIVOT — 행과 열을 서로 전치한다.
  • STRUCT 데이터 타입과 관련 함수 — 복잡한 중첩 데이터를 다루기 쉽게 만든다.

저자들이 DuckDB에 흥분하는 이유는 결국 하나다. 데이터 파이프라인과 데이터 준비 작업이 단순해지면, 그만큼의 시간이 실제 분석과 탐색과 실험으로 되돌아온다.

책이 설득하려는 여섯 가지

저자들은 이 책을 통해 DuckDB에 관해 다음을 납득시키겠다고 적어놓았다. 문장의 결이 노골적으로 도발적인데, 그 솔직함이 오히려 미덥다.

  • 분석 워크로드에서는 SQLite보다 빠르다.
  • Spark 클러스터보다 세우기 쉽다.
  • pandas보다 자원 요구량이 적다.
  • Polars처럼 희한한 Rust 오류를 뱉지 않는다.
  • PostgreSQL, Redshift 등 여느 관계형 데이터베이스보다 설치와 사용이 쉽다.
  • 데이터 변환에 있어 Talend보다 빠르고 강력하다.
1.3 — 1.4

쓸 자리와 쓰지 말 자리When should you use DuckDB? / When should you not?

기술을 소개하는 책이 자기가 파는 물건의 한계를 두 절에 걸쳐 못 박아두는 일은 흔치 않다. 이 장의 가장 정직한 대목이 여기다. 요건을 먼저 정리하면 이렇다. SQL로 표현할 수 있고, 구조화된 데이터—표 또는 문서—를 대상으로 하고, 데이터가 이미 확보되어 있고(스트리밍이 아니고), 용량이 수백 기가바이트를 넘지 않는 모든 분석 작업에 DuckDB를 쓸 수 있다. 컬럼 기반 엔진이라 컬럼이 많은 넓은 테이블과 행이 많은 큰 테이블을 모두 잘 감당하며, 앞서 열거한 여러 형식을 처리하고 확장을 통해 다른 시스템과 통합된다.

여기서 딸려 나오는 미덕이 하나 더 있다. 데이터가 내 시스템을 떠나지 않는다는 점이다(로컬 또는 개인정보 규정을 준수하는 호스팅). 그래서 건강 정보, 홈 오토메이션 데이터, 환자 데이터, 개인 식별 정보, 재무제표 같은 민감한 데이터를 분석하는 데 특히 잘 맞는다.

DuckDB가 잘 푸는 분석 과제

  • 로그 파일을 저장된 자리에서 분석한다. 새 위치로 복사할 필요가 없다.
  • 개인의 의료 데이터를 정량화한다. 러너가 자기 심박수를 들여다보는 일 같은 것.
  • 스마트 미터 데이터로 전력 생산과 소비를 보고한다.
  • 자전거와 자동차 등 현대적 운송의 운행 데이터를 최적화한다.
  • 머신러닝 학습에 쓸 사용자 생성 데이터를 전처리하고 미리 정제한다.

DuckDB를 쓰지 말아야 할 자리

  • 분석 데이터베이스이므로 트랜잭션과 병렬 쓰기 지원이 최소한이다. 입력 데이터가 임의로 도착해 이를 처리·저장하는 애플리케이션과 API에는 쓸 수 없다.
  • 처리 용량이 대체로 컴퓨터의 주 메모리에 묶인다. 메모리 초과 처리를 디스크로 흘려보내는 기능이 있지만, 이는 처리의 마지막 일부가 메모리에 들어가지 않는 예외적 상황을 겨냥한 것이다. 대개는 수백 기가바이트가 상한이며, 그 전부가 동시에 메모리에 있어야 하는 것은 아니다. DuckDB가 필요한 것만 골라 적재하도록 최적화하기 때문이다.
  • DuckDB는 데이터 분석의 긴 꼬리를 겨냥한다. 수 테라바이트를 처리하는 복잡한 데이터 원천·도구·애플리케이션 구성의 엔터프라이즈 환경이라면 알맞은 선택이 아닐 수 있다.
  • 계속 갱신되는 실시간 데이터 스트림을 처리하지 못한다. 데이터 갱신은 새 테이블이나 큰 덩어리를 한 번에 적재하는 벌크 방식이어야 한다. 스트림에서 미니 배치를 만들어 어딘가에 저장하고 그것을 DuckDB가 질의하게 하는 배칭은 직접 구현해야 한다.

덧붙일 만한 좋은 쓰임이 하나 더 있다. 이미 pandas나 Polars 데이터프레임에 올라와 있는 데이터를 더 효율적으로 처리하는 일이다. DuckDB는 데이터프레임 표현에서 데이터를 복사하지 않고 직접 접근한다. 반대 방향도 같다. DuckDB가 만들어낸 출력과 테이블은 추가 메모리 사용이나 전송 없이 그대로 데이터프레임으로 쓸 수 있다. 이 무복사 왕래가 노트북 작업의 체감 속도를 바꿔놓는다.

1.5

활용 사례Use cases

이런 도구의 활용처는 많다. 그중 가장 흥미로운 것은 기존의 클라우드·모바일·데스크톱·명령행 애플리케이션에 통합되어 무대 뒤에서 제 일을 하는 경우다. 그렇게 되면 그것은 오늘날 SQLite가 누리는 광범위한 쓰임의 등가물이 된다. 다만 트랜잭션 데이터 저장이 아니라 분석 처리를 위한 SQLite인 것이다. 건강·운동·금융·홈 오토메이션 데이터처럼 사용자의 기기를 떠나서는 안 되는 데이터를 분석할 때, 효율적인 로컬 인프라는 요긴하다. 로컬에서 분석하고 전처리하면 스마트 미터나 센서 같은 엣지 기기에서 실어 보내야 하는 데이터의 양 자체가 줄어든다.

대용량 로그 분석

로그 파일 같은 큰 데이터셋을 빠르게 분석한다. 계산과 축약을 데이터가 저장된 자리에서 수행하므로 높은 전송 시간과 비용을 아낀다.

클라우드 분석 서비스 대체

현재 클라우드 사업자들은 BigQuery, Amazon Redshift, AWS Athena 같은 값비싼 분석 서비스를 처리 데이터 용량 기준으로 과금한다. 그 상당 부분을 DuckDB로 데이터를 처리하는 예약 클라우드 함수로 대체할 수 있다.

함수의 연쇄와 감사

중간 결과를 클라우드 스토리지에 써내며 처리 함수들을 사슬처럼 이을 수 있다. 그 중간 산출물은 감사(auditing)에도 그대로 쓰인다.

데이터 과학자의 노트북

최신 질의 엔진을 쓰므로 데이터 준비·분석·필터링·집계가 pandas나 여느 데이터프레임 라이브러리보다 효율적이다. 그것도 파이썬·R API가 있는 편안한 노트북 환경을 떠나지 않고서.

고급 분석의 대중화

더 진전된 분석 역량이 데이터 과학 사용자의 손에 들어가고, 더 큰 데이터를 더 빠르고 효율적으로 다루게 된다. 구성의 복잡도가 크게 줄어들어 데이터 운영 조직을 끌어들일 필요도 없어진다.

분산 분석

마지막으로 흥미로운 사례는 클라우드 스토리지·엣지 네트워크·로컬 기기 사이의 분산 분석이다. MotherDuck이 지금 바로 그 일을 하고 있으며, DuckDB를 클라우드와 로컬 양쪽에서 돌릴 수 있게 한다.

1.6

파이프라인의 어디에 놓이는가Where does DuckDB fit in?

이 책은 독자가 분석하거나 변환하고 싶은 데이터를 이미 갖고 있다고 가정한다. 그 데이터는 CSV, Parquet, JSON 같은 평면 파일에 있을 수도 있고, PostgreSQL이나 SQLite 같은 다른 데이터베이스 시스템에 있을 수도 있다. 책의 예제 데이터는 저자들이 깃허브 저장소에 올려두었다.

DATA SOURCES JSON Parquet CSV RDBMS 데이터 변환 DuckDB Python · R Java · JS · Go PROGRAMMING LANGUAGES 선택적 영속화
← 좌우로 밀어 보기 →
〈도판 1.3〉데이터 파이프라인 속의 DuckDB. 스쳐 지나가게 쓸 수도 있고, 테이블로 붙잡아 둘 수도 있다.

쓰임에 따라 DuckDB를 일시적으로 써서 데이터를 변환하고 걸러 다른 형식으로 통과시켜 보낼 수 있다. 그러나 대개는 데이터를 테이블로 만들어 영속화하고, 이후의 고성능 분석에 쓴다. 그 과정에서 컬럼 이름과 데이터 타입과 값을 바로잡을 수 있다. 입력이 중첩 문서라면 중첩을 풀어 평탄화해서 관계형 분석이 더 쉽고 효율적이게 만들 수 있다.

다음 단계는 어떤 SQL 기능 또는 DuckDB 기능이 그 분석과 변환에 도움이 되는지 가늠하는 일이다. 탐색적 데이터 분석(EDA)을 수행해 데이터의 분포와 범위와 관계를 빠르게 파악해 두는 것도 이때다.

데이터와 낯을 익힌 다음에야 실제 분석 과제로 넘어간다. 여기서는 관련 SQL 문을 점진적으로 쌓아 올리면서, 매 단계마다 산출된 결과의 표본이 기대와 맞는지 확인한다. 윈도 함수, 공통 테이블 표현식, 피벗 같은 고급 SQL 기능을 쓰기 전에 테이블이나 뷰를 추가로 만들어 두는 것도 이 단계다. 마지막으로 결과를 어떻게 소비할지 정한다. 다시 파일이나 데이터베이스로 만들지, 애플리케이션이나 API를 통해 사용자에게 서비스할지, 주피터 노트북이나 대시보드에서 시각화할지.

1.7

데이터 처리 흐름의 네 걸음Steps of the data processing flow

이어지는 하위 절들은 DuckDB의 구조와 기능 집합을 높은 수준에서 훑는다. 전체를 이해하고 그 됨됨이를 감상하게 하려는 것이 목적이다. 절의 순서는 실제로 DuckDB를 쓰는 순서를 따랐다. 데이터를 적재하고, 테이블을 채우고, 분석할 SQL을 쓰고, 결과를 시각화하는 순서다.

데이터 적재 테이블 구성 SQL로 분석 결과 활용 1.7.11.7.21.7.31.7.4
← 좌우로 밀어 보기 →
〈도판 1.4〉데이터 처리 흐름. 이 장의 하위 절 번호가 그대로 걸음의 순서다.

1.7.1 데이터 형식과 원천

DuckDB는 수많은 데이터 형식과 원천을 지원하며, 그 데이터를 격식 없이 들여다보고 분석하게 해준다. SQL Server 같은 다른 데이터 시스템과 달리 스키마 세부를 먼저 명시할 필요가 없다. 데이터를 읽을 때 데이터베이스가 합리적인 기본값과 데이터에 내재한 스키마 정보를 활용하며, 필요하면 그것을 덮어쓸 수 있다. 이 한 가지 태도의 차이가 첫 삽을 뜨는 데 걸리는 시간을 크게 줄인다.

NOTE

DuckDB로는 사전 데이터 엔지니어링보다 정작 필요한 데이터 처리와 분석에 더 집중할 수 있다. 실무자들이 만든 오픈소스 프로젝트이기에 사용성에 대한 강조가 강하다. 쓰기에 너무 어려운 것이 있으면 공동체의 누군가가 고칠 것을 제안하고 실제로 제출한다. 내장 기능이 미치지 못하는 곳이라면 그 요구를 채워주는 확장이 이미 있을 것이다. 지리공간 데이터나 전문 검색 같은 것이 그 예다.

CSV

대량으로, 그리고 병렬로 적재된다. 컬럼은 자동으로 매핑된다.

DataFrame

데이터프레임의 메모리를 같은 파이썬 프로세스 안에서 DuckDB가 직접 다룬다. 복사가 없다.

JSON

구조를 해체하고 평탄화해서 관계형 테이블로 바꿀 수 있다. 이런 데이터를 담는 JSON 타입도 따로 있다.

Parquet

스키마 메타데이터와 함께 질의된다. 질의의 조건절은 아래로 밀려 내려가 Parquet 저장 계층에서 평가되므로 적재되는 데이터의 양 자체가 줄어든다. 데이터 레이크에 읽고 쓰기에 이상적인 컬럼 형식이다.

Apache Arrow

컬럼 형태의 데이터를 ADBC(Arrow Database Connectivity)를 통해 읽는다. 데이터 복사도, 변환도 없다.

클라우드 버킷

S3나 GCP의 데이터에 접근하면 전송·복사 인프라가 줄고, 대용량 데이터를 값싸게 처리할 수 있다.

1.7.2 데이터 구조

DuckDB는 다양한 테이블과 뷰, 데이터 타입을 다룬다. 테이블 컬럼과 처리와 결과에 쓸 수 있는 타입은 전통적인 것—문자열(varchar), 수치(integer·float·decimal), 날짜, 타임스탬프, 인터벌, 불리언, 큰 이진 객체(BLOB)—에 그치지 않는다. 구조화된 타입이 함께 있다.

  • 열거형(enum) — 집합의 원소에 색인과 이름을 붙인 것. 저장과 처리가 효율적이다.
  • 리스트 또는 배열 — 같은 타입의 원소 여럿을 담는다. 리스트를 다루는 함수가 다양하게 준비되어 있다.
  • 맵(map) — 효율적인 키–값 쌍. 키를 붙인 데이터 지점을 보관하는 데 쓴다. JSON 처리 과정에서 쓰이며, 여러 방식으로 만들고 접근할 수 있다.
  • 구조체(struct) — 일관된 키–값 구조. 같은 키는 언제나 같은 타입의 값을 갖는다. 그 덕에 저장과 추론과 처리가 더 효율적이다.

사용자가 자기 타입과 데이터베이스 확장을 만들 수도 있고, 확장이 새 데이터 타입을 제공할 수도 있다. 다른 데이터로부터 표현식을 통해 만들어지는 가상 컬럼, 파생 컬럼도 만들 수 있다.

1.7.3 SQL을 지어 올리는 법

데이터를 분석할 때는 보통 데이터의 모양을 파악하는 데서 시작한다. 그다음 간단한 질의로 출발해 기본 구성 요소를 조합하며 점점 복잡한 질의를 만들어간다. 데이터 원천과 테이블과 뷰의 컬럼과 데이터 타입을 알아보려면 DESCRIBE를 쓴다. 그 정보로 무장한 다음에는 count(*) 질의를 전역으로, 또는 시간·위치·품목 유형처럼 흥미로운 차원으로 묶어 돌려서 데이터셋의 기본 통계와 분포를 얻는다. 그것만으로도 앞으로 이 데이터에서 무엇을 기대할 수 있는지에 대한 좋은 통찰이 생긴다.

DuckDB에는 컬럼별 통계를 한 번에 내주는 SUMMARIZE 절까지 있다.

  • count
  • min, max, avg, std — 최소·최대·평균·표준편차
  • approx_unique — 서로 다른 값의 개수 추정
  • percentiles — q25, q50, q75
  • null_percentage — 데이터 중 널의 비중

분석 질의를 쓸 때는 LIMIT을 걸거나 입력 파일 하나만 보면서 데이터의 부분집합에서 작업을 시작할 수 있다. 필요한 결과 컬럼의 윤곽을 먼저 잡는다. 이 컬럼들은 때로 변환이 필요하다. 날짜라면 strptime 같은 것을 쓴다. 그리고 그 컬럼들이 곧 묶는 기준이 된다. 그다음 필요한 만큼 집계와 필터를 적용한다.

DuckDB에는 집계 함수가 대단히 많다. min, avg, sum 같은 전통적인 것에서 histogram, bitstring_agg, list 같은 진전된 것, approx_count_distinct 같은 근사 함수까지 있다. 백분위수, 엔트로피 또는 회귀 계산, 왜도 같은 고급 집계도 마련되어 있다. 누적 합계나 이전·이후 행과의 비교에는 윈도 함수 집계를 쓴다.

-- 누적과 비교: 윈도 함수 집계
SELECT ..., sum(value) OVER (
         PARTITION BY column
         ORDER BY column2 [RANGE …]
       )
FROM ...

분석 문장에서 반복해 쓰이는 부분은 이름 붙인 공통 테이블 표현식(CTE)이나 뷰로 뽑아낼 수 있다. 계산의 일부를 서브쿼리로 옮겨 그 결과로 존재 여부를 검사하거나 중첩 데이터를 준비하는 것도 가독성에 도움이 되곤 한다. 그리고 분석 문장을 쌓아 올리는 동안 언제든 결과를 확인해서 아직 정확한지, 잘못된 길로 접어들지 않았는지 확인할 수 있다. 이 확인의 습관이 곧 통제력이다.

1.7.4 결과를 쓰거나 처리하기

문장을 다 썼고, DuckDB에서 분석 결과를 빠르게 얻었다. 그다음은 무엇인가.

일단 결과를 남겨두는 것이 유용하다. 파일이나 테이블에 저장하는 식이다. 결과로 테이블을 만드는 일은 CREATE TABLE <name> AS SELECT …로 간단히 끝난다. DuckDB는 CSV, JSON, Parquet, Excel, Apache Arrow 등 여러 형식으로 쓸 수 있고, 사용자 확장을 통해 SQLite, Postgres 등 다른 데이터베이스 형식도 지원한다. 결과 집합이 작다면 DuckDB CLI로 CSV나 JSON으로 출력해도 된다.

한 장의 그림이 천 개의 행보다 많은 것을 말해준다. 1.7.4절, 시각화를 권하는 대목

그래서 선호되는 선택은 흔히 데이터 시각화다. 내장 bar 함수로 인라인 막대 차트를 그려낼 수 있고, youplot 같은 명령행 플로팅 도구로 터미널에서 빠른 결과를 볼 수도 있다. 그러나 대개는 방대한 파이썬과 자바스크립트 생태계를 동원한다. 그 목적이라면 결과를 데이터프레임으로 바꾼 다음, 파이썬의 matplotlib와 ggplot, R의 ggplot2, 자바스크립트의 d3·nivo·observable로 온갖 차트를 렌더링한다. 〈도판 1.5〉가 그 모습이다.

LINE PIE 41% 27% 19% 13% CALENDAR HEATMAP DataFrame → matplotlib · ggplot · ggplot2 · d3 · nivo · observable
← 좌우로 밀어 보기 →
〈도판 1.5〉대시보드 또는 주피터 노트북에서의 데이터 시각화.

마지막 한 수가 남았다. DuckDB가 워낙 빠르기 때문에, 데이터에 대한 질의 결과를 웹·명령행·모바일 클라이언트가 소비할 API로 바로 서비스할 수 있다. 전통적인 클라이언트–데이터베이스 서버 구성이 정말로 필요한 경우는, 원본 데이터가 너무 커서 옮길 수 없고 결과는 그에 비해 아주 작을 때—전체 용량의 1%에도 훨씬 못 미칠 때—뿐이다. 그 밖의 경우라면 Streamlit 같은 것으로 지은 애플리케이션이나 대시보드 도구에 DuckDB를 임베드해 두고, 로컬 원시 데이터나 로컬 DuckDB 데이터베이스 위에서 돌리면 된다.

SUMMARY

제1장이 남긴 아홉 문장Summary

  1. DuckDB는 인메모리 처리에 특히 뛰어난, 새로 개발된 분석 데이터베이스다.
  2. 확장된 SQL 방언을 지원하며, 확장(extension)을 통해 새 역량을 얻는다.
  3. 로컬과 원격 원천의 여러 형식을 별도 도구 없이 그대로 읽는다.
  4. 파이썬, R, 그 밖의 언어와의 통합이 매끄럽고 효율적이다.
  5. 프로세스 내(in-process) 데이터베이스이므로 복사 없이 데이터를 효율적으로 처리한다.
  6. 전통적인 데이터 타입에 더해 리스트, 맵, 구조체, 열거형을 지원한다.
  7. 데이터 타입과 값에 대한 함수가 풍부해서 데이터 처리와 정형화가 훨씬 쉬워진다.
  8. 데이터의 모양을 먼저 익힌 뒤 SQL 질의를 한 걸음씩 쌓아 올리면 통제력을 유지할 수 있다.
  9. 질의 결과는 보고서 생성, 차트 시각화, 새 형식으로의 출력까지 여러 방식으로 쓸 수 있다.