SQLSQL 기초강의 8개 중 7번째난이도 입문

DDL과 인덱스 — 테이블 설계와 성능 최적화

발행 읽는 시간 약 2 분

  • SQL
  • DDL
  • CREATE TABLE
  • 인덱스
  • INDEX
  • 제약조건

강의 소개

CREATE TABLE로 테이블을 설계하고, 제약 조건으로 데이터 무결성을 보장하는 방법을 배웁니다. 인덱스로 쿼리 성능을 높이는 원리도 이해합니다.

CREATE TABLE 상세#

SQL
CREATE TABLE products (
    -- 기본키
    id          SERIAL PRIMARY KEY,

    -- NOT NULL: 반드시 값 있어야 함
    name        VARCHAR(200) NOT NULL,

    -- UNIQUE: 중복 불가
    sku         VARCHAR(50) UNIQUE NOT NULL,

    -- DEFAULT: 기본값
    price       INTEGER NOT NULL DEFAULT 0,
    is_active   BOOLEAN NOT NULL DEFAULT TRUE,

    -- CHECK: 조건 제약
    stock       INTEGER NOT NULL DEFAULT 0
                CHECK (stock >= 0),
    rating      DECIMAL(2,1) CHECK (rating >= 0 AND rating <= 5),

    -- 외래키
    category_id INTEGER REFERENCES categories(id)
                ON DELETE SET NULL,   -- 카테고리 삭제 시 NULL로

    -- 타임스탬프
    created_at  TIMESTAMP NOT NULL DEFAULT NOW(),
    updated_at  TIMESTAMP NOT NULL DEFAULT NOW()
);

데이터 타입#

타입예시설명
INTEGER / INT42정수
BIGINT9999999999큰 정수
SERIAL-자동 증가 정수
DECIMAL(p,s)9.99정확한 소수
FLOAT3.14부동소수점
VARCHAR(n)"철수"가변 길이 문자열
TEXT긴 텍스트길이 제한 없음
BOOLEANTRUE/FALSE참/거짓
DATE2026-04-21날짜
TIMESTAMP2026-04-21 14:00:00날짜+시간
JSONB키·값 쌍 (예: 문자열 키와 값)JSON (PostgreSQL)
UUID550e8400-...고유 식별자

ALTER TABLE: 테이블 수정#

SQL
-- 열 추가
ALTER TABLE products ADD COLUMN description TEXT;

-- 열 삭제
ALTER TABLE products DROP COLUMN description;

-- 열 타입 변경
ALTER TABLE products ALTER COLUMN price TYPE BIGINT;

-- 제약 추가
ALTER TABLE products ADD CONSTRAINT check_price CHECK (price >= 0);

-- 제약 삭제
ALTER TABLE products DROP CONSTRAINT check_price;

-- 열 이름 변경
ALTER TABLE products RENAME COLUMN sku TO product_code;

-- 테이블 이름 변경
ALTER TABLE products RENAME TO items;

인덱스: 검색 속도 향상#

인덱스가 없으면 조건에 맞는 행을 찾기 위해 전체 테이블을 읽는 경우가 많고, 적절한 인덱스가 있으면 인덱스만 따라가 원하는 행을 빠르게 찾을 수 있습니다.

구분인덱스 없음인덱스 있음
탐색 방식전체 테이블 스캔 (Full Table Scan)인덱스 스캔 (Index Scan 등)
대략적 특성테이블이 크면 행마다 확인검색·범위 조건에 유리하면 로그 시간에 가깝게
SQL
-- 단일 열 인덱스
CREATE INDEX idx_products_category ON products(category_id);
CREATE INDEX idx_employees_department ON employees(department);

-- 복합 인덱스 (자주 함께 쓰는 열)
CREATE INDEX idx_orders_customer_date ON orders(customer_id, created_at);

-- 유니크 인덱스
CREATE UNIQUE INDEX idx_users_email ON users(email);

-- 인덱스 목록 확인
SELECT indexname, indexdef FROM pg_indexes WHERE tablename = 'products';

-- 인덱스 삭제
DROP INDEX idx_products_category;

EXPLAIN: 실행 계획 확인#

SQL
-- 어떻게 쿼리가 실행되는지 확인
EXPLAIN SELECT * FROM employees WHERE department = '개발팀';

-- 실제 실행 통계 포함
EXPLAIN ANALYZE SELECT * FROM employees WHERE department = '개발팀';

-- 결과 예시
-- Seq Scan on employees (cost=0.00..1.06 rows=3 width=68)
-- Filter: ((department)::text = '개발팀'::text)
-- → 인덱스 없으면 Seq Scan (전체 탐색)

-- 인덱스 추가 후
-- Index Scan using idx_employees_department on employees
-- → Index Scan으로 개선됨

뷰 (View)#

자주 쓰는 복잡한 쿼리를 저장합니다.

SQL
-- 뷰 생성
CREATE VIEW active_employees AS
SELECT id, name, department, salary
FROM employees
WHERE is_active = TRUE;

-- 테이블처럼 사용
SELECT * FROM active_employees WHERE department = '개발팀';

-- 뷰 삭제
DROP VIEW active_employees;

정리#

DDL역할
CREATE TABLE테이블 생성
ALTER TABLE테이블 구조 변경
DROP TABLE테이블 삭제
CREATE INDEX인덱스 생성
CREATE VIEW뷰 생성

인덱스를 만들어야 할 때:

  • WHERE 절에 자주 등장하는 열
  • JOIN 연결 열 (외래키)
  • ORDER BY에 자주 쓰는 열

다음 편에서는 SQL 실전 패턴 — 실제 앱 개발에서 자주 만나는 쿼리 패턴을 배웁니다.

Follow · Ask · Work

이 글이 도움이 됐다면

짧은 작업 기록과 데모는 인스타그램에 올립니다. 만들고 싶은 것이 있다면 프로젝트 의뢰나 협업 제안도 편하게 보내 주세요.

글쓴이

파란여우

직접 만든 AI 앱·제품의 개발·배포를 공개하는 실전형 테크 크리에이터

파란여우 소개 Instagram @bluefox._.hi

이어서 보기

만들고 싶은 것이 있다면 프로젝트 의뢰로 알려 주세요.