본문 바로가기

학습/SQL

[SQL] TEMP TABLE vs 일반 테이블 vs WITH(CTE) vs VIEW 비교 정리

 

데이터베이스에서 복잡한 쿼리를 최적화하고 효율적으로 사용하기 위해  일반 테이블, TEMP TABLE(임시 테이블), WITH(CTE), VIEW(뷰) 를 활용할 수 있다.
각 방법마다 장단점이 다르기 때문에, 상황에 따라 적절한 방식을 선택하는 것이 중요하다!


✅ 일반 테이블이란?

일반 테이블은 데이터베이스에 영구적으로 저장되는 테이블이다.
모든 트랜잭션이 끝나도 데이터가 유지되며, INDEX를 사용할 수 있어 검색 성능이 좋다.

📌 일반 테이블이 필요한 이유

  • 데이터를 영구적으로 저장해야 할 때
  • INDEX를 활용해서 빠르게 조회해야 할 때
  • 여러 트랜잭션에서 데이터를 공유해야 할 때

예를 들어, 상품 데이터처럼 지속적으로 유지되어야 하는 정보

CREATE TABLE products ( 
product_id INT PRIMARY KEY, 
product_name VARCHAR(255), 
price DECIMAL(10,2) );

테이블을 생성하면, 해당 데이터는 데이터베이스에 영구적으로 저장됨


✅ TEMP TABLE(임시 테이블)이란?

TEMP TABLE(임시 테이블)은 특정 세션(Session)에서만 유지되는 테이블이다.
일반 테이블과 비슷하지만, 세션이 종료되면 자동으로 삭제된다.

 

📌 TEMP TABLE이 필요한 이유

  •  서브쿼리 결과를 여러 번 사용할 때
  • JOIN이 많거나 복잡한 연산을 최적화할 때
  • 동일한 데이터를 여러 번 조회할 때 성능 개선 가능

예를 들어, 고객별 첫 구매일을 여러 번 JOIN해야 하는 경우

  • WITH first_purchase AS (...) 사용 시 매번 데이터를 다시 계산해야 해서 비효율적
  • TEMP TABLE에 저장하면 한 번만 계산하고 여러 번 재사용 가능

✅ VIEW(뷰)란?

VIEW(뷰)는 실제 데이터를 저장하지 않는 가상 테이블이다.
미리 정의된 쿼리를 저장해두고, 필요할 때마다 실행해서 최신 데이터를 가져올 수 있다.

 

📌 VIEW가 필요한 이유

  • 복잡한 SQL을 단순화하고 쉽게 재사용할 때
  • 사용자에게 보안적으로 제한된 데이터를 제공할 때 (예: 특정 컬럼만 보여주기)
  • 매번 같은 쿼리를 반복해서 실행할 때

예를 들어, 주문 테이블과 고객 테이블을 매번 조인해서 분석하는 경우

  • SELECT o.order_id, c.customer_name FROM orders o JOIN customers c ...
  • VIEW를 생성하면 SELECT * FROM order_customer_view; 만 실행하면 됨!

✅ WITH(CTE, Common Table Expression)란?

WITH(CTE)는 SQL 실행 시 일시적으로 유지되는 가상의 테이블이다.
TEMP TABLE과 비슷하지만, TEMP TABLE처럼 데이터를 저장하지 않고 실행될 때만 유지된다.

 

📌 WITH(CTE)가 필요한 이유

  • 한 번만 사용할 데이터를 간결하게 정리할 때
  • 재귀 쿼리(Recursive Query)를 사용할 때
  • 서브쿼리보다 가독성을 높이고 싶을 때

예를 들어, 회원별 총 주문 수를 구하는 쿼리가 여러 번 사용될 때

WITH order_counts AS ( 
    SELECT customer_id, COUNT(order_id) AS total_orders 
    FROM orders GROUP BY customer_id 
) 
SELECT c.customer_name, oc.total_orders 
FROM customers c JOIN order_counts oc 
	ON c.customer_id = oc.customer_id;

order_counts를 WITH(CTE)로 만들어 재사용 가능


✅ TEMP TABLE vs 일반 테이블 vs WITH(CTE) vs VIEW 비교 표

구분 일반 테이블 TEMP TABLE
(임시 테이블)
WITH (CTE) VIEW (뷰)
데이터 저장 ✅ 영구 저장 ✅ 임시 저장 ❌ 저장 안됨 ❌ 저장 안됨 (가상 테이블)
유지 기간 ✅ 영구적 ❌ 세션 종료 시 삭제 ❌ 쿼리 실행 중에만 유지 ✅ 영구적
속도 ❌ 느릴 수 있음 (INDEX 없으면) ✅ 빠름 (한 번 생성 후 재사용) ⭕ 빠르지만 여러 번 실행 시 비효율적 ❌ 실행할 때마다 원본 테이블 조회
INDEX 사용 ✅ 가능 ✅ 가능 ❌ 불가능 ❌ 불가능 (뷰 자체에는 INDEX 추가 불가)
JOIN 사용 ✅ 가능 ✅ 가능 ✅ 가능 ✅ 가능하지만 성능 저하 가능
데이터 변경 가능 여부 ✅ 가능 ✅ 가능 ❌ 불가능 ❌ 불가능 (읽기 전용)
사용 목적 ✅ 영구적 데이터 저장 ✅ 속도 개선 ✅ 가독성 향상 ✅ 복잡한 쿼리 재사용

✅ 언제 어떤 방식을 사용해야 할까?

📌 일반 테이블이 더 좋은 경우

  • 데이터를 영구적으로 저장해야 할 때
  • INDEX를 활용해서 빠르게 조회해야 할 때
  • 여러 트랜잭션에서 데이터를 공유해야 할 때

📌 TEMP TABLE이 더 좋은 경우

  • JOIN이 많거나, 반복적으로 실행되는 쿼리를 최적화할 때
  • 서브쿼리 결과를 여러 번 재사용해야 할 때
  • 대량 데이터를 처리할 때 속도를 개선하고 싶을 때

📌 WITH(CTE)가 더 좋은 경우

  • 한 번만 사용할 데이터를 처리할 때
  • 쿼리를 단순화하고 가독성을 높이고 싶을 때
  • 재귀 쿼리(Recursive Query)를 사용할 때

📌 VIEW(뷰)가 더 좋은 경우

  • 복잡한 SQL 쿼리를 단순하게 만들어서 재사용하고 싶을 때
  • 원본 테이블의 데이터를 변형하지 않고, 최신 데이터를 조회해야 할 때

🔥 최종 정리

TEMP TABLE → "임시 저장소", 일반 테이블 → "영구 저장소"
WITH(CTE) → "실행할 때만 유지", VIEW → "미리 정의된 가상 테이블"
속도가 중요한 경우 TEMP TABLE을, 가독성이 중요한 경우 VIEW를 사용하면 좋다!