2017.08.30

“데이터베이스의 언어” SQL이란 무엇인가

Martin Heller | InfoWorld

오늘날 구조화 쿼리 언어(Structured Query Language)는 비록 제품들 간에 자사 고유의 확장 기능을 가지고 있기는 하지만, 관계형 데이터베이스에서 데이터를 조작하고 쿼리하는 표준 수단이다. SQL의 편의성과 보편성은 하둡(Hadoop)을 위시한 수 많은 NoSQL 또는 비관계형 데이터 저장(Non-Relational Data Stores) 기술도 SQL의 일부를 도입하거나 SQL과 유사한 쿼리 언어를 만들어 낼 정도이다.

그렇지만 SQL이 과거에도 “보편적인” 관계형 데이터베이스용 언어는 아니었다. 초기, 그러니까 1980년대에 SQL은 반대 세력이 적지 않았다. 당시에는 필자를 포함해 많은 연구원과 개발자들이 SQL의 오버헤드로 인해 업무용 데이터베이스로서는 결코 실용적이지 않다고 생각했다.

분명 잘못된 생각이었다. 하지만 아직도 많은 이들이 SQL의 모든 편의성과 접근성에도 불구하고 런타임 성능에 따라 부과되는 대가가 너무 클 때가 많다고 생각한다.



SQL이 있기 전
SQL이 있기 전에는 데이터베이스는 밀접하게 결합된 탐색형 프로그래밍 인터페이스를 가지고 있었으며, 대개의 경우 코다실(CODASYL) 데이터 모델이라 부르는 네트워크 스키마(Schema)를 중심으로 설계되었다. 코다실(CODASYL: Conference/Committee on Data Systems Languages)은 1959년부터 코볼(COBOL) 프로그래밍 언어 그리고 10년 뒤부터는 데이터베이스 언어 확장기능을 책임지던 컨소시엄이었다.

코다실 데이터베이스에 대하여 프로그래밍을 했다면, 일대다 관계를 나타내는 세트(Set)를 통해서 레코드(Record)를 탐색했을 것이다. 구식 계층형(Hierarchical) 데이터베이스는 레코드가 한 개의 세트에만 속할 수 있도록 한다. 네트워크 데이터베이스는 레코드가 여러 개의 세트에 속할 수 있게 해준다.

CS 101에 등록한 학생들을 열거하고 싶어한다고 하자. 우선 이름으로 Courses 세트에서 “CS 101”을 찾을 수 있을 것이다, 그것을 Enrollees 세트의 소유자 또는 부모(Parent)로 설정하고, Enrollees 세트의 첫 번째 멤버(ffm)를 찾으면, 그것이 Student 레코드인데, 그것을 나열하면 된다. 그 다음에는 루프에 들어간다. 다음 멤버 (fnm)을 찾아서 그것을 나열한다. fnm에 실패하면, 루프를 빠져나오면 된다.

이렇게 하는 것이 데이터베이스 프로그래머에게는 많은 쓸데없는 일처럼 보일 수도 있지만, 런타임에는 매우 효율적이었다. 캘리포니아 대학교 버클리 & 인그레스 분교의 마이클 스톤브레이커 같은 전문가들은 코다실 데이터베이스에서 이런 종류의 쿼리를 하는 것이 SQL을 사용해서 관계형 데이터베이스에 대해 동일한 쿼리를 하는 것보다 약 절반의 CPU 시간과 절반 이하의 메모리를 사용했다고 지적했다.

비교를 위해, CS 101에 등록한 모든 학생들을 되돌려주기 위한 동일한 SQL 쿼리는 아마도 다음과 같을 것이다

SELECT student.name FROM courses, enrollees, students WHERE course.name ="CS 101"

이 구문은 필자가 아래에서 설명하겠지만, 관계형 내부 조인(Inner Join) (실제로는 두 개의 조인)을 암시하고 있으며, 조인용으로 사용되는 필드 같은 몇 가지 중요한 세부사항을 빼놓고 있다.

관계형 데이터베이스와 SQL
실행 속도와 메모리를 두 배로 늘리는 것을 포기할 이유가 있는가? 포기하는 데는 두 가지 커다란 이유가 있다. 바로 개발 편이성과 이식성이다. 1908년대에 필자는 성능과 메모리 요구조건과 비교하여 둘 중 어느 한 가지도 중요하지 않다고 생각했지만, 컴퓨터 하드웨어가 개선되고 가격이 더 저렴해지면서 사람들은 실행 속도와 메모리보다는 개발 비용을 더 많이 걱정했다.

즉, 무어의 법칙이 관계형 데이터베이스를 위해 코다실 데이터베이스를 죽였다. 공교롭게도, 개발 시간은 상당히 단축되었지만, SQL 이식성은 몽상으로 판명 낫다.

관계형 모델과 SQL의 기원은 어디인가? 에드가 “테드” 코드는 1960년 대에 IBM 산호세 연구소에서 관계형 모델에 대한 이론을 고안하고 그 결과를 1970년에 발표한 컴퓨터 과학자이다. IBM은 자사의 코다실 데이터베이스인 IMS/DB의 매출을 보호하기 위한 노력의 일환으로 관계형 데이터베이스의 구현에 적극적이지 않았다. 마침내 IBM이 자사의 시스템 R 프로젝트를 시작했을 때, 개발 팀(돈 챔버린과 레이 보이스)은 테드 코드 소속이 아니었으며, 자신들의 언어인 시퀄(Sequel: Structured English Query Language: 구조화 영어 질의어)을 설계하기 위해 코드의 1971년 알파 관계형 언어 논문을 무시했다. 1979년 IBM이 자사의 제품을 출시하기도 전에, 래리 앨리슨은 (준비단계였던 IBM 시퀄 관련 사양들을 자신의 사양에 사용함으로써) 자사의 오라클 데이터베이스에 이 언어를 포함시켰다. 시퀄은 국제 상표권 침해를 회피하기 위해 곧 SQL이 되었다.

(마이클 스톤브레이커의 말을 빌자면) “SQL에 대한 칭송은 오라클과 IBM뿐아니라 고객들에게서도 들려왔다. 코다실 데이터베이스 설계자와 프로그래머를 고용하기가 쉽지 않았기 때문에, 시퀄 (그리고 SQL)이 훨씬 더 매력적으로 보였다. 1980년대 후반에는 SQL이 너무나 매력적이어서 관계형이기 위해서는 관계형 데이터베이스를 처음부터 새로 설계해야만 한다고 생각하고 있던 코드에게는 엄청나게 실망스럽게도, 많은 데이터베이스 공급업체들이 자사의 코다실 데이터베이스 위에 SQL 쿼리 처리기를 기본적으로 탑재할 정도였다.

코드가 설계한 것 같은 순수한 관계형 데이터베이스는 일차 술어 논리(First-Order Predicate Logic)와 일관되게, 관계(Relation)로 그룹화 되는 튜플(Tuple)을 기반으로 구축된다. 실제 관계형 데이터베이스는 필드, 제약 조건(Constraint), 그리고 트리거(Trigger)를 포함하고 있는 테이블을 가지고 있으며, 테이블은 외래 키(Foreign Key)를 통해서 관계가 맺어진다. 리턴 데이터를 선언하기 위해 SQL이 사용되며, SQL 쿼리 처리기(Processor)와 쿼리 최적화기(Optimizer)는 SQL 선언을 데이터베이스 엔진이 실행하는 쿼리 계획(Query Plan)으로 바꾼다.

SQL에는 데이터 수정을 위한 특수 언어인 DML(Data Manipulation Language: 데이터 조작 언어)와 함께, 스키마를 정의하는 특수 언어인 DDL(Data Definition Language: 데이터 정의 언어)이 포함되어 있다. 이 두 가지 모두 초기 코다실 사양에 뿌리를 두고 있다. SQL의 세 번째 특수 언어는 SELECT 문과 관계형 결합(Relational Join)을 통해서 쿼리를 선언한다.

SQL의 SELECT 문
SELECT 문은 쿼리 최적화기에게 어떤 데이터가 리턴되는지, 어떤 테이블을 살펴보아야 하는지, 어느 관계를 따라야 하는지, 그리고 리턴된 데이터에 어떤 순서를 부여해야 하는지를 알려준다. 쿼리 최적화기는 특정 데이터베이스가 인덱스 힌트(Index Hint)를 지원하지 않는 한, 무작위 테이블 스캔(Brute Force Table Scan)을 회피하고 좋은 쿼리 성능을 달성하기 위해 어떤 인덱스를 사용해야 할지를 스스로 알아내야만 한다.


2017.08.30

“데이터베이스의 언어” SQL이란 무엇인가

Martin Heller | InfoWorld

오늘날 구조화 쿼리 언어(Structured Query Language)는 비록 제품들 간에 자사 고유의 확장 기능을 가지고 있기는 하지만, 관계형 데이터베이스에서 데이터를 조작하고 쿼리하는 표준 수단이다. SQL의 편의성과 보편성은 하둡(Hadoop)을 위시한 수 많은 NoSQL 또는 비관계형 데이터 저장(Non-Relational Data Stores) 기술도 SQL의 일부를 도입하거나 SQL과 유사한 쿼리 언어를 만들어 낼 정도이다.

그렇지만 SQL이 과거에도 “보편적인” 관계형 데이터베이스용 언어는 아니었다. 초기, 그러니까 1980년대에 SQL은 반대 세력이 적지 않았다. 당시에는 필자를 포함해 많은 연구원과 개발자들이 SQL의 오버헤드로 인해 업무용 데이터베이스로서는 결코 실용적이지 않다고 생각했다.

분명 잘못된 생각이었다. 하지만 아직도 많은 이들이 SQL의 모든 편의성과 접근성에도 불구하고 런타임 성능에 따라 부과되는 대가가 너무 클 때가 많다고 생각한다.



SQL이 있기 전
SQL이 있기 전에는 데이터베이스는 밀접하게 결합된 탐색형 프로그래밍 인터페이스를 가지고 있었으며, 대개의 경우 코다실(CODASYL) 데이터 모델이라 부르는 네트워크 스키마(Schema)를 중심으로 설계되었다. 코다실(CODASYL: Conference/Committee on Data Systems Languages)은 1959년부터 코볼(COBOL) 프로그래밍 언어 그리고 10년 뒤부터는 데이터베이스 언어 확장기능을 책임지던 컨소시엄이었다.

코다실 데이터베이스에 대하여 프로그래밍을 했다면, 일대다 관계를 나타내는 세트(Set)를 통해서 레코드(Record)를 탐색했을 것이다. 구식 계층형(Hierarchical) 데이터베이스는 레코드가 한 개의 세트에만 속할 수 있도록 한다. 네트워크 데이터베이스는 레코드가 여러 개의 세트에 속할 수 있게 해준다.

CS 101에 등록한 학생들을 열거하고 싶어한다고 하자. 우선 이름으로 Courses 세트에서 “CS 101”을 찾을 수 있을 것이다, 그것을 Enrollees 세트의 소유자 또는 부모(Parent)로 설정하고, Enrollees 세트의 첫 번째 멤버(ffm)를 찾으면, 그것이 Student 레코드인데, 그것을 나열하면 된다. 그 다음에는 루프에 들어간다. 다음 멤버 (fnm)을 찾아서 그것을 나열한다. fnm에 실패하면, 루프를 빠져나오면 된다.

이렇게 하는 것이 데이터베이스 프로그래머에게는 많은 쓸데없는 일처럼 보일 수도 있지만, 런타임에는 매우 효율적이었다. 캘리포니아 대학교 버클리 & 인그레스 분교의 마이클 스톤브레이커 같은 전문가들은 코다실 데이터베이스에서 이런 종류의 쿼리를 하는 것이 SQL을 사용해서 관계형 데이터베이스에 대해 동일한 쿼리를 하는 것보다 약 절반의 CPU 시간과 절반 이하의 메모리를 사용했다고 지적했다.

비교를 위해, CS 101에 등록한 모든 학생들을 되돌려주기 위한 동일한 SQL 쿼리는 아마도 다음과 같을 것이다

SELECT student.name FROM courses, enrollees, students WHERE course.name ="CS 101"

이 구문은 필자가 아래에서 설명하겠지만, 관계형 내부 조인(Inner Join) (실제로는 두 개의 조인)을 암시하고 있으며, 조인용으로 사용되는 필드 같은 몇 가지 중요한 세부사항을 빼놓고 있다.

관계형 데이터베이스와 SQL
실행 속도와 메모리를 두 배로 늘리는 것을 포기할 이유가 있는가? 포기하는 데는 두 가지 커다란 이유가 있다. 바로 개발 편이성과 이식성이다. 1908년대에 필자는 성능과 메모리 요구조건과 비교하여 둘 중 어느 한 가지도 중요하지 않다고 생각했지만, 컴퓨터 하드웨어가 개선되고 가격이 더 저렴해지면서 사람들은 실행 속도와 메모리보다는 개발 비용을 더 많이 걱정했다.

즉, 무어의 법칙이 관계형 데이터베이스를 위해 코다실 데이터베이스를 죽였다. 공교롭게도, 개발 시간은 상당히 단축되었지만, SQL 이식성은 몽상으로 판명 낫다.

관계형 모델과 SQL의 기원은 어디인가? 에드가 “테드” 코드는 1960년 대에 IBM 산호세 연구소에서 관계형 모델에 대한 이론을 고안하고 그 결과를 1970년에 발표한 컴퓨터 과학자이다. IBM은 자사의 코다실 데이터베이스인 IMS/DB의 매출을 보호하기 위한 노력의 일환으로 관계형 데이터베이스의 구현에 적극적이지 않았다. 마침내 IBM이 자사의 시스템 R 프로젝트를 시작했을 때, 개발 팀(돈 챔버린과 레이 보이스)은 테드 코드 소속이 아니었으며, 자신들의 언어인 시퀄(Sequel: Structured English Query Language: 구조화 영어 질의어)을 설계하기 위해 코드의 1971년 알파 관계형 언어 논문을 무시했다. 1979년 IBM이 자사의 제품을 출시하기도 전에, 래리 앨리슨은 (준비단계였던 IBM 시퀄 관련 사양들을 자신의 사양에 사용함으로써) 자사의 오라클 데이터베이스에 이 언어를 포함시켰다. 시퀄은 국제 상표권 침해를 회피하기 위해 곧 SQL이 되었다.

(마이클 스톤브레이커의 말을 빌자면) “SQL에 대한 칭송은 오라클과 IBM뿐아니라 고객들에게서도 들려왔다. 코다실 데이터베이스 설계자와 프로그래머를 고용하기가 쉽지 않았기 때문에, 시퀄 (그리고 SQL)이 훨씬 더 매력적으로 보였다. 1980년대 후반에는 SQL이 너무나 매력적이어서 관계형이기 위해서는 관계형 데이터베이스를 처음부터 새로 설계해야만 한다고 생각하고 있던 코드에게는 엄청나게 실망스럽게도, 많은 데이터베이스 공급업체들이 자사의 코다실 데이터베이스 위에 SQL 쿼리 처리기를 기본적으로 탑재할 정도였다.

코드가 설계한 것 같은 순수한 관계형 데이터베이스는 일차 술어 논리(First-Order Predicate Logic)와 일관되게, 관계(Relation)로 그룹화 되는 튜플(Tuple)을 기반으로 구축된다. 실제 관계형 데이터베이스는 필드, 제약 조건(Constraint), 그리고 트리거(Trigger)를 포함하고 있는 테이블을 가지고 있으며, 테이블은 외래 키(Foreign Key)를 통해서 관계가 맺어진다. 리턴 데이터를 선언하기 위해 SQL이 사용되며, SQL 쿼리 처리기(Processor)와 쿼리 최적화기(Optimizer)는 SQL 선언을 데이터베이스 엔진이 실행하는 쿼리 계획(Query Plan)으로 바꾼다.

SQL에는 데이터 수정을 위한 특수 언어인 DML(Data Manipulation Language: 데이터 조작 언어)와 함께, 스키마를 정의하는 특수 언어인 DDL(Data Definition Language: 데이터 정의 언어)이 포함되어 있다. 이 두 가지 모두 초기 코다실 사양에 뿌리를 두고 있다. SQL의 세 번째 특수 언어는 SELECT 문과 관계형 결합(Relational Join)을 통해서 쿼리를 선언한다.

SQL의 SELECT 문
SELECT 문은 쿼리 최적화기에게 어떤 데이터가 리턴되는지, 어떤 테이블을 살펴보아야 하는지, 어느 관계를 따라야 하는지, 그리고 리턴된 데이터에 어떤 순서를 부여해야 하는지를 알려준다. 쿼리 최적화기는 특정 데이터베이스가 인덱스 힌트(Index Hint)를 지원하지 않는 한, 무작위 테이블 스캔(Brute Force Table Scan)을 회피하고 좋은 쿼리 성능을 달성하기 위해 어떤 인덱스를 사용해야 할지를 스스로 알아내야만 한다.


X