SQL
1. 개요
1. 개요
SQL은 관계형 데이터베이스 관리 시스템(RDBMS)에서 데이터를 정의, 조작, 제어하기 위해 사용되는 표준화된 선언형 프로그래밍 언어이다. 데이터베이스에 질의를 보내거나, 데이터를 삽입·수정·삭제하고, 데이터베이스 구조를 생성·변경하는 등 데이터베이스와의 모든 상호작용에 주로 사용된다. SQL은 특정 프로그래밍 언어의 문법에 종속되지 않으며, 다양한 응용 프로그램이나 스크립트 내에서 데이터베이스에 접근하기 위한 인터페이스 역할을 한다.
SQL의 핵심 기능은 크게 데이터 정의, 데이터 조작, 데이터 제어로 나뉜다. 데이터 정의 언어(DDL)는 테이블, 뷰, 인덱스 등의 데이터베이스 객체의 구조를 생성(CREATE), 변경(ALTER), 삭제(DROP)하는 명령어를 포함한다. 데이터 조작 언어(DML)는 테이블 내의 실제 데이터를 조회(SELECT), 추가(INSERT), 수정(UPDATE), 삭제(DELETE)하는 작업을 담당한다. 데이터 제어 언어(DCL)는 데이터에 대한 접근 권한을 부여(GRANT)하거나 회수(REVOKE)하여 보안을 관리한다.
SQL은 사용자가 원하는 *무엇을(What)* 할지 선언하기만 하면, 데이터베이스 엔진이 *어떻게(How)* 수행할지 최적화하고 실행하는 선언형 언어의 특징을 가진다. 이는 처리 절차를 순차적으로 기술하는 명령형 프로그래밍 언어와 대비된다. SQL 문은 일반적으로 하나 이상의 절(clause)로 구성되며, SELECT, FROM, WHERE, GROUP BY, ORDER BY 등이 대표적이다.
SQL은 ANSI와 ISO에 의해 표준이 제정되어 있으나, Oracle, MySQL, Microsoft SQL Server, PostgreSQL 등 주요 RDBMS 벤더들은 각자의 확장 기능이나 약간 다른 문법을 구현하는 경우가 많다. 그럼에도 불구하고 핵심적인 SQL 문법은 대부분 호환되어, 하나의 데이터베이스에서 학습한 지식을 다른 시스템에도 적용할 수 있는 기반을 제공한다.
2. SQL의 역사와 표준
2. SQL의 역사와 표준
SQL은 1970년대 초 IBM 연구소의 도널드 D. 체임벌린과 레이먼드 F. 보이스가 개발한 SEQUEL 언어에서 기원한다. 이 언어는 에드거 F. 커드가 제안한 관계형 데이터베이스 모델을 구현하기 위해 설계되었다. IBM은 이 언어를 사용하여 시스템 R이라는 프로토타입 데이터베이스를 만들었고, 이 경험을 바탕으로 SQL 언어를 계속 발전시켰다.
1980년대에 SQL은 상업적 성공을 거두기 시작했다. 오라클이 상용 RDBMS로 처음 시장에 진출했으며, IBM도 DB2 제품을 출시했다. 이러한 상용화 과정에서 각 벤더는 자체적인 SQL 방언을 추가하기 시작했고, 이로 인해 표준화의 필요성이 대두되었다. 1986년, 미국표준협회와 국제표준화기구가 최초의 SQL 표준인 SQL-86을 발표했다. 이는 SQL이 국제적으로 공식적인 지위를 얻는 중요한 계기가 되었다.
이후 SQL 표준은 지속적으로 확장되어 왔다. 주요 개정판으로는 1992년의 SQL-92, 1999년의 SQL:1999, 2003년의 SQL:2003 등이 있다. 각 표준은 새로운 기능을 도입했는데, 예를 들어 SQL:1999은 재귀 쿼리, 트리거, 객체 지향 기능 등을 추가했다. 최신 표준은 더 복잡한 데이터 유형과 JSON 지원, 향상된 윈도우 함수 등을 포함한다.
표준이 존재함에도 불구하고, 주요 데이터베이스 관리 시스템 벤더들은 여전히 표준을 완전히 준수하지 않거나, 고유의 확장 기능을 제공한다. 이로 인해 Oracle SQL, Transact-SQL, PL/pgSQL과 같은 방언 간의 호환성 문제가 발생하기도 한다. 그러나 SQL 표준은 데이터베이스 기술의 발전 방향을 제시하고, 다양한 시스템 간의 이식성을 높이는 데 기여하고 있다.
3. SQL 문법의 주요 구성 요소
3. SQL 문법의 주요 구성 요소
SQL 문법은 수행하는 작업의 종류에 따라 몇 가지 주요 범주로 나뉜다. 이 범주들은 데이터베이스의 구조를 정의하고, 데이터를 조작하며, 접근 권한과 트랜잭션을 관리하는 기능을 제공한다.
가장 기본적인 범주는 데이터 정의 언어(DDL)이다. DDL은 데이터베이스의 구조를 생성, 변경, 삭제하는 명령어로 구성된다. 주요 명령어로는 CREATE(데이터베이스, 테이블, 인덱스 등 생성), ALTER(기존 객체의 구조 변경), DROP(객체 삭제)이 있다. DDL 명령어는 실행 시 자동으로 커밋되어 트랜잭션 내에서 롤백이 어려운 경우가 많다.
데이터를 조작하는 핵심 범주는 데이터 조작 언어(DML)이다. DML은 테이블에 저장된 실제 데이터를 질의하고 수정하는 데 사용된다. 네 가지 기본 연산인 SELECT(데이터 검색), INSERT(새 데이터 추가), UPDATE(기존 데이터 수정), DELETE(데이터 삭제)가 이에 속한다. 특히 SELECT 문은 다양한 절과 함수를 조합하여 복잡한 질의를 가능하게 한다.
데이터베이스의 보안과 무결성을 관리하는 범주로는 데이터 제어 언어(DCL)와 트랜잭션 제어 언어(TCL)가 있다. DCL은 데이터에 대한 접근 권한을 부여(GRANT)하거나 회수(REVOKE)하는 데 사용된다. TCL은 논리적 작업 단위인 트랜잭션의 상태를 관리하며, COMMIT(변경사항 확정), ROLLBACK(변경사항 취소), SAVEPOINT(트랜잭션 내 중간 저장점 설정) 등의 명령어를 포함한다. 이들은 데이터의 일관성과 회복성을 보장하는 데 필수적이다.
범주 (약어) | 주요 명령어 | 주요 역할 |
|---|---|---|
데이터 정의 언어 (DDL) |
| 데이터베이스 스키마(구조) 정의 및 수정 |
데이터 조작 언어 (DML) |
| 데이터 검색, 추가, 수정, 삭제 |
데이터 제어 언어 (DCL) |
| 사용자 권한 부여 및 관리 |
트랜잭션 제어 언어 (TCL) |
| 트랜잭션 관리 및 데이터 무결성 보장 |
3.1. 데이터 정의 언어 (DDL)
3.1. 데이터 정의 언어 (DDL)
데이터 정의 언어는 데이터베이스의 구조를 정의하고 변경하며 삭제하는 데 사용되는 SQL 명령어들의 집합이다. 이 언어를 통해 사용자는 데이터베이스 스키마를 생성하고 관리한다. 주요 명령어로는 CREATE, ALTER, DROP이 있으며, 이들은 각각 객체 생성, 구조 변경, 객체 삭제 기능을 담당한다.
가장 기본적인 명령어는 CREATE이다. CREATE TABLE 문을 사용하면 새로운 테이블을 정의할 수 있으며, 이때 컬럼의 이름, 데이터 타입, 제약 조건 등을 지정한다. 예를 들어, 기본 키나 외래 키 제약을 설정하여 데이터 무결성을 보장할 수 있다. CREATE INDEX는 검색 성능을 향상시키기 위한 인덱스를 생성하고, CREATE VIEW는 하나 이상의 테이블을 기반으로 한 가상 테이블인 뷰를 정의한다.
기존 객체의 구조를 수정할 때는 ALTER 명령어를 사용한다. ALTER TABLE 문은 테이블에 새로운 컬럼을 추가하거나, 기존 컬럼의 데이터 타입을 변경하며, 제약 조건을 추가 또는 삭제하는 작업을 수행한다. 이 명령어를 통해 데이터베이스 구조를 중단 없이 진화시킬 수 있다.
객체를 데이터베이스에서 완전히 제거하려면 DROP 명령어를 사용한다. DROP TABLE은 테이블과 그 안의 모든 데이터를 삭제하며, DROP INDEX나 DROP VIEW는 각각 인덱스와 뷰를 제거한다. 이 작업은 주의를 요하며, 일반적으로 되돌릴 수 없다. 일부 데이터베이스 시스템은 실수를 방지하기 위해 DROP TABLE IF EXISTS와 같은 조건부 삭제 구문을 지원한다.
명령어 | 대상 객체 | 주요 기능 |
|---|---|---|
| TABLE, INDEX, VIEW | 새로운 데이터베이스 객체를 생성한다. |
| TABLE | 기존 테이블의 구조(컬럼, 제약)를 변경한다. |
| TABLE, INDEX, VIEW | 데이터베이스 객체를 삭제한다. |
3.2. 데이터 조작 언어 (DML)
3.2. 데이터 조작 언어 (DML)
데이터 조작 언어는 데이터베이스 내에 저장된 데이터를 직접 조작하는 데 사용되는 SQL 명령어들의 집합이다. 주로 데이터의 검색, 추가, 수정, 삭제 작업을 수행하며, 데이터베이스 사용자가 가장 빈번하게 접하는 부분이다.
핵심 명령어는 네 가지로 구성된다. SELECT 문은 하나 이상의 테이블에서 데이터를 조회한다. INSERT 문은 테이블에 새로운 행을 추가한다. UPDATE 문은 테이블 내 기존 행의 데이터를 수정한다. DELETE 문은 테이블에서 특정 행을 제거한다. 이 중 SELECT는 데이터를 변경하지 않고 읽기만 하는 반면, 나머지 세 명령어는 데이터 자체를 변경하므로 주의해서 사용해야 한다.
DML 작업은 종종 WHERE 절과 함께 사용되어 특정 조건을 만족하는 데이터만 대상으로 한다. 예를 들어, UPDATE employees SET salary = salary * 1.1 WHERE department = 'Sales';와 같은 구문은 'Sales' 부서 직원의 급여만 10% 인상한다. 조건이 생략되면 테이블의 모든 행에 영향을 미치므로, 특히 UPDATE와 DELETE 실행 시 조건을 명시하는 것이 중요하다.
다음은 주요 DML 명령어의 기본 형식을 보여주는 표이다.
명령어 | 기본 형식 | 주요 역할 |
|---|---|---|
|
| 데이터 조회 |
|
| 데이터 추가 |
|
| 데이터 수정 |
|
| 데이터 삭제 |
이러한 DML 명령어의 실행은 일반적으로 하나의 트랜잭션으로 묶인다. 따라서 변경 사항은 COMMIT 명령어를 통해 확정되거나, ROLLBACK 명령어를 통해 실행 전 상태로 되돌릴 수 있다.
3.3. 데이터 제어 언어 (DCL)
3.3. 데이터 제어 언어 (DCL)
데이터 제어 언어는 데이터베이스의 보안과 권한 관리를 담당하는 SQL 명령어 집합이다. 주로 데이터베이스 관리자(DBA)가 사용하며, 사용자에게 데이터베이스 객체에 대한 접근 권한을 부여하거나 회수하는 데 중점을 둔다. 이를 통해 데이터 무결성과 보안을 유지하고, 허가되지 않은 접근으로부터 시스템을 보호한다.
DCL의 핵심 명령어는 GRANT와 REVOKE이다. GRANT 문은 특정 사용자나 역할(Role)에게 특정 권한을 부여한다. 부여할 수 있는 권한에는 객체(예: 테이블, 뷰)에 대한 SELECT, INSERT, UPDATE, DELETE, REFERENCES와 같은 객체 권한과, CREATE SESSION, CREATE TABLE과 같은 시스템 권한이 포함된다. REVOKE 문은 반대로 이미 부여된 권한을 취소한다.
권한 관리는 세분화되어 이루어진다. 예를 들어, 한 사용자에게 특정 테이블에 대해 SELECT 권한만 부여하여 데이터 조회는 허용하지만, 데이터 변경(INSERT, UPDATE)은 불가능하게 할 수 있다. 또한, WITH GRANT OPTION 절을 사용하면 권한을 받은 사용자가 다른 사용자에게 동일한 권한을 부여할 수 있는 권한까지 위임할 수 있다.
명령어 | 주요 기능 | 예시 |
|---|---|---|
| 권한 부여 |
|
| 권한 회수 |
|
이러한 권한 제어 메커니즘은 다중 사용자 환경에서 데이터베이스의 안전한 운영을 위한 필수적인 요소이다. 일부 데이터베이스 시스템에서는 DENY와 같은 추가적인 명령어를 제공하여 명시적으로 특정 권한을 거부하는 기능도 지원한다[1].
3.4. 트랜잭션 제어 언어 (TCL)
3.4. 트랜잭션 제어 언어 (TCL)
트랜잭션 제어 언어는 데이터베이스 트랜잭션의 시작과 종료, 그리고 내부의 저장점을 관리하는 명령어들의 집합이다. 이 명령어들을 통해 여러 개의 데이터 조작 언어 작업을 논리적인 하나의 작업 단위로 묶고, 그 결과를 데이터베이스에 영구적으로 반영하거나 취소할 수 있다. 이를 통해 데이터의 무결성과 일관성을 보장한다.
주요 명령어로는 COMMIT, ROLLBACK, SAVEPOINT가 있다. COMMIT 명령은 현재 트랜잭션에서 수행한 모든 변경 사항을 데이터베이스에 영구적으로 저장하고 트랜잭션을 종료한다. ROLLBACK 명령은 트랜잭션 시작 이후 또는 특정 저장점 이후의 모든 변경 사항을 취소하고 트랜잭션을 종료한다. SAVEPOINT는 트랜잭션 내에 특정 지점을 저장점으로 설정하여, 이후에 ROLLBACK TO SAVEPOINT 명령으로 해당 저장점까지만 변경을 취소할 수 있게 한다.
명령어 | 설명 |
|---|---|
| 트랜잭션의 변경 사항을 영구 저장하고 트랜잭션을 종료한다. |
| 트랜잭션의 변경 사항을 모두 취소하고 트랜잭션을 종료한다. |
| 트랜잭션 내에 이름이 지정된 저장점을 설정한다. |
| 지정된 저장점까지의 변경 사항만 취소한다. |
이러한 명령어들은 일반적으로 데이터 조작 언어 문장들 사이에서 사용된다. 예를 들어, 여러 개의 UPDATE 문을 실행한 후 문제가 없으면 COMMIT으로 확정하고, 오류가 발생하면 ROLLBACK으로 모든 UPDATE를 원상태로 되돌릴 수 있다. 데이터 정의 언어 문장은 대부분 자동으로 커밋되는 경우가 많아 트랜잭션 제어 언어로 롤백할 수 없는 경우도 있다.
4. 핵심 쿼리 구문
4. 핵심 쿼리 구문
SELECT 문은 SQL에서 데이터를 검색하는 가장 기본적이고 핵심적인 명령어이다. SELECT 절에는 조회할 열을, FROM 절에는 데이터를 가져올 테이블을 지정한다. WHERE 절을 사용하면 특정 조건을 만족하는 행만 필터링할 수 있으며, ORDER BY 절로 결과를 정렬할 수 있다. 기본 구조는 SELECT 열1, 열2 FROM 테이블명 WHERE 조건 ORDER BY 정렬기준이다.
데이터를 하나 이상의 테이블에서 결합하여 조회할 때는 조인 (JOIN)을 사용한다. 가장 일반적인 조인은 내부 조인 (INNER JOIN)으로, 두 테이블 간 지정된 조인 조건을 만족하는 행만 결과에 포함된다. 왼쪽 외부 조인 (LEFT OUTER JOIN)은 왼쪽 테이블의 모든 행을 가져오고, 오른쪽 테이블에서 조건에 맞는 행이 없으면 NULL 값을 반환한다. 이 외에도 오른쪽 외부 조인 (RIGHT OUTER JOIN), 완전 외부 조인 (FULL OUTER JOIN), 자체 조인 (SELF JOIN) 등이 있다.
조인 유형 | 설명 |
|---|---|
두 테이블 모두에 일치하는 행만 반환 | |
왼쪽 테이블의 모든 행과 일치하는 오른쪽 행 반환 | |
두 테이블의 카테시안 곱 반환 |
데이터를 그룹화하고 집계하려면 집계 함수와 GROUP BY 절을 함께 사용한다. 대표적인 집계 함수로는 COUNT(), SUM(), AVG(), MAX(), MIN() 등이 있다. GROUP BY 뒤에 지정한 열의 값이 같은 행들을 하나의 그룹으로 묶고, 각 그룹별로 집계 함수를 적용한다. HAVING 절은 GROUP BY로 생성된 그룹에 대한 필터 조건을 지정할 때 사용하며, WHERE 절은 개별 행을 필터링하는 데 사용된다는 점에서 차이가 있다.
하나의 SQL 문 안에 다른 SQL 문을 포함시키는 서브쿼리는 주 쿼리에 데이터를 제공하거나 조건을 결정하는 데 사용된다. 서브쿼리는 SELECT, FROM, WHERE 절 등 여러 위치에서 활용될 수 있다. 단일 값을 반환하는 스칼라 서브쿼리, 여러 행을 반환하는 서브쿼리, 상관 서브쿼리 등 다양한 형태가 존재한다. 서브쿼리는 복잡한 논리를 구현할 수 있게 해주지만, 성능에 영향을 미칠 수 있으므로 주의가 필요하다.
4.1. SELECT 문과 데이터 검색
4.1. SELECT 문과 데이터 검색
SELECT 문은 SQL에서 데이터를 검색하는 데 사용되는 가장 기본적이고 핵심적인 명령어이다. 이 문은 하나 이상의 테이블에서 사용자가 지정한 조건에 맞는 행과 열을 선택하여 결과 집합을 반환한다. 기본 구조는 SELECT 열_목록 FROM 테이블_이름이며, 여기에 다양한 절을 추가하여 검색을 세밀하게 제어할 수 있다.
검색의 정밀도를 높이기 위해 WHERE 절을 사용하여 특정 조건을 만족하는 행만 필터링할 수 있다. 예를 들어, WHERE salary > 50000은 급여가 5만을 초과하는 직원 레코드만 선택한다. 결과의 순서를 지정하려면 ORDER BY 절을 사용하며, 오름차순(ASC) 또는 내림차순(DESC) 정렬이 가능하다. 중복된 행을 제거하고 싶을 때는 SELECT 키워드 뒤에 DISTINCT를 추가한다.
절 | 키워드 | 주요 기능 |
|---|---|---|
행 필터링 |
| 지정된 조건에 맞는 행만 선택 |
결과 정렬 |
| 지정된 열 기준으로 결과 정렬 |
중복 제거 |
| 선택된 열에서 중복 값 제거 |
결과 제한 |
| 반환할 행의 수 제한[2] |
SELECT 문은 단순한 데이터 조회를 넘어, 표현식과 열 별칭을 사용하여 계산된 값을 출력할 수 있다. 예를 들어, SELECT unit_price * quantity AS total_amount는 단가와 수량을 곱한 총액을 total_amount라는 새 열 이름으로 보여준다. 또한, 여러 테이블을 연결하는 조인이나 집계 함수와 함께 사용되어 복잡한 데이터 분석의 기초를 형성한다.
4.2. 조인 (JOIN)
4.2. 조인 (JOIN)
조인은 둘 이상의 테이블에 저장된 관련 데이터를 연결하여 하나의 결과 집합으로 만드는 SQL의 핵심 연산이다. 관계형 데이터베이스의 정규화된 데이터를 효율적으로 통합하는 데 필수적이다. 조인의 기본 원리는 두 테이블 간에 공통된 열(기본 키와 외래 키 관계가 일반적)을 기준으로 행을 결합하는 것이다.
가장 일반적인 조인 유형은 다음과 같다.
조인 유형 | 설명 |
|---|---|
내부 조인 (INNER JOIN) | 두 테이블에서 조인 조건을 만족하는 행만 반환한다. 가장 흔히 사용된다. |
왼쪽 외부 조인 (LEFT OUTER JOIN) | 왼쪽 테이블의 모든 행과, 조인 조건을 만족하는 오른쪽 테이블의 행을 반환한다. 조건을 만족하지 않으면 오른쪽 열은 NULL로 채워진다. |
오른쪽 외부 조인 (RIGHT OUTER JOIN) | 오른쪽 테이블의 모든 행과, 조인 조건을 만족하는 왼쪽 테이블의 행을 반환한다. |
완전 외부 조인 (FULL OUTER JOIN) | 양쪽 테이블의 모든 행을 반환하며, 조인 조건이 맞지 않는 부분은 NULL로 채운다. |
크로스 조인 (CROSS JOIN) | 두 테이블의 모든 행의 카테시안 곱을 반환한다. 명시적 조인 조건이 없다. |
조인은 명시적 조인 구문(JOIN ... ON)을 사용하거나, WHERE 절에 조인 조건을 명시하는 암시적 조인 구문으로 작성할 수 있다. 현대적인 SQL에서는 가독성과 명확성을 위해 명시적 조인 구문을 사용하는 것이 권장된다. 조인 조건을 정확히 지정하지 않거나, 카디널리티가 높은 열을 조인하면 의도하지 않은 많은 수의 행이 생성되어 성능에 심각한 영향을 미칠 수 있다.
4.3. 집계 함수와 GROUP BY
4.3. 집계 함수와 GROUP BY
집계 함수는 테이블의 여러 행을 그룹화하여 하나의 결과 값을 계산하는 함수이다. 대표적인 집계 함수로는 COUNT, SUM, AVG, MAX, MIN 등이 있다. 예를 들어, SUM(price)는 특정 그룹 내 모든 price 값의 합계를 반환한다. 이러한 함수는 단독으로 사용되어 전체 테이블에 대한 통계를 낼 수도 있고, GROUP BY 절과 결합하여 특정 기준별로 그룹화된 통계를 생성하는 데 더욱 자주 사용된다.
GROUP BY 절은 지정된 하나 이상의 열을 기준으로 행을 그룹으로 묶는다. 집계 함수는 각 그룹 내의 데이터에 대해 개별적으로 적용된다. 기본 문법은 SELECT column1, AGG_FUNC(column2) FROM table GROUP BY column1; 형태를 따른다. 이때 SELECT 절에 나열된 모든 일반 열(집계 함수가 적용되지 않은 열)은 반드시 GROUP BY 절에 포함되어야 한다. 그렇지 않으면 문법 오류가 발생한다.
GROUP BY 절과 함께 HAVING 절을 사용하면, WHERE 절이 개별 행을 필터링하는 것과 달리, 집계 결과를 바탕으로 그룹 자체를 필터링할 수 있다. 예를 들어, 평균 급여가 특정 값 이상인 부서만 조회하려면 GROUP BY dept_id HAVING AVG(salary) > 50000과 같은 조건을 추가한다. WHERE 절은 그룹화 전 행을 필터링하고, HAVING 절은 그룹화 후 생성된 그룹을 필터링한다는 점이 핵심 차이점이다.
집계 함수와 GROUP BY를 효과적으로 사용하기 위해서는 데이터의 분포와 그룹화의 목적을 이해하는 것이 중요하다. 잘못 설계된 그룹화는 성능 저하를 초래하거나 의미 없는 결과를 도출할 수 있다. 또한, ROLLUP이나 CUBE와 같은 확장 구문을 사용하면 소계(Subtotal)나 총계(Grand Total)를 포함한 다차원적인 집계 결과를 생성할 수 있다.
4.4. 서브쿼리
4.4. 서브쿼리
서브쿼리는 하나의 SQL 문 내에 포함된 또 다른 SELECT 문이다. 주 쿼리의 조건이나 결과 집합을 구성하기 위해 내부적으로 실행되는 쿼리를 의미하며, 괄호로 묶어서 표현한다. 서브쿼리는 단일 값을 반환하는 스칼라 서브쿼리, 여러 행과 단일 열을 반환하는 서브쿼리, 여러 행과 여러 열을 반환하는 서브쿼리 등 그 형태에 따라 다양하게 활용된다.
서브쿼리는 주로 WHERE 절, FROM 절, SELECT 절에 위치한다. WHERE 절에서는 IN, EXISTS, ANY, ALL 등의 연산자와 함께 사용되어 조건을 필터링하는 데 쓰인다. 예를 들어, 특정 부서에 속한 직원을 찾기 위해 부서 테이블을 먼저 조회하는 방식이다. FROM 절에 사용되는 서브쿼리는 인라인 뷰라고 불리며, 하나의 임시 테이블처럼 동작하여 주 쿼리에서 조인이나 추가 조작의 대상이 된다.
서브쿼리의 성능은 데이터베이스 시스템의 옵티마이저에 의해 최적화되지만, 주의 깊게 작성하지 않으면 성능 저하를 초래할 수 있다. 특히 상관 서브쿼리는 외부 쿼리의 각 행에 대해 내부 쿼리가 반복 실행되기 때문에 데이터 양이 많을 경우 비효율적일 수 있다. 이러한 경우 조인 연산으로 재작성하는 것이 성능 향상에 도움이 되는 경우가 많다[3].
서브쿼리의 주요 유형과 사용 예는 다음과 같이 정리할 수 있다.
유형 | 설명 | 사용 예 |
|---|---|---|
스칼라 서브쿼리 | 단일 행, 단일 열(값)을 반환하는 서브쿼리. SELECT 리스트나 조건식에서 사용 가능. |
|
다중 행 서브쿼리 |
| |
상관 서브쿼리 | 외부 쿼리의 컬럼을 참조하는 서브쿼리. 외부 쿼리의 각 행에 대해 실행됨. |
|
인라인 뷰 | FROM 절에 위치하여 임시 테이블 역할을 하는 서브쿼리. |
|
5. 데이터베이스 객체
5. 데이터베이스 객체
데이터베이스 객체는 관계형 데이터베이스 관리 시스템(RDBMS)에서 데이터를 구조화하고, 접근하며, 관리하기 위해 생성되는 논리적 단위이다. 이 객체들은 SQL의 데이터 정의 언어(DDL)를 사용하여 생성, 변경, 삭제된다. 주요 객체로는 데이터를 저장하는 테이블, 논리적 데이터 뷰를 제공하는 뷰, 검색 성능을 향상시키는 인덱스, 그리고 비즈니스 로직을 캡슐화하는 저장 프로시저와 함수 등이 있다.
가장 기본적이고 핵심적인 객체는 테이블이다. 테이블은 행과 열로 구성되며, 모든 실제 데이터는 테이블에 저장된다. 각 열은 특정 데이터 타입을 가지며, 기본 키, 외래 키 같은 제약 조건을 통해 데이터 무결성을 보장한다. 뷰는 하나 이상의 테이블을 기반으로 하는 가상 테이블이다. 실제 데이터를 저장하지 않지만, 복잡한 쿼리를 단순화하거나 특정 사용자에게 보여줄 데이터를 제한하는 데 사용된다. 뷰에 대한 쿼리는 기본 테이블에 대한 쿼리로 변환되어 실행된다.
객체 유형 | 주요 목적 | 생성 키워드 | 비고 |
|---|---|---|---|
데이터 물리적 저장 |
| 데이터의 기본 저장 단위 | |
논리적 데이터 표현 |
| 가상 테이블, 데이터 저장 안 함 | |
데이터 검색 속도 향상 |
| 책의 색인과 유사한 역할 | |
비즈니스 로직 캡슐화 |
| 일련의 SQL 문을 하나의 단위로 실행 | |
계산 및 값 반환 |
| 프로시저와 유사하지만 반드시 값 반환 |
인덱스는 테이블의 특정 열에 대한 검색 속도를 높이기 위해 사용되는 자료 구조이다. 책의 색인과 유사하게 동작하여, 전체 테이블을 스캔하지 않고도 원하는 데이터를 빠르게 찾을 수 있게 한다. 그러나 인덱스는 추가 저장 공간을 차지하며, 데이터 삽입, 갱신, 삭제 시 성능 오버헤드를 발생시킬 수 있다. 저장 프로시저와 함수는 데이터베이스 서버에 저장되는 실행 가능한 코드 블록이다. 저장 프로시저는 주로 여러 SQL 문을 하나의 트랜잭션으로 묶어 실행할 때 사용되며, 함수는 매개변수를 받아 계산을 수행하고 단일 값을 반환한다. 이들은 코드 재사용성을 높이고 네트워크 트래픽을 줄이는 데 기여한다.
5.1. 테이블과 뷰
5.1. 테이블과 뷰
테이블은 관계형 데이터베이스에서 데이터를 저장하는 기본 단위이다. 행과 열로 구성되며, 각 열은 특정 데이터 타입을 가진다. 테이블은 데이터 정의 언어를 사용하여 생성, 변경, 삭제된다. 테이블의 구조는 스키마에 의해 정의되며, 기본 키, 외래 키 등의 제약 조건을 통해 데이터 무결성을 보장한다.
뷰는 하나 이상의 테이블로부터 유도된 가상 테이블이다. 실제 데이터를 저장하지 않고, 저장된 쿼리의 결과를 테이블처럼 보여준다. 뷰는 복잡한 쿼리를 단순화하거나, 특정 사용자에게 보여줄 데이터를 제한하는 데 사용된다. 보안 계층으로서의 역할도 수행한다[4].
테이블과 뷰의 주요 차이점은 다음과 같다.
특성 | 테이블 | 뷰 |
|---|---|---|
데이터 저장 | 물리적으로 데이터를 저장함 | 데이터를 저장하지 않음 (쿼리 정의만 저장) |
성능 | 일반적으로 빠른 접근이 가능함 | 기본 테이블의 쿼리를 실행하므로 상대적으로 느릴 수 있음 |
업데이트 | 직접 데이터 삽입, 수정, 삭제가 가능함 | 일부 제약 조건 하에서만 업데이트가 가능함[5] |
용도 | 원본 데이터 저장 | 쿼리 단순화, 보안, 논리적 데이터 추상화 |
뷰는 크게 단순 뷰와 복합 뷰로 나눌 수 있다. 단순 뷰는 하나의 테이블에서 파생되며, 데이터 수정이 가능한 경우가 많다. 복합 뷰는 여러 테이블을 조인하거나 집계 함수를 사용하여 생성되며, 주로 읽기 전용으로 사용된다.
5.2. 인덱스
5.2. 인덱스
인덱스는 데이터베이스 내의 테이블에 대한 검색 성능을 향상시키기 위해 사용되는 자료 구조이다. 책의 색인과 유�사하게, 특정 컬럼(열)의 값을 기반으로 데이터의 물리적 위치를 빠르게 찾을 수 있도록 하는 포인터 역할을 한다. 테이블에 인덱스를 생성하면, 해당 컬럼을 기준으로 한 정렬된 데이터 구조가 별도로 생성되고 유지 관리된다. 이 구조는 주로 B-트리나 해시 테이블과 같은 알고리즘을 기반으로 구현된다.
인덱스의 주요 유형으로는 단일 컬럼에 생성하는 단일 인덱스, 여러 컬럼을 조합하여 생성하는 복합 인덱스, 그리고 데이터의 물리적 정렬 순서와 일치하는 클러스터형 인덱스가 있다. 클러스터형 인덱스는 테이블당 보통 하나만 생성할 수 있으며, 데이터 자체를 지정된 키 값 순서로 저장하고 재구성한다. 반면, 비클러스터형 인덱스는 테이블 데이터와는 별도의 구조로 존재하며, 여러 개를 생성할 수 있다.
인덱스 설계는 신중하게 이루어져야 한다. 적절한 인덱스는 SELECT 쿼리의 속도를 획기적으로 개선하지만, 불필요하거나 과도한 인덱스는 성능에 부정적인 영향을 미친다. 인덱스가 존재하는 테이블에 데이터를 추가(INSERT), 수정(UPDATE), 삭제(DELETE)할 때마다 인덱스 구조도 함께 갱신되어야 하기 때문에, 쓰기 작업의 오버헤드가 발생한다. 또한, 인덱스를 저장하기 위한 추가적인 디스크 공간이 필요하다.
효율적인 인덱스 전략을 수립하기 위해서는 애플리케이션의 주요 쿼리 패턴, 데이터의 분포도, 그리고 조인 조건에 사용되는 컬럼 등을 분석해야 한다. 자주 검색 조건(WHERE 절)이나 정렬(ORDER BY), 조인에 사용되는 컬럼에 인덱스를 생성하는 것이 일반적이다. 데이터 변경이 빈번한 컬럼이나, 카디널리티(중복도)가 매우 낮은 컬럼(예: 성별 코드)에 대한 인덱스는 효과가 적을 수 있다. 데이터베이스 관리 시스템은 쿼리 최적화 과정에서 비용 기반 최적화를 수행하며, 가장 효율적인 인덱스를 선택하여 실행 계획을 수립한다.
5.3. 저장 프로시저와 함수
5.3. 저장 프로시저와 함수
저장 프로시저는 데이터베이스 서버에 저장되어 하나의 단위로 실행되는 SQL 문장들의 집합이다. 반복적으로 사용되는 복잡한 비즈니스 로직을 캡슐화하여 재사용성을 높이고, 네트워크 트래픽을 줄이며, 보안을 강화하는 데 사용된다. 저장 프로시저는 일반적으로 CREATE PROCEDURE 문으로 생성되며, EXECUTE나 CALL 명령어로 실행된다. 입력 매개변수를 받아들이고, 출력 매개변수나 결과 집합을 반환할 수 있다.
저장 함수는 프로시저와 유사하지만, 주로 단일 값을 계산하여 반환하는 데 사용된다. SELECT 문이나 표현식 내에서 직접 호출될 수 있다는 점이 프로시저와의 주요 차이점이다. 함수는 CREATE FUNCTION 문으로 정의되며, 반드시 데이터 타입을 명시하는 반환값을 가져야 한다. 함수는 다시 결정적 함수와 비결정적 함수로 구분될 수 있다[6].
객체 | 주요 목적 | 반환값 | SQL 문 내 호출 가능성 |
|---|---|---|---|
저장 프로시저 | 비즈니스 로직 실행, 작업 수행 | 선택사항 (결과 집합 또는 출력 매개변수) | 일반적으로 독립적으로 실행 |
저장 함수 | 값 계산 | 필수 (단일 스칼라 값 또는 테이블) | SELECT 문 등 표현식 내에서 직접 사용 가능 |
이들 객체를 사용하면 애플리케이션 코드에서 직접 SQL을 작성하는 대신 데이터베이스 서버 측에 로직을 위임할 수 있다. 이는 코드 모듈화를 촉진하고, 유지보수성을 향상시키며, 데이터 접근 제어를 중앙에서 관리할 수 있게 한다. 다만, 과도한 사용은 데이터베이스 서버의 부하를 증가시키고 비즈니스 로직의 이식성을 낮출 수 있다는 점에 유의해야 한다.
6. 성능 최적화와 고려사항
6. 성능 최적화와 고려사항
성능 최적화는 데이터베이스 시스템의 응답 시간을 단축하고 자원 사용 효율을 높이는 과정이다. 핵심은 쿼리가 데이터에 접근하고 처리하는 방식을 최적화하는 것이다. 이를 위해 먼저 데이터베이스 관리 시스템(DBMS)이 제공하는 실행 계획 분석 도구를 사용한다. 실행 계획은 쿼리가 어떤 순서로 테이블을 스캔하고, 인덱스를 사용하며, 조인 알고리즘을 적용하는지 상세히 보여준다. 비효율적인 풀 테이블 스캔이나 잘못된 조인 순서, 불필요한 정렬 작업 등을 실행 계획에서 식별하는 것이 튜닝의 첫 단계이다.
인덱스 설계는 성능 최적화의 근간이다. 적절한 인덱스는 데이터 접근 경로를 단축하지만, 과도한 인덱스는 데이터 갱신(INSERT, UPDATE, DELETE) 성능을 저하시키고 저장 공간을 낭비한다. 인덱스 설계 전략에는 카디널리티가 높은 컬럼에 인덱스를 생성하는 것, 자주 사용되는 조인 조건과 WHERE 절 필터 조건을 고려하는 것, 복합 인덱스의 컬럼 순서를 쿼리 패턴에 맞추는 것 등이 포함된다. 또한 클러스터형 인덱스와 비클러스터형 인덱스의 차이를 이해하고 데이터 모델에 맞게 선택하는 것이 중요하다.
쿼리 튜닝 기법은 작성된 SQL 문 자체를 개선하는 방법이다. 일반적인 기법으로는 불필요한 컬럼을 SELECT 절에 나열하지 않기, 서브쿼리 대신 조인을 활용하기(또는 그 반대 경우도 성능에 따라 검토), LIKE 연산자에서 선두 와일드카드(%) 사용을 피하기, 집계 함수 사용 시 불필요한 데이터를 먼저 필터링하기 등이 있다. 또한 옵티마이저 힌트를 사용해 특정 인덱스 사용이나 조인 방법을 강제할 수 있지만, 이는 데이터 분포나 통계 정보 변경으로 인해 최적의 방법이 달라질 수 있으므로 신중하게 적용해야 한다.
최적화 대상 | 주요 접근법 | 고려사항 |
|---|---|---|
쿼리 실행 계획 | 실행 계획 분석, 통계 정보 갱신 | 비용 기반 옵티마이저의 결정을 이해 |
인덱스 설계 | 카디널리티 고려, 복합 인덱스 컬럼 순서, 인덱스 유형 선택 | 갱신 작업 부하와의 트레이드오프 |
쿼리 작성 | 불필요한 데이터 처리 제거, 효율적인 조인 방법 선택, 서브쿼리 최적화 | 데이터베이스별 최적화기 특성 반영 |
성능 최적화는 일회성 작업이 아니라 지속적인 모니터링과 조정 과정이다. 애플리케이션의 데이터 사용 패턴이 변화하면 기존의 최적화 전략도 재평가되어야 한다.
6.1. 실행 계획 분석
6.1. 실행 계획 분석
실행 계획은 데이터베이스 관리 시스템이 사용자가 제출한 SQL 쿼리를 처리하기 위해 선택한 내부 작업 절차의 상세한 로드맵이다. 쿼리 옵티마이저가 여러 가능한 실행 경로 중 예상 비용을 계산하여 최적의 경로를 선택한 결과를 보여준다. 이 계획을 분석함으로써 개발자나 데이터베이스 관리자는 쿼리가 어떻게 실행될지 이해하고, 병목 현상이나 비효율적인 연산을 식별하여 성능을 개선할 수 있다.
대부분의 현대 DBMS는 EXPLAIN 또는 EXPLAIN ANALYZE와 같은 명령어를 제공하여 실행 계획을 텍스트나 그래픽 형태로 출력한다. 실행 계획은 일반적으로 트리 구조로 표현되며, 각 노드는 테이블 스캔, 조인, 정렬, 집계 등의 단일 연산을 나타낸다. 각 노드에는 해당 연산에 대한 예상 비용(예: 시작 비용, 총 비용), 예상 반환 행 수, 사용된 접근 방법(예: 인덱스 스캔, 전체 테이블 스캔) 등의 정보가 포함된다.
분석 시 주목해야 할 주요 항목은 다음과 같다.
주목할 연산 | 설명 | 일반적 의미 |
|---|---|---|
Seq Scan (Full Table Scan) | 테이블의 모든 행을 순차적으로 읽음 | 대용량 테이블에서 비효율적일 수 있음 |
Index Scan / Index Only Scan | 인덱스를 통해 데이터 접근 | 선택도가 높은 쿼리에 효율적 |
Nested Loop Join | 중첩 루프 방식 조인 | 한쪽 테이블이 매우 작을 때 유리 |
Hash Join | 해시 테이블을 생성하여 조인 | 대용량 데이터의 동등 조인에 효율적 |
Sort | 정렬 연산 | 메모리 또는 디스크 사용량이 많을 수 있음 |
Aggregate | 집계 연산 (GROUP BY) |
실행 계획 분석의 핵심은 고비용 노드를 찾고, 그 원인을 파악하는 것이다. 예를 들어, 예상보다 많은 행을 처리하는 Seq Scan이 발생한다면 적절한 인덱스가 부족할 수 있다. 불필요한 Sort 연산이 있다면 인덱스를 활용해 정렬 단계를 생략할 수 있다. 또한, 옵티마이저의 예상 행 수와 실제 행 수가 크게 차이 나면 테이블 통계 정보가 오래되어 잘못된 계획을 수립했을 가능성이 있다. 이러한 분석을 바탕으로 SQL 쿼리 튜닝이나 인덱스 설계를 재검토하게 된다.
6.2. 인덱스 설계 전략
6.2. 인덱스 설계 전략
인덱스 설계는 데이터베이스 성능에 직접적인 영향을 미치는 핵심 요소이다. 효과적인 인덱스 설계 전략은 빠른 데이터 검색과 효율적인 쿼리 처리를 보장하지만, 부적절한 설계는 오히려 입출력 부하를 증가시키고 저장 공간을 낭비할 수 있다. 설계 시에는 선택도, 클러스터링 팩터, 카디널리티와 같은 개념을 고려하여 인덱스의 효용성을 판단해야 한다.
인덱스 설계의 기본 원칙은 WHERE 절이나 JOIN 조건에 자주 사용되는 컬럼, 그리고 ORDER BY나 GROUP BY 절에 사용되는 컬럼에 우선적으로 인덱스를 생성하는 것이다. 특히, 기본 키는 대부분의 시스템에서 자동으로 클러스터형 인덱스가 생성되며, 외래 키 역시 조인 성능 향상을 위해 인덱싱하는 것이 일반적이다. 복합 컬럼 인덱스를 설계할 때는 컬럼의 순서가 매우 중요하다. 가장 선택도가 높은(고유한 값이 많은) 컬럼을 선두에 배치하고, 범위 검색에 사용되는 컬럼은 뒤쪽에 배치하는 것이 효율적이다.
설계 고려사항 | 설명 | 예시/권장 사항 |
|---|---|---|
인덱스 대상 컬럼 선정 | WHERE, JOIN, ORDER BY/GROUP BY에 빈번히 사용되는 컬럼 |
|
복합 인덱스 컬럼 순서 | 카디널리티가 높은 컬럼을 선두에, 등치 조건 컬럼을 범위 조건보다 앞에[7] |
|
인덱스 유형 선택 | 대부분의 범용 검색에는 B-트리, 낮은 카디널리티 컬럼에는 비트맵 | |
인덱스 유지 비용 고려 | 실제 쿼리 패턴을 분석하여 필수적인 인덱스만 유지 |
마지막으로, 인덱스 설계는 정적이지 않다. 애플리케이션의 쿼리 패턴이 변화함에 따라 주기적으로 인덱스 사용 현황을 모니터링하고 재평가해야 한다. 사용되지 않는 인덱스는 제거하고, 새로운 쿼리 패턴에 맞춰 인덱스를 추가하거나 기존 인덱스를 조정하는 작업이 지속적으로 필요하다. 데이터베이스 시스템이 제공하는 실행 계획 분석 도구를 활용하여 인덱스가 예상대로 효율적으로 사용되고 있는지 확인하는 것이 좋다.
6.3. 쿼리 튜닝 기법
6.3. 쿼리 튜닝 기법
쿼리 튜닝은 데이터베이스 시스템의 성능을 향상시키기 위해 SQL 문의 실행 효율성을 분석하고 개선하는 과정이다. 주된 목표는 동일한 결과를 반환하면서도 더 적은 시스템 자원(CPU, I/O, 메모리)을 사용하고 더 빠르게 실행되는 쿼리를 작성하는 것이다. 튜닝은 주로 비효율적인 인덱스 사용, 불필요한 데이터 접근, 최적화되지 않은 조인 방식 등에서 발생하는 병목 현상을 해결하는 데 초점을 맞춘다.
가장 기본적이고 효과적인 튜닝 기법은 적절한 인덱스를 활용하는 것이다. 자주 사용되는 검색 조건(WHERE 절)이나 조인 조건, 정렬(ORDER BY) 및 그룹화(GROUP BY)에 사용되는 컬럼에 인덱스를 생성하면 데이터 접근 속도가 크게 향상된다. 특히, 선택도가 높은(고유한 값이 많은) 컬럼에 인덱스를 생성하는 것이 유리하다. 반면, 너무 많은 인덱스는 데이터 갱신(INSERT, UPDATE, DELETE) 시 성능 저하를 초래할 수 있으므로 신중하게 설계해야 한다. 또한, 실행 계획을 분석하여 인덱스가 실제로 사용되고 있는지 확인하는 것이 중요하다.
쿼리 자체의 작성 방식을 최적화하는 것도 필수적이다. 불필요한 컬럼을 SELECT * 대신 명시적으로 나열하거나, 비효율적인 서브쿼리를 조인 연산으로 재작성할 수 있다. 집계 함수를 사용할 때는 가능한 한 애플리케이션 단이 아닌 데이터베이스 내에서 처리하도록 한다. 데이터 양이 많을 경우, 한 번에 모든 데이터를 가져오는 대신 페이징 처리를 적용하는 것도 효과적이다. 때로는 복잡한 단일 쿼리를 여러 개의 간단한 쿼리로 분리하거나, 반대로 여러 번 실행되는 쿼리를 하나로 통합하는 전략도 성능에 도움이 된다.
튜닝 기법 | 주요 내용 | 주의사항 |
|---|---|---|
인덱스 활용 | WHERE, JOIN, ORDER BY/GROUP BY 절 컬럼에 인덱스 생성, 복합 인덱스 컬럼 순서 고려 | 과도한 인덱스는 갱신 성능 저하 유발 |
쿼리 재작성 | 불필요한 조인/서브쿼리 제거, SELECT * 지양, IN 대신 EXISTS 활용 | 결과 정합성 유지가 전제 조건 |
조인 최적화 | 드라이빙 테이블 선정, 적절한 조인 방식(Nested Loop, Hash, Merge) 유도 | 통계 정보 최신 상태 유지 필요 |
실행 계획 분석 | 옵티마이저가 선택한 접근 경로 확인, 풀 테이블 스캔 구간 식별 | 데이터베이스별 도구(EXPLAIN 등) 사용 |
마지막으로, 데이터베이스의 옵티마이저가 최적의 경로를 선택할 수 있도록 돕는 것이 중요하다. 이를 위해 테이블과 인덱스에 대한 통계 정보가 정기적으로 갱신되어야 한다. 또한, 데이터베이스별로 제공하는 힌트(Hint) 구문을 사용하여 특정 인덱스 사용이나 조인 방식을 옵티마이저에 제안할 수 있지만, 이는 데이터 분포가 변경되면 오히려 역효과를 낼 수 있으므로 신중하게 적용해야 한다.
7. 주요 데이터베이스별 SQL 특징
7. 주요 데이터베이스별 SQL 특징
관계형 데이터베이스 관리 시스템 제품들은 ANSI SQL 표준을 준수하지만, 각 제품마다 고유한 확장 기능, 문법적 차이, 성능 특성을 가지고 있다. 이는 역사적 배경, 설계 철학, 목표 시장에 따라 다양하게 발전했기 때문이다.
주요 제품군별 특징은 다음과 같다.
데이터베이스 | 주요 특징 | 확장 SQL 방언 명칭 |
|---|---|---|
방대한 기능 세트, PL/SQL이라는 강력한 절차적 언어, ROWNUM 의사 컬럼, 계층형 쿼리(CONNECT BY) 지원 | PL/SQL | |
널리 사용되는 오픈소스 RDBMS, 단순하고 빠른 실행, MyISAM과 InnoDB 등 다양한 스토리지 엔진 지원 | - | |
고급 오픈소스 RDBMS, 표준 준수도가 높음, 풍부한 데이터 타입(예: JSON, 배열)과 확장성(예: PostGIS) 지원 | PL/pgSQL | |
Transact-SQL(T-SQL) 사용, Windows 환경과의 긴밀한 통합, TOP 절을 통한 행 수 제한, 공통 테이블 식(WITH 절) 강화 | T-SQL |
구문 차이의 대표적인 예로, 상위 N개 레코드를 선택하는 방법이 있다. Oracle은 SELECT * FROM table WHERE ROWNUM <= 10을 사용하는 반면, Microsoft SQL Server와 PostgreSQL은 SELECT TOP 10 * FROM table 또는 SELECT * FROM table LIMIT 10(PostgreSQL, MySQL)과 같은 방식을 사용한다[8]. 날짜 처리 함수도 제품마다 이름과 사용법이 상이하다. 예를 들어, 현재 날짜를 얻는 함수는 Oracle의 SYSDATE, SQL Server의 GETDATE(), MySQL의 NOW() 또는 CURDATE() 등으로 다양하다.
이러한 차이에도 불구하고, 기본적인 SELECT, INSERT, UPDATE, DELETE 문과 JOIN 구문은 표준을 크게 벗어나지 않아 학습의 이전이 가능하다. 그러나 성능 최적화를 위한 힌트 구문, 고급 분석 함수, 저장 프로시저 작성법 등은 각 데이터베이스의 매뉴얼을 참고해야 한다. 애플리케이션의 이식성을 고려한다면 가능한 한 표준 ANSI SQL 구문을 사용하고, 벤더 종속적인 확장 기능은 신중하게 도입하는 것이 바람직하다.
7.1. Oracle, MySQL, PostgreSQL
7.1. Oracle, MySQL, PostgreSQL
Oracle, MySQL, PostgreSQL은 각각 독특한 역사와 설계 철학을 바탕으로 발전했으며, 이는 SQL 구현과 확장 기능에서 뚜렷한 차이로 나타난다.
Oracle은 기업용 RDBMS 시장에서 오랜 기간 선도적 위치를 차지해왔다. 강력한 트랜잭션 처리와 데이터 일관성을 보장하는 기능에 중점을 두며, PL/SQL이라는 강력한 절차적 언어 확장을 제공한다. 고급 분석 함수, 윈도우 함수, 계층형 쿼리(CONNECT BY) 등 풍부한 기능을 자랑하며, 대용량 데이터베이스 환경에 최적화되어 있다. 라이선스 비용이 높은 상용 소프트웨어라는 점이 특징이다.
MySQL은 초기에는 속도와 단순함에 중점을 둔 경량 RDBMS로 시작해, Sun Microsystems와 이후 Oracle에 인수되면서 기능이 크게 확장되었다. 가장 널리 사용되는 오픈 소스 데이터베이스 중 하나로, LAMP 스택의 핵심 구성 요소이다. 기본 스토리지 엔진으로 MyISAM과 InnoDB를 제공하며, 5.7 버전 이후부터는 JSON 데이터 타입 지원, 윈도우 함수 등 현대적인 SQL 기능을 지속적으로 추가하고 있다. PostgreSQL에 비해 전통적으로 SQL 표준 준수보다는 실용성과 성능을 우선시하는 경향이 있었다.
PostgreSQL은 객체-관계형 데이터베이스 관리 시스템(ORDBMS)으로 분류되며, 엄격한 SQL 표준 준수와 확장성에 철학을 둔다. 다른 데이터베이스에서는 찾기 어려운 고급 데이터 타입(배열, hstore, JSONB, 기하학적 타입 등), 사용자 정의 타입, 연산자, 함수 생성 기능을 기본적으로 지원한다. 또한 MVCC 구현 방식이 매우 정교하며, 복잡한 쿼리와 분석 작업에 강점을 보인다. 모든 기능이 포함된 완전한 오픈 소스 소프트웨어라는 점이 큰 장점이다.
항목 | Oracle | MySQL | PostgreSQL |
|---|---|---|---|
주요 특징 | 기업용, 고가용성, PL/SQL | 널리 사용되는 오픈 소스, 실용적 | 표준 준수 높은 오픈 소스, 확장성 우수 |
기본 프로그래밍 확장 | PL/SQL | 저장 프로시저/SQL (기능 제한적) | PL/pgSQL |
대표적인 고유 구문 |
|
|
|
JSON 지원 | JSON 데이터 타입 (12c 이후) | JSON 데이터 타입 (5.7 이후) | 강력한 JSONB (이진 JSON) 타입 지원 |
라이선스 | 상용 (Enterprise Edition 등) | 이중 라이선스 (GPL/상용) | 완전한 오픈 소스 (PostgreSQL License) |
7.2. Microsoft SQL Server
7.2. Microsoft SQL Server
Microsoft SQL Server는 마이크로소프트가 개발한 관계형 데이터베이스 관리 시스템(RDBMS)이다. 주로 윈도우 서버 환경에서 운영되며, .NET 프레임워크와의 긴밀한 통합이 특징이다. Transact-SQL(T-SQL)이라는 자체 SQL 방언을 사용하며, 이는 표준 SQL에 프로시저적 확장 기능을 추가한 것이다. 기업용 애플리케이션, 비즈니스 인텔리전스(BI), 데이터 웨어하우징 분야에서 널리 사용된다.
주요 구성 요소로는 데이터베이스 엔진(SQL Server 데이터베이스 엔진) 외에도 SQL Server Reporting Services(SSRS), SQL Server Integration Services(SSIS), SQL Server Analysis Services(SSAS) 등이 포함되어 포괄적인 데이터 플랫폼을 제공한다. 최근 버전에서는 Linux 및 도커 컨테이너 지원, Azure 클라우드 서비스와의 하이브리드 기능 강화 등 개방형 플랫폼으로의 진화를 보여준다.
T-SQL은 다른 RDBMS와 구별되는 여러 기능을 제공한다. 저장 프로시저, 사용자 정의 함수, 트리거 작성에 강력한 절차적 언어 요소를 포함한다. 또한 TOP 절, OUTPUT 절, 공통 테이블 표현식(CTE) 및 윈도우 함수에 대한 풍부한 지원을 한다. 버전별로 지원하는 기능에 차이가 있어 주의가 필요하다.
특징 | 설명 |
|---|---|
주 사용 환경 | |
주요 SQL 방언 | Transact-SQL(T-SQL) |
통합 개발 도구 | |
주요 특징 |
관련 문서: Microsoft Docs - SQL Server
