SQL 데이터베이스 엔진의 일반적인 작동 방식
- 모든 SQL 데이터베이스 엔진은 비슷한 방식으로 동작함
- 입력된 SQL 문을 "준비된 문장(Prepared Statement)"으로 변환
- 준비된 문장을 "실행"해서 결과를 생성
- SQLite에서 준비된 문장은 sqlite3_stmt 객체의 인스턴스로 표현됨
- 준비된 문장을 표현하는 방법은 크게 두 가지
- 바이트코드 방식: SQLite에서 사용
- 객체 트리 방식: MySQL, PostgreSQL에서 사용
바이트코드 방식의 장점
- 이해하기 쉬움
- 단순한 명령어들의 나열로 구성되어 쉽게 출력 가능
- EXPLAIN 키워드를 사용하면 SQL 문장의 바이트코드 확인 가능
- 디버깅이 용이함
- 파싱/분석 단계와 실행 단계를 명확히 구분
- 디버깅 빌드에서 PRAGMA vdbe_trace=ON 명령으로 바이트코드 실행 추적 가능
- 증분식으로 실행 가능
- 바이트코드로 작성된 SQL 문은 한 행씩 실행하고 중지했다 재개 가능
- 객체 트리 방식은 전체 트리를 한번에 실행하므로 증분 실행이 어려움
- 메모리 사용량이 적음
- 바이트코드는 AST보다 크기가 작음
- Prepared Statement는 오래 메모리에 캐싱되므로 메모리 사용량이 중요
- 실행 속도가 빠름
- 각 단계에서 결정해야 할 사항이 적어 실행이 빠름
객체 트리 방식의 장점
- 런타임에 쿼리 계획을 수정할 수 있음
- 객체 트리는 실행 중에도 수정이 용이함
- 쿼리의 진행 상황에 따라 동적으로 최적화 가능
- 병렬화하기 쉬움
- 각 처리 노드를 별도 스레드에 할당 가능
- 노드 간 데이터 전달만 동기화하면 됨
- 대용량 분석 쿼리(OLAP)를 다중 코어에서 실행할 때 유리
GN⁺의 의견
- SQLite의 주요 목표는 사물인터넷 환경에서의 트랜잭션 처리(OLTP)이므로, 바이트코드 방식이 적합해 보임. 간단하고 가벼우면서도 빠른 성능을 제공할 수 있기 때문임.
- 반면 MySQL이나 PostgreSQL은 대용량 데이터 분석에도 많이 사용되므로, 쿼리 실행 계획을 동적으로 최적화하고 병렬화할 수 있는 객체 트리 방식의 장점이 더 부각될 수 있음.
- 다만 객체 트리 방식도 디버깅이나 성능 분석이 어렵다는 단점이 있음. 또한 트리 순회 비용 등으로 인해 간단한 쿼리의 경우 오히려 바이트코드보다 느릴 가능성도 있음.
- 중요한 점은 용도와 목적에 맞는 적절한 방식을 선택하는 것. 범용 RDBMS의 경우 두 방식의 장단점을 절충한 하이브리드 방식을 사용하는 것도 고려해볼 만함.